diff options
author | Minkyu Kang <mk7.kang@samsung.com> | 2010-05-31 09:13:11 +0900 |
---|---|---|
committer | Minkyu Kang <mk7.kang@samsung.com> | 2010-05-31 09:13:11 +0900 |
commit | 922d27b596c179c5a7d68abe45ede5adb1b6589c (patch) | |
tree | c5ef3d5dc70bf51646a7fd7a379f6c2b2588cc2e /arch/i386/lib | |
parent | de200874fb9ecac51d74b4e9783ebb5d2e94c449 (diff) | |
parent | 39c209546ab5b11ca6410c5cc57dcbf457e50800 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-arm
Conflicts:
arch/arm/include/asm/mach-types.h
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
Diffstat (limited to 'arch/i386/lib')
-rw-r--r-- | arch/i386/lib/bios_setup.c | 2 | ||||
-rw-r--r-- | arch/i386/lib/board.c | 85 | ||||
-rw-r--r-- | arch/i386/lib/realmode.c | 2 | ||||
-rw-r--r-- | arch/i386/lib/zimage.c | 127 |
4 files changed, 150 insertions, 66 deletions
diff --git a/arch/i386/lib/bios_setup.c b/arch/i386/lib/bios_setup.c index 6491e522ec4..a92b77ea237 100644 --- a/arch/i386/lib/bios_setup.c +++ b/arch/i386/lib/bios_setup.c @@ -141,7 +141,7 @@ static void setvector(int vector, u16 segment, void *handler) int bios_setup(void) { - ulong i386boot_bios = (ulong)&_i386boot_bios; + ulong i386boot_bios = (ulong)&_i386boot_bios + gd->reloc_off; ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; static int done=0; diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index f3b6348551e..3f849f6542d 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -37,6 +37,7 @@ #include <malloc.h> #include <net.h> #include <ide.h> +#include <serial.h> #include <asm/u-boot-i386.h> #include <elf.h> @@ -52,7 +53,9 @@ extern ulong _i386boot_rel_dyn_start; extern ulong _i386boot_rel_dyn_end; extern ulong _i386boot_bss_start; extern ulong _i386boot_bss_size; -void ram_bootstrap (void *); + +void ram_bootstrap (void *, ulong); + const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; @@ -147,7 +150,6 @@ static void display_flash_config (ulong size) typedef int (init_fnc_t) (void); init_fnc_t *init_sequence[] = { - serial_init, cpu_init_r, /* basic cpu dependent setup */ board_early_init_r, /* basic board dependent setup */ dram_init, /* configure available RAM banks */ @@ -162,6 +164,7 @@ init_fnc_t *init_sequence[] = { NULL, }; +static gd_t gd_data; gd_t *gd; /* @@ -174,21 +177,18 @@ void board_init_f (ulong stack_limit) Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start; Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end; void *bss_start = &_i386boot_bss_start; - void *bss_size = &_i386boot_bss_size; + ulong bss_size = (ulong)&_i386boot_bss_size; - size_t uboot_size; - void *ram_start; + ulong uboot_size; + void *dest_addr; ulong rel_offset; Elf32_Rel *re; - void (*start_func)(void *); - - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("": : :"memory"); + void (*start_func)(void *, ulong); - uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start; - ram_start = (void *)stack_limit - (uboot_size + (ulong)bss_size); - rel_offset = text_start - ram_start; + uboot_size = (ulong)u_boot_cmd_end - (ulong)text_start; + dest_addr = (void *)stack_limit - (uboot_size + (ulong)bss_size); + rel_offset = text_start - dest_addr; start_func = ram_bootstrap - rel_offset; /* First stage CPU initialization */ @@ -200,10 +200,10 @@ void board_init_f (ulong stack_limit) hang(); /* Copy U-Boot into RAM */ - memcpy(ram_start, text_start, (size_t)uboot_size); + memcpy(dest_addr, text_start, uboot_size); /* Clear BSS */ - memset(bss_start - rel_offset, 0, (size_t)bss_size); + memset(bss_start - rel_offset, 0, bss_size); /* Perform relocation adjustments */ for (re = rel_dyn_start; re < rel_dyn_end; re++) @@ -213,27 +213,39 @@ void board_init_f (ulong stack_limit) *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; } - start_func(ram_start); - - /* NOTREACHED - relocate_code() does not return */ + /* Enter the relocated U-Boot! */ + start_func(dest_addr, rel_offset); + /* NOTREACHED - board_init_f() does not return */ while(1); } /* - * All attempts to jump straight from board_init_f() to board_init_r() - * have failed, hence this special 'bootstrap' function. + * We cannot initialize gd_data in board_init_f() because we would be + * attempting to write to flash (I have even tried using manual relocation + * adjustments on pointers but it just won't work) and board_init_r() does + * not have enough arguments to allow us to pass the relocation offset + * straight up. This bootstrap function (which runs in RAM) is used to + * setup gd_data in order to pass the relocation offset to the rest of + * U-Boot. + * + * TODO: The compiler optimization barrier is intended to stop GCC from + * optimizing this function into board_init_f(). It seems to work without + * it, but I've left it in to be sure. I think also that the barrier in + * board_init_r() is no longer needed, but left it in 'just in case' */ -void ram_bootstrap (void *ram_start) +void ram_bootstrap (void *dest_addr, ulong rel_offset) { - static gd_t gd_data; - /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); - board_init_r(&gd_data, (ulong)ram_start); + /* tell others: relocation done */ + gd_data.reloc_off = rel_offset; + gd_data.flags |= GD_FLG_RELOC; + + board_init_r(&gd_data, (ulong)dest_addr); } -void board_init_r(gd_t *id, ulong ram_start) +void board_init_r(gd_t *id, ulong dest_addr) { char *s; int i; @@ -247,16 +259,13 @@ void board_init_r(gd_t *id, ulong ram_start) /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); - memset (gd, 0, sizeof (gd_t)); gd->bd = &bd_data; memset (gd->bd, 0, sizeof (bd_t)); show_boot_progress(0x22); gd->baudrate = CONFIG_BAUDRATE; - gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ - - mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3, + mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3, CONFIG_SYS_MALLOC_LEN); for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) { @@ -268,6 +277,9 @@ void board_init_r(gd_t *id, ulong ram_start) } show_boot_progress(0x23); +#ifdef CONFIG_SERIAL_MULTI + serial_initialize(); +#endif /* configure available FLASH banks */ size = flash_init(); display_flash_config(size); @@ -280,8 +292,10 @@ void board_init_r(gd_t *id, ulong ram_start) show_boot_progress(0x26); +#ifdef CONFIG_CMD_NET /* IP Address */ bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); +#endif #if defined(CONFIG_PCI) /* @@ -420,10 +434,17 @@ void hang (void) unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[]) { /* - * TODO: Test this function - changed to fix compiler error. - * Original code was: - * return (entry >> 1) (argc, argv); - * with a comment about Nios function pointers are address >> 1 + * x86 does not use a dedicated register to pass the pointer + * to the global_data */ + argv[-1] = (char *)gd; + return (entry) (argc, argv); } + +void setup_pcat_compatibility(void) + __attribute__((weak, alias("__setup_pcat_compatibility"))); + +void __setup_pcat_compatibility(void) +{ +} diff --git a/arch/i386/lib/realmode.c b/arch/i386/lib/realmode.c index 3c3c1fc961f..b3f51230a5b 100644 --- a/arch/i386/lib/realmode.c +++ b/arch/i386/lib/realmode.c @@ -37,7 +37,7 @@ extern char realmode_enter; int realmode_setup(void) { - ulong i386boot_realmode = (ulong)&_i386boot_realmode; + ulong i386boot_realmode = (ulong)&_i386boot_realmode + gd->reloc_off; ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* copy the realmode switch code */ diff --git a/arch/i386/lib/zimage.c b/arch/i386/lib/zimage.c index c3b4e597aab..b39615a3e25 100644 --- a/arch/i386/lib/zimage.c +++ b/arch/i386/lib/zimage.c @@ -34,6 +34,8 @@ #include <asm/zimage.h> #include <asm/realmode.h> #include <asm/byteorder.h> +#include <asm/bootparam.h> +#include <asm/ic/sc520.h> /* * Memory lay-out: @@ -90,48 +92,56 @@ void *load_zimage(char *image, unsigned long kernel_size, int big_image; void *load_address; + struct setup_header *hdr = (struct setup_header *)(image + SETUP_SECTS_OFF); setup_base = (void*)DEFAULT_SETUP_BASE; /* base address for real-mode segment */ - if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) { - printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n", - *(u16*)(image + BOOT_FLAG_OFF)); + if (KERNEL_MAGIC != hdr->boot_flag) { + printf("Error: Invalid Boot Flag (found 0x%04x, expected 0x%04x)\n", + hdr->boot_flag, KERNEL_MAGIC); return 0; + } else { + printf("Valid Boot Flag\n"); } - /* determine boot protocol version */ - if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) { - bootproto = *(u16*)(image+VERSION_OFF); + if (KERNEL_V2_MAGIC == hdr->header) { + printf("Magic signature found\n"); + + bootproto = hdr->version; } else { /* Very old kernel */ + printf("Magic signature not found\n"); bootproto = 0x0100; } /* determine size of setup */ - if (0 == *(u8*)(image + SETUP_SECTS_OFF)) { + if (0 == hdr->setup_sects) { + printf("Setup Sectors = 0 (defaulting to 4)\n"); setup_size = 5 * 512; } else { - setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512; + setup_size = (hdr->setup_sects + 1) * 512; } + printf("Setup Size = 0x%8.8lx\n", (ulong)setup_size); + if (setup_size > SETUP_MAX_SIZE) { printf("Error: Setup is too large (%d bytes)\n", setup_size); } /* Determine image type */ - big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG); + big_image = (bootproto >= 0x0200) && (hdr->loadflags & BIG_KERNEL_FLAG); - /* Derermine load address */ - load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR); + /* Determine load address */ + load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR : ZIMAGE_LOAD_ADDR); /* load setup */ + printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n", (ulong)setup_base, setup_size); memmove(setup_base, image, setup_size); printf("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); - if (bootproto == 0x0100) { *(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; @@ -154,48 +164,58 @@ void *load_zimage(char *image, unsigned long kernel_size, memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size); } + /* We are now setting up the real-mode version of the header */ + hdr = (struct setup_header *)(setup_base + SETUP_SECTS_OFF); + if (bootproto >= 0x0200) { - *(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff; - printf("Linux kernel version %s\n", - (char*)(setup_base + SETUP_START_OFFSET + - *(u16*)(setup_base + START_SYS_OFF + 2))); + hdr->type_of_loader = 8; + + if (hdr->setup_sects >= 15) + printf("Linux kernel version %s\n", (char *) + (setup_base + (hdr->kernel_version + 0x200))); + else + printf("Setup Sectors < 15 - Cannot print kernel version.\n"); if (initrd_addr) { printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n", initrd_addr, initrd_size); - *(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr; - *(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size; + hdr->ramdisk_image = initrd_addr; + hdr->ramdisk_size = initrd_size; } } if (bootproto >= 0x0201) { - *(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET; - - /* CAN_USE_HEAP */ - *(u8*)(setup_base + LOADFLAGS_OFF) = - *(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG; + hdr->heap_end_ptr = HEAP_END_OFFSET; + hdr->loadflags |= HEAP_FLAG; } if (bootproto >= 0x0202) { - *(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET; + hdr->cmd_line_ptr = (u32)setup_base + COMMAND_LINE_OFFSET; } else if (bootproto >= 0x0200) { + *(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; *(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; - *(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100; + + hdr->setup_move_size = 0x9100; } + if (bootproto >= 0x0204) + kernel_size = hdr->syssize * 16; + else + kernel_size -= setup_size; + if (big_image) { - if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) { + if ((kernel_size) > BZIMAGE_MAX_SIZE) { printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n", - kernel_size - setup_size, BZIMAGE_MAX_SIZE); + kernel_size, BZIMAGE_MAX_SIZE); return 0; } - } else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) { + } else if ((kernel_size) > ZIMAGE_MAX_SIZE) { printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", - kernel_size - setup_size, ZIMAGE_MAX_SIZE); + kernel_size, ZIMAGE_MAX_SIZE); return 0; } @@ -203,10 +223,10 @@ void *load_zimage(char *image, unsigned long kernel_size, build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot); printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ', - (u32)load_address, kernel_size - setup_size); + (u32)load_address, kernel_size); - memmove(load_address, image + setup_size, kernel_size - setup_size); + memmove(load_address, image + setup_size, kernel_size); /* ready for booting */ return setup_base; @@ -218,8 +238,51 @@ void boot_zimage(void *setup_base) memset(®s, 0, sizeof(struct pt_regs)); regs.xds = (u32)setup_base >> 4; - regs.xss = 0x9000; + regs.xes = regs.xds; + regs.xss = regs.xds; regs.esp = 0x9000; regs.eflags = 0; enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s); } + +int do_zboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + void *base_ptr; + void *bzImage_addr; + ulong bzImage_size = 0; + + disable_interrupts(); + + /* Setup board for maximum PC/AT Compatibility */ + setup_pcat_compatibility(); + + /* argv[1] holds the address of the bzImage */ + bzImage_addr = (void *)simple_strtoul(argv[1], NULL, 16); + + if (argc == 3) + bzImage_size = simple_strtoul(argv[2], NULL, 16); + + /* Lets look for*/ + base_ptr = load_zimage (bzImage_addr, bzImage_size, 0, 0, 0); + + if (NULL == base_ptr) { + printf ("## Kernel loading failed ...\n"); + } else { + printf ("## Transferring control to Linux (at address %08x) ...\n", + (u32)base_ptr); + + /* we assume that the kernel is in place */ + printf("\nStarting kernel ...\n\n"); + + boot_zimage(base_ptr); + /* does not return */ + } + + return -1; +} + +U_BOOT_CMD( + zboot, 3, 0, do_zboot, + "Boot bzImage", + "" +); |