1 /* $NetBSD: loader.c,v 1.4 2008/04/28 20:23:18 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libkern/libkern.h> 34 35 #include <lib/libsa/loadfile.h> 36 37 #include <machine/bootinfo.h> 38 39 #include "console.h" 40 #include "cmd.h" 41 #include "local.h" 42 43 void r4k_pdcache_wbinv_all(uint32_t); 44 void r4k_sdcache_wbinv_all(uint32_t, int); 45 void boot_usage(void); 46 47 int 48 cmd_jump(int argc, char *argp[], int interactive) 49 { 50 uint32_t addr; 51 uint32_t sp; 52 53 if (argc < 2) { 54 printf("jump jump_addr [stack_addr]\n"); 55 return 1; 56 } 57 addr = strtoul(argp[1], 0, 0); 58 if (argc == 3) 59 sp = strtoul(argp[2], 0, 0); 60 else 61 __asm volatile("move %0, $29" : "=r"(sp)); /* current stack */ 62 63 printf("jump to 0x%08x. sp=0x%08x Y/N\n", addr, sp); 64 if (prompt_yesno(interactive)) { 65 __asm volatile( 66 ".set noreorder;" 67 "jalr %0;" 68 "move $29, %1;" 69 ".set reorder" :: "r"(addr), "r"(sp)); 70 /* NOTREACHED */ 71 } else { 72 printf("canceled.\n"); 73 return 1; 74 } 75 76 return 0; 77 } 78 79 int 80 cmd_load_binary(int argc, char *argp[], int interactive) 81 { 82 extern uint8_t kernel_binary[]; 83 extern int kernel_binary_size; 84 extern char start[]; 85 uint8_t *p, *q; 86 int i, j; 87 88 if (argc < 2) { 89 printf("load load_addr\n"); 90 return 1; 91 } 92 93 if (kernel_binary_size == 0) { 94 printf("no kernel image\n"); 95 return 1; 96 } 97 98 q = (uint8_t *)strtoul(argp[1], 0, 0); 99 p = kernel_binary; 100 101 /* check load reagion */ 102 printf("load end=%p loader start=%p\n", 103 q + kernel_binary_size, start); 104 if ((uint32_t)(q + kernel_binary_size) >= (uint32_t)start) { 105 printf("kernel load area is overlapped with loader.\n"); 106 return 1; 107 } 108 109 printf("load kernel to %p %dbytes. Y/N\n", q, kernel_binary_size); 110 if (!prompt_yesno(interactive)) { 111 printf("canceled.\n"); 112 return 1; 113 } 114 115 j = kernel_binary_size / 30; 116 for (i = 0; i < kernel_binary_size; i ++) { 117 *q++ = *p++; 118 if ((i % j) == 0) 119 printf("loading kernel. %d/%dbytes\r", i, 120 kernel_binary_size); 121 } 122 r4k_pdcache_wbinv_all(PD_CACHE_SIZE); 123 r4k_sdcache_wbinv_all(SD_CACHE_SIZE, SD_CACHE_LINESIZE); 124 125 printf("loading kernel. %d/%d\r", i , kernel_binary_size); 126 printf("\ndone.\n"); 127 128 return 0; 129 } 130 131 int 132 cmd_boot_ux(int argc, char *argp[], int interactive) 133 { 134 u_long marks[MARK_MAX]; 135 uint32_t entry; 136 137 marks[MARK_START] = 0; 138 console_cursor(false); 139 if (loadfile("sd0d:iopboot", marks, LOAD_KERNEL) != 0) { 140 printf("load iopboot failed.\n"); 141 return 1; 142 } 143 printf("start=%lx entry=%lx nsym=%lx sym=%lx end=%lx\n", 144 marks[MARK_START], marks[MARK_ENTRY], marks[MARK_NSYM], 145 marks[MARK_SYM], marks[MARK_END]); 146 147 entry = marks[MARK_ENTRY]; 148 printf("jump to iopboot entry.(0x%x) Y/N\n", entry); 149 150 r4k_pdcache_wbinv_all(PD_CACHE_SIZE); 151 r4k_sdcache_wbinv_all(SD_CACHE_SIZE, SD_CACHE_LINESIZE); 152 153 if (prompt_yesno(interactive)) { 154 __asm volatile( 155 ".set noreorder;" 156 "lw $4, %1;" 157 "lw $2, %2;" 158 "lw $3, %3;" 159 "jr %0;" 160 "move $29, %0;" 161 ".set reorder" 162 :: "r"(entry), 163 "m"(ipl_args.a0), 164 "m"(ipl_args.v0), 165 "m"(ipl_args.v1)); 166 /* NOTREACHED */ 167 } 168 console_cursor(true); 169 170 return 0; 171 } 172 173 int 174 cmd_boot(int argc, char *argp[], int interactive) 175 { 176 u_long marks[MARK_MAX]; 177 uint32_t entry; 178 struct bootinfo bi; 179 char *filename; 180 181 if (argc < 2) { 182 boot_usage(); 183 return 1; 184 } else { 185 filename = argp[1]; 186 } 187 188 marks[MARK_START] = 0; 189 console_cursor(false); 190 if (loadfile(filename, marks, LOAD_KERNEL) != 0) { 191 printf("load file failed.\n"); 192 return 1; 193 } 194 printf("start=%lx entry=%lx nsym=%lx sym=%lx end=%lx\n", 195 marks[MARK_START], marks[MARK_ENTRY], marks[MARK_NSYM], 196 marks[MARK_SYM], marks[MARK_END]); 197 198 entry = marks[MARK_ENTRY]; 199 printf("jump to kernel entry.(0x%x)%s\n", entry, 200 interactive ? " Y/N" : ""); 201 202 /* Setup argument */ 203 bi.bi_version = 0x1; 204 bi.bi_size = sizeof bi; 205 bi.bi_nsym = marks[MARK_NSYM]; 206 bi.bi_ssym = (uint8_t *)marks[MARK_SYM]; 207 bi.bi_esym = (uint8_t *)marks[MARK_END]; 208 bi.bi_mainfo = ipl_args.v1; 209 210 r4k_pdcache_wbinv_all(PD_CACHE_SIZE); 211 r4k_sdcache_wbinv_all(SD_CACHE_SIZE, SD_CACHE_LINESIZE); 212 213 if (prompt_yesno(interactive)) { 214 __asm volatile( 215 ".set noreorder;" 216 "lw $4, %1;" 217 "lw $5, %2;" 218 "la $6, %3;" 219 "jr %0;" 220 "move $29, %0;" 221 ".set reorder" 222 :: "r"(entry), "m"(argc), "m"(argp), "m"(bi)); 223 /* NOTREACHED */ 224 } 225 console_cursor(true); 226 227 return 0; 228 } 229 230 void 231 r4k_pdcache_wbinv_all(uint32_t pdcache_size) 232 { 233 uint32_t va = 0x80000000; 234 uint32_t eva = va + pdcache_size; 235 236 while (va < eva) { 237 __asm volatile( 238 ".set noreorder;" 239 ".set mips3;" 240 "cache %1, 0x000(%0); cache %1, 0x010(%0);" 241 "cache %1, 0x020(%0); cache %1, 0x030(%0);" 242 "cache %1, 0x040(%0); cache %1, 0x050(%0);" 243 "cache %1, 0x060(%0); cache %1, 0x070(%0);" 244 "cache %1, 0x080(%0); cache %1, 0x090(%0);" 245 "cache %1, 0x0a0(%0); cache %1, 0x0b0(%0);" 246 "cache %1, 0x0c0(%0); cache %1, 0x0d0(%0);" 247 "cache %1, 0x0e0(%0); cache %1, 0x0f0(%0);" 248 "cache %1, 0x100(%0); cache %1, 0x110(%0);" 249 "cache %1, 0x120(%0); cache %1, 0x130(%0);" 250 "cache %1, 0x140(%0); cache %1, 0x150(%0);" 251 "cache %1, 0x160(%0); cache %1, 0x170(%0);" 252 "cache %1, 0x180(%0); cache %1, 0x190(%0);" 253 "cache %1, 0x1a0(%0); cache %1, 0x1b0(%0);" 254 "cache %1, 0x1c0(%0); cache %1, 0x1d0(%0);" 255 "cache %1, 0x1e0(%0); cache %1, 0x1f0(%0);" 256 ".set reorder" 257 : : "r" (va), "i" (1 |(0 << 2)) : "memory"); 258 va += (32 * 16); 259 } 260 } 261 262 void 263 r4k_sdcache_wbinv_all(uint32_t sdcache_size, int line_size) 264 { 265 uint32_t va = 0x80000000; 266 uint32_t eva = va + sdcache_size; 267 268 while (va < eva) { 269 __asm volatile( 270 ".set noreorder;" 271 ".set mips3;" 272 "cache %1, 0(%0);" 273 ".set reorder" 274 : : "r" (va), "i" (3 |(0 << 2)) : "memory"); 275 va += line_size; 276 } 277 } 278 279 void 280 boot_usage(void) 281 { 282 283 printf("boot dev:filename [argument to kernel]\n"); 284 printf("\tex).\n"); 285 printf("\t Disk 0, Partition 10, /netbsd => sd0k:netbsd\n"); 286 printf("\t NFS, /netbsd => nfs:netbsd\n"); 287 printf("\t `kernel embeded in data section' => mem:\n"); 288 } 289