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 ulong rd_len; 54 ulong initrd_start, initrd_end; 55 int ret; 56 57 ulong cmd_start, cmd_end; 58 bd_t *kbd; 59 void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); 60 struct lmb *lmb = &images->lmb; 61 62 /* 63 * allow the PREP bootm subcommand, it is required for bootm to work 64 */ 65 if (flag & BOOTM_STATE_OS_PREP) 66 return 0; 67 68 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 69 return 1; 70 71 /* allocate space for kernel copy of board info */ 72 ret = boot_get_kbd (lmb, &kbd); 73 if (ret) { 74 puts("ERROR with allocation of kernel bd\n"); 75 goto error; 76 } 77 set_clocks_in_mhz(kbd); 78 79 ret = image_setup_linux(images); 80 if (ret) 81 goto error; 82 83 kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))images->ep; 84 85 debug("## Transferring control to Linux (at address %08lx) ...\n", 86 (ulong) kernel); 87 88 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 89 90 /* 91 * Linux Kernel Parameters (passing board info data): 92 * sp+00: Ignore, side effect of using jsr to jump to kernel 93 * sp+04: ptr to board info data 94 * sp+08: initrd_start or 0 if no initrd 95 * sp+12: initrd_end - unused if initrd_start is 0 96 * sp+16: Start of command line string 97 * sp+20: End of command line string 98 */ 99 (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); 100 /* does not return */ 101 error: 102 return 1; 103 } 104 105 static ulong get_sp (void) 106 { 107 ulong sp; 108 109 asm("movel %%a7, %%d0\n" 110 "movel %%d0, %0\n": "=d"(sp): :"%d0"); 111 112 return sp; 113 } 114 115 static void set_clocks_in_mhz (bd_t *kbd) 116 { 117 char *s; 118 119 if ((s = getenv("clocks_in_mhz")) != NULL) { 120 /* convert all clock information to MHz */ 121 kbd->bi_intfreq /= 1000000L; 122 kbd->bi_busfreq /= 1000000L; 123 } 124 } 125