1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2003 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7#include <bootm.h> 8#include <bootstage.h> 9#include <command.h> 10#include <env.h> 11#include <image.h> 12#include <lmb.h> 13#include <log.h> 14#include <asm/global_data.h> 15#include <u-boot/zlib.h> 16#include <bzlib.h> 17#include <watchdog.h> 18#include <asm/byteorder.h> 19#ifdef CONFIG_SHOW_BOOT_PROGRESS 20# include <status_led.h> 21#endif 22 23DECLARE_GLOBAL_DATA_PTR; 24 25#define PHYSADDR(x) x 26 27#define LINUX_MAX_ENVS 256 28#define LINUX_MAX_ARGS 256 29 30static ulong get_sp (void); 31static void set_clocks_in_mhz (struct bd_info *kbd); 32 33void arch_lmb_reserve(struct lmb *lmb) 34{ 35 arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 1024); 36} 37 38int do_bootm_linux(int flag, struct bootm_info *bmi) 39{ 40 struct bootm_headers *images = bmi->images; 41 int ret; 42 struct bd_info *kbd; 43 void (*kernel) (struct bd_info *, ulong, ulong, ulong, ulong); 44 struct lmb *lmb = &images->lmb; 45 46 /* 47 * allow the PREP bootm subcommand, it is required for bootm to work 48 */ 49 if (flag & BOOTM_STATE_OS_PREP) 50 return 0; 51 52 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 53 return 1; 54 55 /* allocate space for kernel copy of board info */ 56 ret = boot_get_kbd (lmb, &kbd); 57 if (ret) { 58 puts("ERROR with allocation of kernel bd\n"); 59 goto error; 60 } 61 set_clocks_in_mhz(kbd); 62 63 if (IS_ENABLED(CONFIG_LMB)) { 64 ret = image_setup_linux(images); 65 if (ret) 66 goto error; 67 } 68 69 kernel = (void (*)(struct bd_info *, ulong, ulong, ulong, ulong))images->ep; 70 71 debug("## Transferring control to Linux (at address %08lx) ...\n", 72 (ulong) kernel); 73 74 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 75 76 /* 77 * Linux Kernel Parameters (passing board info data): 78 * sp+00: Ignore, side effect of using jsr to jump to kernel 79 * sp+04: ptr to board info data 80 * sp+08: initrd_start or 0 if no initrd 81 * sp+12: initrd_end - unused if initrd_start is 0 82 * sp+16: Start of command line string 83 * sp+20: End of command line string 84 */ 85 (*kernel)(kbd, images->initrd_start, images->initrd_end, 86 images->cmdline_start, images->cmdline_end); 87 /* does not return */ 88error: 89 return 1; 90} 91 92static ulong get_sp (void) 93{ 94 ulong sp; 95 96 asm("movel %%a7, %%d0\n" 97 "movel %%d0, %0\n": "=d"(sp): :"%d0"); 98 99 return sp; 100} 101 102static void set_clocks_in_mhz (struct bd_info *kbd) 103{ 104 char *s; 105 106 s = env_get("clocks_in_mhz"); 107 if (s) { 108 /* convert all clock information to MHz */ 109 kbd->bi_intfreq /= 1000000L; 110 kbd->bi_busfreq /= 1000000L; 111 } 112} 113