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