1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2007 Michal Simek 4 * (C) Copyright 2004 Atmark Techno, Inc. 5 * 6 * Michal SIMEK <monstr@monstr.eu> 7 * Yasushi SHOJI <yashi@atmark-techno.com> 8 */ 9 10#include <bootm.h> 11#include <bootstage.h> 12#include <command.h> 13#include <cpu_func.h> 14#include <env.h> 15#include <fdt_support.h> 16#include <hang.h> 17#include <image.h> 18#include <lmb.h> 19#include <log.h> 20#include <asm/cache.h> 21#include <asm/global_data.h> 22#include <u-boot/zlib.h> 23#include <asm/byteorder.h> 24 25DECLARE_GLOBAL_DATA_PTR; 26 27static ulong get_sp(void) 28{ 29 ulong ret; 30 31 asm("addik %0, r1, 0" : "=r"(ret) : ); 32 return ret; 33} 34 35void arch_lmb_reserve(struct lmb *lmb) 36{ 37 arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096); 38} 39 40static void boot_jump_linux(struct bootm_headers *images, int flag) 41{ 42 void (*thekernel)(char *cmdline, ulong rd, ulong dt); 43 ulong dt = (ulong)images->ft_addr; 44 ulong rd_start = images->initrd_start; 45 ulong cmdline = images->cmdline_start; 46 int fake = (flag & BOOTM_STATE_OS_FAKE_GO); 47 48 thekernel = (void (*)(char *, ulong, ulong))images->ep; 49 50 debug("## Transferring control to Linux (at address 0x%08lx) ", 51 (ulong)thekernel); 52 debug("cmdline 0x%08lx, ramdisk 0x%08lx, FDT 0x%08lx...\n", 53 cmdline, rd_start, dt); 54 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 55 56 printf("\nStarting kernel ...%s\n\n", fake ? 57 "(fake run for tracing)" : ""); 58 bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); 59 60 flush_cache_all(); 61 62 if (!fake) { 63 /* 64 * Linux Kernel Parameters (passing device tree): 65 * r5: pointer to command line 66 * r6: pointer to ramdisk 67 * r7: pointer to the fdt, followed by the board info data 68 */ 69 thekernel((char *)cmdline, rd_start, dt); 70 /* does not return */ 71 } 72} 73 74static void boot_prep_linux(struct bootm_headers *images) 75{ 76 if (CONFIG_IS_ENABLED(OF_LIBFDT) && IS_ENABLED(CONFIG_LMB) && images->ft_len) { 77 debug("using: FDT\n"); 78 if (image_setup_linux(images)) { 79 printf("FDT creation failed! hanging..."); 80 hang(); 81 } 82 } 83} 84 85int do_bootm_linux(int flag, struct bootm_info *bmi) 86{ 87 struct bootm_headers *images = bmi->images; 88 89 images->cmdline_start = (ulong)env_get("bootargs"); 90 91 /* cmdline init is the part of 'prep' and nothing to do for 'bdt' */ 92 if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) 93 return -1; 94 95 if (flag & BOOTM_STATE_OS_PREP) { 96 boot_prep_linux(images); 97 return 0; 98 } 99 100 if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { 101 boot_jump_linux(images, flag); 102 return 0; 103 } 104 105 boot_prep_linux(images); 106 boot_jump_linux(images, flag); 107 return 1; 108} 109