X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Fx86%2Flib%2Fboard.c;h=a240d261716e7c203726a6c155304537a1cc341f;hb=b843f3119339a5ab18d0c0fbff788093deaaed3f;hp=8963580808650c2334a4c03e480908dade98bad2;hpb=f5ca20c6b60acfce81f45a0a0a92a5e72de5b008;p=oweals%2Fu-boot.git diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 8963580808..a240d26171 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -42,29 +42,12 @@ #include #include #include +#include #ifdef CONFIG_BITBANGMII #include #endif -/* - * Pointer to initial global data area - * - * Here we initialize it. - */ -#undef XTRN_DECLARE_GLOBAL_DATA_PTR -#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ -DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); - - -/* Exports from the Linker Script */ -extern ulong __text_start; -extern ulong __data_end; -extern ulong __rel_dyn_start; -extern ulong __rel_dyn_end; -extern ulong __bss_start; -extern ulong __bss_end; - /************************************************************************ * Init Utilities * ************************************************************************ @@ -72,49 +55,41 @@ extern ulong __bss_end; * or dropped completely, * but let's get it working (again) first... */ -static int init_baudrate (void) +static int init_baudrate(void) { gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); return 0; } -static int display_banner (void) +static int display_banner(void) { - printf ("\n\n%s\n\n", version_string); -/* - printf ("U-Boot code: %08lX -> %08lX data: %08lX -> %08lX\n" - " BSS: %08lX -> %08lX stack: %08lX -> %08lX\n", - i386boot_start, i386boot_romdata_start-1, - i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1, - i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1, - i386boot_bss_start+i386boot_bss_size, - i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1); - -*/ + printf("\n\n%s\n\n", version_string); - return (0); + return 0; } -static int display_dram_config (void) +static int display_dram_config(void) { int i; - puts ("DRAM Configuration:\n"); + puts("DRAM Configuration:\n"); - for (i=0; ibd->bi_dram[i].start); - print_size (gd->bd->bi_dram[i].size, "\n"); + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); + print_size(gd->bd->bi_dram[i].size, "\n"); } - return (0); + return 0; } -static void display_flash_config (ulong size) +#ifndef CONFIG_SYS_NO_FLASH +static void display_flash_config(ulong size) { - puts ("Flash: "); - print_size (size, "\n"); + puts("Flash: "); + print_size(size, "\n"); } +#endif /* * Breath some life into the board... @@ -145,6 +120,7 @@ static int calculate_relocation_address(void); static int copy_uboot_to_ram(void); static int clear_bss(void); static int do_elf_reloc_fixups(void); +static int copy_gd_to_ram(void); init_fnc_t *init_sequence_f[] = { cpu_init_f, @@ -155,9 +131,6 @@ init_fnc_t *init_sequence_f[] = { console_init_f, dram_init_f, calculate_relocation_address, - copy_uboot_to_ram, - clear_bss, - do_elf_reloc_fixups, NULL, }; @@ -174,50 +147,57 @@ init_fnc_t *init_sequence_r[] = { NULL, }; -gd_t *gd; - static int calculate_relocation_address(void) { - void *text_start = &__text_start; - void *bss_end = &__bss_end; - void *dest_addr; - ulong rel_offset; + ulong text_start = (ulong)&__text_start; + ulong bss_end = (ulong)&__bss_end; + ulong dest_addr; + + /* + * NOTE: All destination address are rounded down to 16-byte + * boundary to satisfy various worst-case alignment + * requirements + */ - /* Calculate destination RAM Address and relocation offset */ - dest_addr = (void *)gd->ram_size; + /* Global Data is at top of available memory */ + dest_addr = gd->ram_size; + dest_addr -= GENERATED_GBL_DATA_SIZE; + dest_addr &= ~15; + gd->new_gd_addr = dest_addr; + + /* GDT is below Global Data */ + dest_addr -= X86_GDT_SIZE; + dest_addr &= ~15; + gd->gdt_addr = dest_addr; + + /* Stack is below GDT */ + gd->start_addr_sp = dest_addr; + + /* U-Boot is below the stack */ dest_addr -= CONFIG_SYS_STACK_SIZE; dest_addr -= (bss_end - text_start); - rel_offset = dest_addr - text_start; - - gd->start_addr_sp = gd->ram_size; - gd->relocaddr = (ulong)dest_addr; - gd->reloc_off = rel_offset; + dest_addr &= ~15; + gd->relocaddr = dest_addr; + gd->reloc_off = (dest_addr - text_start); return 0; } static int copy_uboot_to_ram(void) { - ulong *dst_addr = (ulong *)gd->relocaddr; - ulong *src_addr = (ulong *)&__text_start; - ulong *end_addr = (ulong *)&__data_end; + size_t len = (size_t)&__data_end - (size_t)&__text_start; - while (src_addr < end_addr) - *dst_addr++ = *src_addr++; + memcpy((void *)gd->relocaddr, (void *)&__text_start, len); return 0; } static int clear_bss(void) { - void *bss_start = &__bss_start; - void *bss_end = &__bss_end; + ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; + size_t len = (size_t)&__bss_end - (size_t)&__bss_start; - ulong *dst_addr = (ulong *)(bss_start + gd->reloc_off); - ulong *end_addr = (ulong *)(bss_end + gd->reloc_off);; - - while (dst_addr < end_addr) - *dst_addr++ = 0x00000000; + memset((void *)dst_addr, 0x00, len); return 0; } @@ -227,10 +207,30 @@ static int do_elf_reloc_fixups(void) Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); + Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_ram; + + /* The size of the region of u-boot that runs out of RAM. */ + uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; + do { - if (re_src->r_offset >= CONFIG_SYS_TEXT_BASE) - if (*(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) >= CONFIG_SYS_TEXT_BASE) - *(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) += gd->reloc_off; + /* Get the location from the relocation entry */ + offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; + + /* Check that the location of the relocation is in .text */ + if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + + /* Switch to the in-RAM version */ + offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + + gd->reloc_off); + + /* Check that the target points into .text */ + if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && + *offset_ptr_ram < + (CONFIG_SYS_TEXT_BASE + size)) { + *offset_ptr_ram += gd->reloc_off; + } + } } while (re_src++ < re_end); return 0; @@ -248,34 +248,88 @@ void board_init_f(ulong boot_flags) hang(); } - gd->flags |= GD_FLG_RELOC; + /* + * SDRAM is now initialised, U-Boot has been copied into SDRAM, + * the BSS has been cleared etc. The final stack can now be setup + * in SDRAM. Code execution will continue (momentarily) in Flash, + * but with the stack in SDRAM and Global Data in temporary memory + * (CPU cache) + */ + board_init_f_r_trampoline(gd->start_addr_sp); + + /* NOTREACHED - board_init_f_r_trampoline() does not return */ + while (1) + ; +} + +void board_init_f_r(void) +{ + if (copy_gd_to_ram() != 0) + hang(); - /* Enter the relocated U-Boot! */ - relocate_code(gd->start_addr_sp, gd, gd->relocaddr); + if (init_cache() != 0) + hang(); - /* NOTREACHED - relocate_code() does not return */ - while(1); + copy_uboot_to_ram(); + clear_bss(); + do_elf_reloc_fixups(); + + /* + * Transfer execution from Flash to RAM by calculating the address + * of the in-RAM copy of board_init_r() and calling it + */ + (board_init_r + gd->reloc_off)(gd, gd->relocaddr); + + /* NOTREACHED - board_init_r() does not return */ + while (1) + ; +} + +static int copy_gd_to_ram(void) +{ + gd_t *ram_gd; + + /* + * Global data is still in temporary memory (the CPU cache). + * calculate_relocation_address() has set gd->new_gd_addr to + * where the global data lives in RAM but getting it there + * safely is a bit tricky due to the 'F-Segment Hack' that + * we need to use for x86 + */ + ram_gd = (gd_t *)gd->new_gd_addr; + memcpy((void *)ram_gd, gd, sizeof(gd_t)); + + /* + * Reload the Global Descriptor Table so FS points to the + * in-RAM copy of Global Data (calculate_relocation_address() + * has already calculated the in-RAM location of the GDT) + */ + ram_gd->gd_addr = (ulong)ram_gd; + init_gd(ram_gd, (u64 *)gd->gdt_addr); + + return 0; } void board_init_r(gd_t *id, ulong dest_addr) { +#if defined(CONFIG_CMD_NET) char *s; +#endif +#ifndef CONFIG_SYS_NO_FLASH ulong size; +#endif static bd_t bd_data; - static gd_t gd_data; init_fnc_t **init_fnc_ptr; show_boot_progress(0x21); - /* Global data pointer is now writable */ - gd = &gd_data; - memcpy(gd, id, sizeof(gd_t)); - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("": : :"memory"); + __asm__ __volatile__("" : : : "memory"); + + gd->flags |= GD_FLG_RELOC; gd->bd = &bd_data; - memset (gd->bd, 0, sizeof (bd_t)); + memset(gd->bd, 0, sizeof(bd_t)); show_boot_progress(0x22); gd->baudrate = CONFIG_BAUDRATE; @@ -285,28 +339,31 @@ void board_init_r(gd_t *id, ulong dest_addr) for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) - hang (); + hang(); } show_boot_progress(0x23); #ifdef CONFIG_SERIAL_MULTI serial_initialize(); #endif + +#ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */ size = flash_init(); display_flash_config(size); show_boot_progress(0x24); +#endif show_boot_progress(0x25); /* initialize environment */ - env_relocate (); + env_relocate(); show_boot_progress(0x26); #ifdef CONFIG_CMD_NET /* IP Address */ - bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); + bd_data.bi_ip_addr = getenv_IPaddr("ipaddr"); #endif #if defined(CONFIG_PCI) @@ -319,9 +376,9 @@ void board_init_r(gd_t *id, ulong dest_addr) show_boot_progress(0x27); - stdio_init (); + stdio_init(); - jumptable_init (); + jumptable_init(); /* Initialize the console (after the relocation and devices init) */ console_init_r(); @@ -333,7 +390,7 @@ void board_init_r(gd_t *id, ulong dest_addr) #if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) WATCHDOG_RESET(); - puts ("PCMCIA:"); + puts("PCMCIA:"); pcmcia_init(); #endif @@ -348,7 +405,7 @@ void board_init_r(gd_t *id, ulong dest_addr) show_boot_progress(0x28); #ifdef CONFIG_STATUS_LED - status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING); + status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); #endif udelay(20); @@ -356,9 +413,10 @@ void board_init_r(gd_t *id, ulong dest_addr) /* Initialize from environment */ load_addr = getenv_ulong("loadaddr", 16, load_addr); #if defined(CONFIG_CMD_NET) - if ((s = getenv ("bootfile")) != NULL) { - copy_filename (BootFile, s, sizeof (BootFile)); - } + s = getenv("bootfile"); + + if (s != NULL) + copy_filename(BootFile, s, sizeof(BootFile)); #endif WATCHDOG_RESET(); @@ -390,10 +448,10 @@ void board_init_r(gd_t *id, ulong dest_addr) eth_initialize(gd->bd); #endif -#if ( defined(CONFIG_CMD_NET)) && (0) +#if (defined(CONFIG_CMD_NET)) && (0) WATCHDOG_RESET(); # ifdef DEBUG - puts ("Reset Ethernet PHY\n"); + puts("Reset Ethernet PHY\n"); # endif reset_phy(); #endif @@ -410,27 +468,27 @@ void board_init_r(gd_t *id, ulong dest_addr) #ifdef CONFIG_POST - post_run (NULL, POST_RAM | post_bootmode_get(0)); + post_run(NULL, POST_RAM | post_bootmode_get(0)); #endif - show_boot_progress(0x29); /* main_loop() can return to retry autoboot, if so just run it again. */ - for (;;) { + for (;;) main_loop(); - } /* NOTREACHED - no way out of command loop except booting */ } -void hang (void) +void hang(void) { - puts ("### ERROR ### Please RESET the board ###\n"); - for (;;); + puts("### ERROR ### Please RESET the board ###\n"); + for (;;) + ; } -unsigned long do_go_exec (ulong (*entry)(int, char * const []), int argc, char * const argv[]) +unsigned long do_go_exec(ulong (*entry)(int, char * const []), + int argc, char * const argv[]) { unsigned long ret = 0; char **argv_tmp;