prom.c
来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 1,048 行 · 第 1/2 页
C
1,048 行
M_LEON2 | M_LEON2_SOC, /* machine type */ {0, 0, 0, 0, 0, 0}, /* eth */ 0, /* date */ 0, /* sernum */ 0, /* checksum */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */ }, { __va(no_nextnode), __va(no_child), __va(no_proplen), __va(no_getprop), __va(no_setprop), __va(no_nextprop) }, __va(&spi.totphys), { NULL, (char *)CFG_SDRAM_BASE, 0, }, __va(&spi.avail), { NULL, (char *)CFG_SDRAM_BASE, 0, }, NULL, /* prommap_p */ NULL, __va(&spi.bootargs), { {NULL, __va(spi.arg), NULL /*... */ }, /*... */ }, { 0, 0, /* sun4c v0 prom */ 0, 0, {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)}, __va(&spi.nodeops), NULL, {NULL /* ... */ }, NULL, NULL, NULL, NULL, /* pv_getchar, pv_putchar */ __va(leon_nbgetchar), __va(leon_nbputchar), NULL, __va(leon_reboot), NULL, NULL, NULL, __va(leon_halt), __va(&spi.synchook), {NULL}, __va(&spi.bootargs_p) /*... */ }, { {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }, {0, __va(spi.root_properties)}, /* cpu 0, must be spi.nodes[2] see leon_prom_init() */ {1, __va(spi.cpu_properties)},#undef CPUENTRY#define CPUENTRY(idx) \ {1, __va(spi.cpu_properties##idx) } /* cpu <idx> */ CPUENTRY(1), CPUENTRY(2), CPUENTRY(3), CPUENTRY(4), CPUENTRY(5), CPUENTRY(6), CPUENTRY(7), CPUENTRY(8), CPUENTRY(9), CPUENTRY(10), CPUENTRY(11), CPUENTRY(12), CPUENTRY(13), CPUENTRY(14), CPUENTRY(15), CPUENTRY(16), CPUENTRY(17), CPUENTRY(18), CPUENTRY(19), CPUENTRY(20), CPUENTRY(21), CPUENTRY(22), CPUENTRY(23), CPUENTRY(24), CPUENTRY(25), CPUENTRY(26), CPUENTRY(27), CPUENTRY(28), CPUENTRY(29), CPUENTRY(30), CPUENTRY(31), {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ } }, "device_type", "cpu", "mid", "idprom", "compatability", "leon2", "mmu-nctx", "clock-frequency", "uart1_baud", "uart2_baud", CONFIG_DEFAULT_KERNEL_COMMAND_LINE};/* from arch/sparc/kernel/setup.c */#define RAMDISK_LOAD_FLAG 0x4000extern unsigned short root_flags;extern unsigned short root_dev;extern unsigned short ram_flags;extern unsigned int sparc_ramdisk_image;extern unsigned int sparc_ramdisk_size;extern int root_mountflags;extern char initrd_end, initrd_start;/* Reboot the CPU = jump to beginning of flash again. * * Make sure that all function are inlined here. */static void PROM_TEXT leon_reboot(char *bcommand){ register char *arg = bcommand; void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); /* get physical address */ struct leon_prom_info *pspi = (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); unsigned int *srmmu_ctx_table; /* Turn of Interrupts */ set_pil(0xf); /* Set kernel's context, context zero */ srmmu_set_context(0); /* Get physical address of the MMU shutdown routine */ reboot_physical = (void *) SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); /* Now that we know the physical address of the function * we can make the MMU allow jumping to it. */ srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); /* get physical address of kernel's context table (assume ptd) */ srmmu_ctx_table = (unsigned int *) (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); /* enable access to physical address of MMU shutdown function */ SPARC_BYPASS_WRITE(&srmmu_ctx_table [((unsigned int)reboot_physical) >> 24], (((unsigned int)reboot_physical & 0xff000000) >> 4) | 0x1e); /* flush TLB cache */ leon_flush_tlb_all(); /* flash instruction & data cache */ sparc_icache_flush_all(); sparc_dcache_flush_all(); /* jump to physical address function * so that when the MMU is disabled * we can continue to execute */ reboot_physical(arg);}static void PROM_TEXT leon_reboot_physical(char *bcommand){ void __attribute__ ((noreturn)) (*reset) (void); /* Turn off MMU */ srmmu_set_mmureg(0); /* Hardcoded start address */ reset = CFG_MONITOR_BASE; /* flush data cache */ sparc_dcache_flush_all(); /* flush instruction cache */ sparc_icache_flush_all(); /* Jump to start in Flash */ reset();}static void PROM_TEXT leon_halt(void){ while (1) ;}/* get single char, don't care for blocking*/static int PROM_TEXT leon_nbgetchar(void){ return -1;}/* put single char, don't care for blocking*/static int PROM_TEXT leon_nbputchar(int c){ LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; /***** put char in buffer... *********** * Make sure all functions are inline! * ***************************************/ /* Wait for last character to go. */ while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) & LEON2_UART_STAT_THE)) ; /* Send data */ SPARC_BYPASS_WRITE(&leon2->UART_Channel_1, c); /* Wait for data to be sent */ while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) & LEON2_UART_STAT_TSE)) ; return 0;}/* node ops *//*#define nodes ((struct node *)__va(&pspi->nodes))*/#define nodes ((struct node *)(pspi->nodes))static int PROM_TEXT no_nextnode(int node){ /* get physical address */ struct leon_prom_info *pspi = (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); if (nodes[node].level == nodes[node + 1].level) return node + 1; return -1;}static int PROM_TEXT no_child(int node){ /* get physical address */ struct leon_prom_info *pspi = (struct leon_prom_info *) (CFG_PROM_OFFSET + sizeof(srmmu_tables)); /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); if (nodes[node].level == nodes[node + 1].level - 1) return node + 1; return -1;}static struct property PROM_TEXT *find_property(int node, char *name){ /* get physical address */ struct leon_prom_info *pspi = (struct leon_prom_info *) (CFG_PROM_OFFSET + sizeof(srmmu_tables)); /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); struct property *prop = &nodes[node].properties[0]; while (prop && prop->name) { if (pspi->reloc_funcs.strcmp(prop->name, name) == 0) return prop; prop++; } return NULL;}static int PROM_TEXT no_proplen(int node, char *name){ /* get physical address */ struct leon_prom_info *pspi = (struct leon_prom_info *) (CFG_PROM_OFFSET + sizeof(srmmu_tables)); /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); struct property *prop = pspi->reloc_funcs.find_property(node, name); if (prop) return prop->length; return -1;}static int PROM_TEXT no_getprop(int node, char *name, char *value){ /* get physical address */ struct leon_prom_info *pspi = (struct leon_prom_info *) (CFG_PROM_OFFSET + sizeof(srmmu_tables)); /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); struct property *prop = pspi->reloc_funcs.find_property(node, name); if (prop) { pspi->reloc_funcs.memcpy(value, prop->value, prop->length); return 1; } return -1;}static int PROM_TEXT no_setprop(int node, char *name, char *value, int len){ return -1;}static char PROM_TEXT *no_nextprop(int node, char *name){ /* get physical address */ struct leon_prom_info *pspi = (struct leon_prom_info *) (CFG_PROM_OFFSET + sizeof(srmmu_tables)); struct property *prop; /* convert into virtual address */ pspi = (struct leon_prom_info *) (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); if (!name || !name[0]) return nodes[node].properties[0].name; prop = pspi->reloc_funcs.find_property(node, name); if (prop) return prop[1].name; return NULL;}static int PROM_TEXT leon_strcmp(const char *s1, const char *s2){ register char result; while (1) { result = *s1 - *s2; if (result || !*s1) break; s2++; s1++; } return result;}static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n){ char *dst = (char *)dest, *source = (char *)src; while (n--) { *dst = *source; dst++; source++; } return dest;}#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp))void leon_prom_init(struct leon_prom_info *pspi){ unsigned long i; unsigned char cksum, *ptr; char *addr_str, *end; unsigned long sp; GETREGSP(sp); pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000; /* Set Available main memory size */ pspi->totphys.num_bytes = CFG_PROM_OFFSET - CFG_SDRAM_BASE; pspi->avail.num_bytes = pspi->totphys.num_bytes;#undef nodes pspi->nodes[3].level = -1; pspi->nodes[3].properties = __va(spi.root_properties + 3); /* Set Ethernet MAC address from environment */ if ((addr_str = getenv("ethaddr")) != NULL) { for (i = 0; i < 6; i++) { pspi->idprom.id_ethaddr[i] = addr_str ? simple_strtoul(addr_str, &end, 16) : 0; if (addr_str) { addr_str = (*end) ? end + 1 : end; } } } else { /* HW Address not found in environment, * Set default HW address */ pspi->idprom.id_ethaddr[0] = 0; pspi->idprom.id_ethaddr[1] = 0; pspi->idprom.id_ethaddr[2] = 0; pspi->idprom.id_ethaddr[3] = 0; pspi->idprom.id_ethaddr[4] = 0; pspi->idprom.id_ethaddr[5] = 0; } ptr = (unsigned char *)&pspi->idprom; for (i = cksum = 0; i <= 0x0E; i++) cksum ^= *ptr++; pspi->idprom.id_cksum = cksum;}static inline void set_cache(unsigned long regval){ asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory");}extern unsigned short bss_start, bss_end;/* mark as section .img.main.text, to be referenced in linker script */int prom_init(void){ struct leon_prom_info *pspi = (void *) ((((unsigned int)&spi) & PROM_SIZE_MASK) + CFG_PROM_OFFSET); /* disable mmu */ srmmu_set_mmureg(0x00000000); __asm__ __volatile__("flush\n\t"); /* init prom info struct */ leon_prom_init(pspi); kernel_arg_promvec = &pspi->romvec;#ifdef PRINT_ROM_VEC printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec));#endif return 0;}/* Copy current kernel boot argument to ROMvec */void prepare_bootargs(char *bootargs){ struct leon_prom_info *pspi; char *src, *dst; int left; /* if no bootargs set, skip copying ==> default bootline */ if (bootargs && (*bootargs != '\0')) { pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) + CFG_PROM_OFFSET); src = bootargs; dst = &pspi->arg[0]; left = 255; /* max len */ while (*src && left > 0) { *dst++ = *src++; left--; } /* terminate kernel command line string */ *dst = 0; }}void srmmu_init_cpu(unsigned int entry){ sparc_srmmu_setup *psrmmu_tables = (void *) ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) + CFG_PROM_OFFSET); /* Make context 0 (kernel's context) point * to our prepared memory mapping */#define PTD 1 psrmmu_tables->ctx_table[0] = ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD; /* Set virtual kernel address 0xf0000000 * to SRAM/SDRAM address. * Make it READ/WRITE/EXEC to SuperUser */#define PTE 2#define ACC_SU_ALL 0x1c psrmmu_tables->pgd_table[0xf0] = (CFG_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf1] = ((CFG_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf2] = ((CFG_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf3] = ((CFG_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf4] = ((CFG_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf5] = ((CFG_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf6] = ((CFG_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE; psrmmu_tables->pgd_table[0xf7] = ((CFG_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE; /* convert rom vec pointer to virtual address */ kernel_arg_promvec = (struct linux_romvec *) (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000); /* Set Context pointer to point to context table * 256 contexts supported. */ srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]); /* Set kernel's context, context zero */ srmmu_set_context(0); /* Invalidate all Cache */ __asm__ __volatile__("flush\n\t"); srmmu_set_mmureg(0x00000001); leon_flush_tlb_all(); leon_flush_cache_all();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?