diff options
Diffstat (limited to 'arch/x86/lib/bootm.c')
-rw-r--r-- | arch/x86/lib/bootm.c | 151 |
1 files changed, 116 insertions, 35 deletions
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index ff158dd..4c5c7f5 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -10,80 +10,161 @@ #include <common.h> #include <command.h> +#include <fdt_support.h> #include <image.h> #include <u-boot/zlib.h> #include <asm/bootparam.h> #include <asm/byteorder.h> #include <asm/zimage.h> +#ifdef CONFIG_SYS_COREBOOT +#include <asm/arch/timestamp.h> +#endif #define COMMAND_LINE_OFFSET 0x9000 -/*cmd_boot.c*/ -int do_bootm_linux(int flag, int argc, char * const argv[], - bootm_headers_t *images) +/* + * Implement a weak default function for boards that optionally + * need to clean up the system before jumping to the kernel. + */ +__weak void board_final_cleanup(void) { - struct boot_params *base_ptr = NULL; - ulong os_data, os_len; - image_header_t *hdr; - void *load_address; +} -#if defined(CONFIG_FIT) - const void *data; - size_t len; +void bootm_announce_and_cleanup(void) +{ + printf("\nStarting kernel ...\n\n"); + +#ifdef CONFIG_SYS_COREBOOT + timestamp_add_now(TS_U_BOOT_START_KERNEL); +#endif + bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); +#ifdef CONFIG_BOOTSTAGE_REPORT + bootstage_report(); #endif + board_final_cleanup(); +} - if (flag & BOOTM_STATE_OS_PREP) - return 0; - if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) - return 1; +#if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL) +int arch_fixup_memory_node(void *blob) +{ + bd_t *bd = gd->bd; + int bank; + u64 start[CONFIG_NR_DRAM_BANKS]; + u64 size[CONFIG_NR_DRAM_BANKS]; + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start[bank] = bd->bi_dram[bank].start; + size[bank] = bd->bi_dram[bank].size; + } + + return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); +} +#endif +/* Subcommand: PREP */ +static int boot_prep_linux(bootm_headers_t *images) +{ + char *cmd_line_dest = NULL; + image_header_t *hdr; + int is_zimage = 0; + void *data = NULL; + size_t len; + int ret; + +#ifdef CONFIG_OF_LIBFDT + if (images->ft_len) { + debug("using: FDT\n"); + if (image_setup_linux(images)) { + puts("FDT creation failed! hanging..."); + hang(); + } + } +#endif if (images->legacy_hdr_valid) { hdr = images->legacy_hdr_os; if (image_check_type(hdr, IH_TYPE_MULTI)) { + ulong os_data, os_len; + /* if multi-part image, we need to get first subimage */ image_multi_getimg(hdr, 0, &os_data, &os_len); + data = (void *)os_data; + len = os_len; } else { /* otherwise get image data */ - os_data = image_get_data(hdr); - os_len = image_get_data_size(hdr); + data = (void *)image_get_data(hdr); + len = image_get_data_size(hdr); } + is_zimage = 1; #if defined(CONFIG_FIT) - } else if (images->fit_uname_os) { - int ret; - + } else if (images->fit_uname_os && is_zimage) { ret = fit_image_get_data(images->fit_hdr_os, - images->fit_noffset_os, &data, &len); + images->fit_noffset_os, + (const void **)&data, &len); if (ret) { puts("Can't get image data/size!\n"); goto error; } - os_data = (ulong)data; - os_len = (ulong)len; + is_zimage = 1; #endif - } else { - puts("Could not find kernel image!\n"); - goto error; } -#ifdef CONFIG_CMD_ZBOOT - base_ptr = load_zimage((void *)os_data, os_len, &load_address); -#endif + if (is_zimage) { + void *load_address; + char *base_ptr; - if (NULL == base_ptr) { - printf("## Kernel loading failed ...\n"); + base_ptr = (char *)load_zimage(data, len, &load_address); + images->os.load = (ulong)load_address; + cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET; + images->ep = (ulong)base_ptr; + } else if (images->ep) { + cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET; + } else { + printf("## Kernel loading failed (no setup) ...\n"); goto error; } - if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, + printf("Setup at %#08lx\n", images->ep); + ret = setup_zimage((void *)images->ep, cmd_line_dest, 0, images->rd_start, - images->rd_end - images->rd_start)) { + images->rd_end - images->rd_start); + + if (ret) { printf("## Setting up boot parameters failed ...\n"); - goto error; + return 1; } - boot_zimage(base_ptr, load_address); - /* does not return */ + return 0; error: return 1; } + +/* Subcommand: GO */ +static int boot_jump_linux(bootm_headers_t *images) +{ + debug("## Transferring control to Linux (at address %08lx, kernel %08lx) ...\n", + images->ep, images->os.load); + + boot_zimage((struct boot_params *)images->ep, (void *)images->os.load); + /* does not return */ + + return 1; +} + +int do_bootm_linux(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + /* No need for those on x86 */ + if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) + return -1; + + if (flag & BOOTM_STATE_OS_PREP) + return boot_prep_linux(images); + + if (flag & BOOTM_STATE_OS_GO) { + boot_jump_linux(images); + return 0; + } + + return boot_jump_linux(images); +} |