1fea25720SGraeme Russ /* 2fea25720SGraeme Russ * (C) Copyright 2002 3fea25720SGraeme Russ * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 4fea25720SGraeme Russ * Marius Groeger <mgroeger@sysgo.de> 5fea25720SGraeme Russ * 6fea25720SGraeme Russ * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) 7fea25720SGraeme Russ * 81a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 9fea25720SGraeme Russ */ 10fea25720SGraeme Russ 11fea25720SGraeme Russ #include <common.h> 12fea25720SGraeme Russ #include <command.h> 13*0d0ba59cSSimon Glass #include <fdt_support.h> 14fea25720SGraeme Russ #include <image.h> 15fea25720SGraeme Russ #include <u-boot/zlib.h> 1669370d14SGabe Black #include <asm/bootparam.h> 17fea25720SGraeme Russ #include <asm/byteorder.h> 18fea25720SGraeme Russ #include <asm/zimage.h> 19*0d0ba59cSSimon Glass #ifdef CONFIG_SYS_COREBOOT 20*0d0ba59cSSimon Glass #include <asm/arch/timestamp.h> 21*0d0ba59cSSimon Glass #endif 22fea25720SGraeme Russ 2369370d14SGabe Black #define COMMAND_LINE_OFFSET 0x9000 2469370d14SGabe Black 25*0d0ba59cSSimon Glass /* 26*0d0ba59cSSimon Glass * Implement a weak default function for boards that optionally 27*0d0ba59cSSimon Glass * need to clean up the system before jumping to the kernel. 28*0d0ba59cSSimon Glass */ 29*0d0ba59cSSimon Glass __weak void board_final_cleanup(void) 30fea25720SGraeme Russ { 31*0d0ba59cSSimon Glass } 32fea25720SGraeme Russ 33*0d0ba59cSSimon Glass void bootm_announce_and_cleanup(void) 34*0d0ba59cSSimon Glass { 35*0d0ba59cSSimon Glass printf("\nStarting kernel ...\n\n"); 36*0d0ba59cSSimon Glass 37*0d0ba59cSSimon Glass #ifdef CONFIG_SYS_COREBOOT 38*0d0ba59cSSimon Glass timestamp_add_now(TS_U_BOOT_START_KERNEL); 39*0d0ba59cSSimon Glass #endif 40*0d0ba59cSSimon Glass bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); 41*0d0ba59cSSimon Glass #ifdef CONFIG_BOOTSTAGE_REPORT 42*0d0ba59cSSimon Glass bootstage_report(); 43*0d0ba59cSSimon Glass #endif 44*0d0ba59cSSimon Glass board_final_cleanup(); 45*0d0ba59cSSimon Glass } 46*0d0ba59cSSimon Glass 47*0d0ba59cSSimon Glass #if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL) 48*0d0ba59cSSimon Glass int arch_fixup_memory_node(void *blob) 49*0d0ba59cSSimon Glass { 50*0d0ba59cSSimon Glass bd_t *bd = gd->bd; 51*0d0ba59cSSimon Glass int bank; 52*0d0ba59cSSimon Glass u64 start[CONFIG_NR_DRAM_BANKS]; 53*0d0ba59cSSimon Glass u64 size[CONFIG_NR_DRAM_BANKS]; 54*0d0ba59cSSimon Glass 55*0d0ba59cSSimon Glass for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { 56*0d0ba59cSSimon Glass start[bank] = bd->bi_dram[bank].start; 57*0d0ba59cSSimon Glass size[bank] = bd->bi_dram[bank].size; 58*0d0ba59cSSimon Glass } 59*0d0ba59cSSimon Glass 60*0d0ba59cSSimon Glass return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); 61*0d0ba59cSSimon Glass } 62fea25720SGraeme Russ #endif 63fea25720SGraeme Russ 64*0d0ba59cSSimon Glass /* Subcommand: PREP */ 65*0d0ba59cSSimon Glass static int boot_prep_linux(bootm_headers_t *images) 66*0d0ba59cSSimon Glass { 67*0d0ba59cSSimon Glass char *cmd_line_dest = NULL; 68*0d0ba59cSSimon Glass image_header_t *hdr; 69*0d0ba59cSSimon Glass int is_zimage = 0; 70*0d0ba59cSSimon Glass void *data = NULL; 71*0d0ba59cSSimon Glass size_t len; 72*0d0ba59cSSimon Glass int ret; 73fea25720SGraeme Russ 74*0d0ba59cSSimon Glass #ifdef CONFIG_OF_LIBFDT 75*0d0ba59cSSimon Glass if (images->ft_len) { 76*0d0ba59cSSimon Glass debug("using: FDT\n"); 77*0d0ba59cSSimon Glass if (image_setup_linux(images)) { 78*0d0ba59cSSimon Glass puts("FDT creation failed! hanging..."); 79*0d0ba59cSSimon Glass hang(); 80*0d0ba59cSSimon Glass } 81*0d0ba59cSSimon Glass } 82*0d0ba59cSSimon Glass #endif 83fea25720SGraeme Russ if (images->legacy_hdr_valid) { 84fea25720SGraeme Russ hdr = images->legacy_hdr_os; 85fea25720SGraeme Russ if (image_check_type(hdr, IH_TYPE_MULTI)) { 86*0d0ba59cSSimon Glass ulong os_data, os_len; 87*0d0ba59cSSimon Glass 88fea25720SGraeme Russ /* if multi-part image, we need to get first subimage */ 89fea25720SGraeme Russ image_multi_getimg(hdr, 0, &os_data, &os_len); 90*0d0ba59cSSimon Glass data = (void *)os_data; 91*0d0ba59cSSimon Glass len = os_len; 92fea25720SGraeme Russ } else { 93fea25720SGraeme Russ /* otherwise get image data */ 94*0d0ba59cSSimon Glass data = (void *)image_get_data(hdr); 95*0d0ba59cSSimon Glass len = image_get_data_size(hdr); 96fea25720SGraeme Russ } 97*0d0ba59cSSimon Glass is_zimage = 1; 98fea25720SGraeme Russ #if defined(CONFIG_FIT) 99*0d0ba59cSSimon Glass } else if (images->fit_uname_os && is_zimage) { 100fea25720SGraeme Russ ret = fit_image_get_data(images->fit_hdr_os, 101*0d0ba59cSSimon Glass images->fit_noffset_os, 102*0d0ba59cSSimon Glass (const void **)&data, &len); 103fea25720SGraeme Russ if (ret) { 104fea25720SGraeme Russ puts("Can't get image data/size!\n"); 105fea25720SGraeme Russ goto error; 106fea25720SGraeme Russ } 107*0d0ba59cSSimon Glass is_zimage = 1; 108fea25720SGraeme Russ #endif 109*0d0ba59cSSimon Glass } 110*0d0ba59cSSimon Glass 111*0d0ba59cSSimon Glass if (is_zimage) { 112*0d0ba59cSSimon Glass void *load_address; 113*0d0ba59cSSimon Glass char *base_ptr; 114*0d0ba59cSSimon Glass 115*0d0ba59cSSimon Glass base_ptr = (char *)load_zimage(data, len, &load_address); 116*0d0ba59cSSimon Glass images->os.load = (ulong)load_address; 117*0d0ba59cSSimon Glass cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET; 118*0d0ba59cSSimon Glass images->ep = (ulong)base_ptr; 119*0d0ba59cSSimon Glass } else if (images->ep) { 120*0d0ba59cSSimon Glass cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET; 121fea25720SGraeme Russ } else { 122*0d0ba59cSSimon Glass printf("## Kernel loading failed (no setup) ...\n"); 123fea25720SGraeme Russ goto error; 124fea25720SGraeme Russ } 125fea25720SGraeme Russ 126*0d0ba59cSSimon Glass printf("Setup at %#08lx\n", images->ep); 127*0d0ba59cSSimon Glass ret = setup_zimage((void *)images->ep, cmd_line_dest, 12869370d14SGabe Black 0, images->rd_start, 129*0d0ba59cSSimon Glass images->rd_end - images->rd_start); 130*0d0ba59cSSimon Glass 131*0d0ba59cSSimon Glass if (ret) { 13269370d14SGabe Black printf("## Setting up boot parameters failed ...\n"); 133*0d0ba59cSSimon Glass return 1; 134fea25720SGraeme Russ } 135fea25720SGraeme Russ 136*0d0ba59cSSimon Glass return 0; 137fea25720SGraeme Russ 138fea25720SGraeme Russ error: 139fea25720SGraeme Russ return 1; 140fea25720SGraeme Russ } 141*0d0ba59cSSimon Glass 142*0d0ba59cSSimon Glass /* Subcommand: GO */ 143*0d0ba59cSSimon Glass static int boot_jump_linux(bootm_headers_t *images) 144*0d0ba59cSSimon Glass { 145*0d0ba59cSSimon Glass debug("## Transferring control to Linux (at address %08lx, kernel %08lx) ...\n", 146*0d0ba59cSSimon Glass images->ep, images->os.load); 147*0d0ba59cSSimon Glass 148*0d0ba59cSSimon Glass boot_zimage((struct boot_params *)images->ep, (void *)images->os.load); 149*0d0ba59cSSimon Glass /* does not return */ 150*0d0ba59cSSimon Glass 151*0d0ba59cSSimon Glass return 1; 152*0d0ba59cSSimon Glass } 153*0d0ba59cSSimon Glass 154*0d0ba59cSSimon Glass int do_bootm_linux(int flag, int argc, char * const argv[], 155*0d0ba59cSSimon Glass bootm_headers_t *images) 156*0d0ba59cSSimon Glass { 157*0d0ba59cSSimon Glass /* No need for those on x86 */ 158*0d0ba59cSSimon Glass if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) 159*0d0ba59cSSimon Glass return -1; 160*0d0ba59cSSimon Glass 161*0d0ba59cSSimon Glass if (flag & BOOTM_STATE_OS_PREP) 162*0d0ba59cSSimon Glass return boot_prep_linux(images); 163*0d0ba59cSSimon Glass 164*0d0ba59cSSimon Glass if (flag & BOOTM_STATE_OS_GO) { 165*0d0ba59cSSimon Glass boot_jump_linux(images); 166*0d0ba59cSSimon Glass return 0; 167*0d0ba59cSSimon Glass } 168*0d0ba59cSSimon Glass 169*0d0ba59cSSimon Glass return boot_jump_linux(images); 170*0d0ba59cSSimon Glass } 171