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