1 1.38 phx /* $NetBSD: loadbsd.c,v 1.38 2023/05/14 16:13:05 phx Exp $ */ 2 1.15 cgd 3 1.7 chopps /* 4 1.12 chopps * Copyright (c) 1994 Michael L. Hitch 5 1.12 chopps * All rights reserved. 6 1.12 chopps * 7 1.12 chopps * Redistribution and use in source and binary forms, with or without 8 1.12 chopps * modification, are permitted provided that the following conditions 9 1.12 chopps * are met: 10 1.12 chopps * 1. Redistributions of source code must retain the above copyright 11 1.12 chopps * notice, this list of conditions and the following disclaimer. 12 1.12 chopps * 2. Redistributions in binary form must reproduce the above copyright 13 1.12 chopps * notice, this list of conditions and the following disclaimer in the 14 1.12 chopps * documentation and/or other materials provided with the distribution. 15 1.12 chopps * 16 1.12 chopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.12 chopps * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.12 chopps * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.12 chopps * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.12 chopps * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.12 chopps * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.12 chopps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.12 chopps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.12 chopps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.12 chopps * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.7 chopps */ 27 1.7 chopps 28 1.30 jklos #include <errno.h> 29 1.1 mw #include <stdio.h> 30 1.30 jklos #include <stdlib.h> 31 1.30 jklos #include <string.h> 32 1.12 chopps #include <stdarg.h> 33 1.30 jklos 34 1.30 jklos #include <exec/memory.h> 35 1.1 mw #include <exec/execbase.h> 36 1.10 chopps #include <exec/resident.h> 37 1.12 chopps #include <graphics/gfxbase.h> 38 1.30 jklos #include <libraries/expansion.h> 39 1.30 jklos #include <libraries/expansionbase.h> 40 1.1 mw #include <libraries/configregs.h> 41 1.12 chopps #include <libraries/configvars.h> 42 1.30 jklos #include <proto/expansion.h> 43 1.30 jklos #include <proto/graphics.h> 44 1.30 jklos #include <proto/exec.h> 45 1.30 jklos #include <proto/dos.h> 46 1.1 mw 47 1.3 mw /* Get definitions for boothowto */ 48 1.30 jklos #include "sys/reboot.h" 49 1.30 jklos #include "inttypes.h" 50 1.30 jklos #include "loadfile.h" 51 1.3 mw 52 1.29 thorpej #undef AOUT_LDPGSZ 53 1.29 thorpej #define AOUT_LDPGSZ 8192 54 1.1 mw 55 1.30 jklos #undef sleep 56 1.30 jklos #define sleep(n) if (!t_flag) (void)Delay(50*n) 57 1.6 chopps 58 1.9 chopps /* 59 1.9 chopps * Version history: 60 1.19 mhitch * 1.x Kernel startup interface version check. 61 1.10 chopps * 2.0 Added symbol table end address and symbol table support. 62 1.10 chopps * 2.1 03/23/94 - Round up end of fastram segment. 63 1.10 chopps * Check fastram segment size for minimum of 2M. 64 1.10 chopps * Use largest segment of highest priority if -p option. 65 1.10 chopps * Print out fastram size in KB if not a multiple of MB. 66 1.10 chopps * 2.2 03/24/94 - Zero out all unused registers. 67 1.10 chopps * Started version history comment. 68 1.10 chopps * 2.3 04/26/94 - Added -D option to enter debugger on boot. 69 1.10 chopps * 2.4 04/30/94 - Cpuid includes base machine type. 70 1.10 chopps * Also check if CPU is capable of running NetBSD. 71 1.11 chopps * 2.5 05/17/94 - Add check for "A3000 bonus". 72 1.11 chopps * 2.6 06/05/94 - Added -c option to override machine type. 73 1.12 chopps * 2.7 06/15/94 - Pass E clock frequency. 74 1.13 chopps * 2.8 06/22/94 - Fix supervisor stack usage. 75 1.14 chopps * 2.9 06/26/94 - Use PAL flag for E clock freq on pre 2.0 WB 76 1.14 chopps * Added AGA enable parameter 77 1.16 chopps * 2.10 12/22/94 - Use FindResident() & OpenResource() for machine 78 1.16 chopps * type detection. 79 1.16 chopps * Add -n flag & option for non-contiguous memory. 80 1.16 chopps * 01/28/95 - Corrected -n on usage & help messages. 81 1.17 jtc * 2.11 03/12/95 - Check kernel size against chip memory size. 82 1.17 jtc * 2.12 11/11/95 - Add -I option to inhibit synchronous transfer 83 1.19 mhitch * 11/12/95 - New kernel startup interface version - to 84 1.19 mhitch * support loading kernel image to fastmem rather than chipmem. 85 1.19 mhitch * 2.13 04/15/96 - Direct load to fastmem. 86 1.19 mhitch * Add -Z flag to force chipmem load. 87 1.19 mhitch * Moved test mode exit to later - kernel image is created 88 1.19 mhitch * and startup interface version checked in test mode. 89 1.19 mhitch * Add -s flag for compatibility to bootblock loader. 90 1.19 mhitch * 05/02/96 - Add a maximum startup interface version level 91 1.20 is * to allow future kernel compatibility. 92 1.20 is * 2.14 06/26/96 is - Add first version of kludges needed to 93 1.20 is * boot on DraCos. This can probably be done a bit more cleanly 94 1.20 is * using TTRs, but it works for now. 95 1.21 is * 2.15 07/28/96 is - Add first version of kludges needed to 96 1.21 is * get FusionForty kickrom'd memory back. Hope this doesn't 97 1.21 is * break anything else. 98 1.30 jklos * 2.16 07/08/00 - Added bootverbose support. 99 1.30 jklos * 01/15/03 - Plugged resource leaks. 100 1.30 jklos * Fixed printf() statements. 101 1.30 jklos * Ansified. 102 1.30 jklos * 3.0 01/16/03 - ELF support through loadfile() interface. 103 1.37 phx * 3.1 07/10/11 - Added a serial console flag 104 1.37 phx * 11/18/15 - (gnikl) Added detection of A600. 105 1.37 phx * Fix handling of multiple -n options. 106 1.37 phx * 3.2 09/02/22 - Make it compile with modern AmigaOS gcc ports. 107 1.38 phx * 3.3 01/04/22 - Loading the kernel to the highest priority memory 108 1.38 phx * segment is the default now. New option -l to revert to the 109 1.38 phx * previous behaviour of largest segment. 110 1.38 phx * New option -M to define a minimum size for the memory segment. 111 1.9 chopps */ 112 1.38 phx static const char _version[] = "$VER: LoadBSD 3.3 (01.04.2023)"; 113 1.9 chopps 114 1.12 chopps /* 115 1.19 mhitch * Kernel startup interface version 116 1.12 chopps * 1: first version of loadbsd 117 1.12 chopps * 2: needs esym location passed in a4 118 1.19 mhitch * 3: load kernel image into fastmem rather than chipmem 119 1.19 mhitch * MAX: highest version with backward compatibility. 120 1.12 chopps */ 121 1.30 jklos #define KERNEL_STARTUP_VERSION 3 122 1.19 mhitch #define KERNEL_STARTUP_VERSION_MAX 9 123 1.10 chopps 124 1.20 is #define DRACOREVISION (*(UBYTE *)0x02000009) 125 1.20 is #define DRACOMMUMARGIN 0x200000 126 1.20 is 127 1.12 chopps #define MAXMEMSEG 16 128 1.12 chopps struct boot_memlist { 129 1.12 chopps u_int m_nseg; /* num_mem; */ 130 1.12 chopps struct boot_memseg { 131 1.12 chopps u_int ms_start; 132 1.12 chopps u_int ms_size; 133 1.12 chopps u_short ms_attrib; 134 1.12 chopps short ms_pri; 135 1.12 chopps } m_seg[MAXMEMSEG]; 136 1.12 chopps }; 137 1.12 chopps struct boot_memlist memlist; 138 1.12 chopps struct boot_memlist *kmemlist; 139 1.12 chopps 140 1.38 phx void err(int eval, const char *, ...); 141 1.37 phx int getopt(int, char * const [], const char *); 142 1.30 jklos void get_mem_config (void **, u_long *, u_long *); 143 1.30 jklos void get_cpuid (void); 144 1.30 jklos void get_eclock (void); 145 1.30 jklos void get_AGA (void); 146 1.30 jklos void usage (void); 147 1.30 jklos void verbose_usage (void); 148 1.38 phx extern void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *, 149 1.30 jklos int, int, u_long, u_long, int); 150 1.30 jklos extern u_long startit_sz; 151 1.12 chopps 152 1.5 mw extern char *optarg; 153 1.5 mw extern int optind; 154 1.5 mw 155 1.30 jklos struct ExpansionBase *ExpansionBase = NULL; 156 1.30 jklos struct GfxBase *GfxBase = NULL; 157 1.30 jklos 158 1.38 phx u_int minmemsz = 2 * 1024 * 1024; 159 1.38 phx int p_flag = 1; 160 1.12 chopps int k_flag; 161 1.12 chopps int t_flag; 162 1.12 chopps int reqmemsz; 163 1.12 chopps int S_flag; 164 1.17 jtc u_long I_flag; 165 1.19 mhitch int Z_flag; 166 1.12 chopps u_long cpuid; 167 1.12 chopps long eclock_freq; 168 1.16 chopps long amiga_flags; 169 1.12 chopps char *program_name; 170 1.20 is u_char *kp; 171 1.30 jklos u_long kpsz; 172 1.30 jklos 173 1.37 phx 174 1.30 jklos void 175 1.30 jklos exit_func(void) 176 1.30 jklos { 177 1.30 jklos if (kp) 178 1.30 jklos FreeMem(kp, kpsz); 179 1.30 jklos if (ExpansionBase) 180 1.30 jklos CloseLibrary((struct Library *)ExpansionBase); 181 1.30 jklos if (GfxBase) 182 1.30 jklos CloseLibrary((struct Library *)GfxBase); 183 1.30 jklos } 184 1.1 mw 185 1.10 chopps int 186 1.30 jklos main(int argc, char **argv) 187 1.1 mw { 188 1.12 chopps struct ConfigDev *cd, *kcd; 189 1.30 jklos u_long fmemsz, cmemsz, ksize, marks[MARK_MAX]; 190 1.30 jklos int boothowto, ncd, i, mem_ix, ch; 191 1.30 jklos u_short kvers; 192 1.12 chopps int *nkcd; 193 1.38 phx u_char *fmem; 194 1.12 chopps char *esym; 195 1.30 jklos void (*start_it) (void *, u_long, u_long, void *, u_long, u_long, 196 1.30 jklos int, void *, int, int, u_long, u_long, int) = startit; 197 1.30 jklos char *kernel_name; 198 1.30 jklos 199 1.30 jklos atexit(exit_func); 200 1.12 chopps 201 1.12 chopps program_name = argv[0]; 202 1.12 chopps boothowto = RB_SINGLE; 203 1.12 chopps 204 1.12 chopps if (argc < 2) 205 1.12 chopps usage(); 206 1.30 jklos 207 1.12 chopps if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL) 208 1.12 chopps err(20, "can't open graphics library"); 209 1.12 chopps if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL) 210 1.12 chopps err(20, "can't open expansion library"); 211 1.12 chopps 212 1.38 phx while ((ch = getopt(argc, argv, "aAbCc:DhI:klm:M:n:qptsSvVZ")) != -1) { 213 1.12 chopps switch (ch) { 214 1.12 chopps case 'k': 215 1.12 chopps k_flag = 1; 216 1.12 chopps break; 217 1.12 chopps case 'a': 218 1.12 chopps boothowto &= ~(RB_SINGLE); 219 1.12 chopps boothowto |= RB_AUTOBOOT; 220 1.12 chopps break; 221 1.12 chopps case 'b': 222 1.12 chopps boothowto |= RB_ASKNAME; 223 1.12 chopps break; 224 1.12 chopps case 'p': 225 1.12 chopps p_flag = 1; 226 1.12 chopps break; 227 1.38 phx case 'l': 228 1.38 phx p_flag = 0; 229 1.38 phx break; 230 1.12 chopps case 't': 231 1.12 chopps t_flag = 1; 232 1.12 chopps break; 233 1.12 chopps case 'm': 234 1.12 chopps reqmemsz = atoi(optarg) * 1024; 235 1.12 chopps break; 236 1.38 phx case 'M': 237 1.38 phx minmemsz = atoi(optarg) * 1024 * 1024; 238 1.38 phx break; 239 1.19 mhitch case 's': 240 1.19 mhitch boothowto &= ~(RB_AUTOBOOT); 241 1.19 mhitch boothowto |= RB_SINGLE; 242 1.19 mhitch break; 243 1.25 jdolecek case 'q': 244 1.25 jdolecek boothowto |= AB_QUIET; 245 1.26 aymeric break; 246 1.25 jdolecek case 'v': 247 1.25 jdolecek boothowto |= AB_VERBOSE; 248 1.25 jdolecek break; 249 1.12 chopps case 'V': 250 1.12 chopps fprintf(stderr,"%s\n",_version + 6); 251 1.12 chopps break; 252 1.12 chopps case 'S': 253 1.12 chopps S_flag = 1; 254 1.12 chopps break; 255 1.12 chopps case 'D': 256 1.12 chopps boothowto |= RB_KDB; 257 1.12 chopps break; 258 1.12 chopps case 'c': 259 1.12 chopps cpuid = atoi(optarg) << 16; 260 1.12 chopps break; 261 1.14 chopps case 'A': 262 1.16 chopps amiga_flags |= 1; 263 1.16 chopps break; 264 1.16 chopps case 'n': 265 1.16 chopps i = atoi(optarg); 266 1.37 phx if (i >= 0 && i <= 3) { 267 1.37 phx amiga_flags &= ~(3 << 1); 268 1.16 chopps amiga_flags |= i << 1; 269 1.37 phx } 270 1.16 chopps else 271 1.16 chopps err(20, "-n option must be 0, 1, 2, or 3"); 272 1.14 chopps break; 273 1.35 mhitch case 'C': 274 1.35 mhitch amiga_flags |= (1 << 3); 275 1.35 mhitch break; 276 1.17 jtc case 'I': 277 1.17 jtc I_flag = strtoul(optarg, NULL, 16); 278 1.17 jtc break; 279 1.19 mhitch case 'Z': 280 1.19 mhitch Z_flag = 1; 281 1.19 mhitch break; 282 1.12 chopps case 'h': 283 1.12 chopps verbose_usage(); 284 1.12 chopps default: 285 1.12 chopps usage(); 286 1.12 chopps } 287 1.12 chopps } 288 1.12 chopps argc -= optind; 289 1.12 chopps argv += optind; 290 1.12 chopps 291 1.12 chopps if (argc != 1) 292 1.12 chopps usage(); 293 1.30 jklos 294 1.30 jklos kernel_name = argv[0]; 295 1.12 chopps 296 1.12 chopps for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++) 297 1.12 chopps ; 298 1.20 is get_cpuid(); 299 1.38 phx get_mem_config((void **)&fmem, &fmemsz, &cmemsz); 300 1.12 chopps get_eclock(); 301 1.14 chopps get_AGA(); 302 1.12 chopps 303 1.30 jklos /* 304 1.30 jklos * XXX Call loadfile with COUNT* options to get size 305 1.30 jklos * XXX Allocate memory for kernel + additional data 306 1.30 jklos * XXX Call loadfile with LOAD* options to load text/data/symbols 307 1.30 jklos */ 308 1.30 jklos marks[MARK_START] = 0; 309 1.30 jklos if (loadfile(kernel_name, marks, 310 1.30 jklos COUNT_TEXT|COUNT_TEXTA|COUNT_DATA|COUNT_BSS| 311 1.30 jklos (S_flag ? (COUNT_SYM|COUNT_HDR) : 0)) == -1) { 312 1.30 jklos err(20, "unable to parse kernel image"); 313 1.30 jklos } 314 1.30 jklos ksize = ((marks[MARK_END] + 3) & ~3) 315 1.30 jklos + sizeof(*nkcd) + ncd * sizeof(*cd) 316 1.30 jklos + sizeof(*nkcd) + memlist.m_nseg * sizeof(struct boot_memseg); 317 1.12 chopps 318 1.12 chopps if (t_flag) { 319 1.12 chopps for (i = 0; i < memlist.m_nseg; ++i) { 320 1.38 phx printf("mem segment %d: start=%08x size=%08x" 321 1.38 phx " attribute=%04x pri=%d\n", 322 1.30 jklos i + 1, 323 1.30 jklos memlist.m_seg[i].ms_start, 324 1.12 chopps memlist.m_seg[i].ms_size, 325 1.12 chopps memlist.m_seg[i].ms_attrib, 326 1.12 chopps memlist.m_seg[i].ms_pri); 327 1.10 chopps } 328 1.38 phx printf("kernel size: %lu\n", ksize); 329 1.12 chopps } 330 1.30 jklos 331 1.30 jklos kpsz = ksize + 256 + startit_sz; 332 1.30 jklos kp = (u_char *)AllocMem(kpsz, MEMF_FAST|MEMF_REVERSE); 333 1.12 chopps if (kp == NULL) 334 1.30 jklos err(20, "failed alloc %d", ksize); 335 1.12 chopps 336 1.30 jklos marks[MARK_START] = (u_long)kp; 337 1.30 jklos if (loadfile(kernel_name, marks, 338 1.30 jklos LOAD_TEXT|LOAD_TEXTA|LOAD_DATA|LOAD_BSS| 339 1.30 jklos (S_flag ? (LOAD_SYM|LOAD_HDR) : 0)) == -1) { 340 1.30 jklos err(20, "unable to load kernel image"); 341 1.30 jklos } 342 1.30 jklos marks[MARK_END] = (marks[MARK_END] + 3) & ~3; 343 1.12 chopps 344 1.12 chopps if (k_flag) { 345 1.12 chopps fmem += 4 * 1024 * 1024; 346 1.12 chopps fmemsz -= 4 * 1024 * 1024; 347 1.12 chopps } 348 1.12 chopps if (reqmemsz && reqmemsz <= fmemsz) 349 1.12 chopps fmemsz = reqmemsz; 350 1.30 jklos 351 1.12 chopps if (boothowto & RB_AUTOBOOT) 352 1.12 chopps printf("Autobooting..."); 353 1.12 chopps if (boothowto & RB_ASKNAME) 354 1.12 chopps printf("Askboot..."); 355 1.12 chopps 356 1.38 phx printf("Using %lu%c FASTMEM at 0x%lx, %luM CHIPMEM\n", 357 1.12 chopps (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20, 358 1.30 jklos (fmemsz & 0xfffff) ? 'K' : 'M', (u_long)fmem, cmemsz >> 20); 359 1.30 jklos 360 1.30 jklos kvers = *(u_short *)(marks[MARK_ENTRY] - 2); 361 1.30 jklos if (kvers == 0x4e73) kvers = 0; 362 1.30 jklos if (kvers > KERNEL_STARTUP_VERSION_MAX) 363 1.30 jklos err(20, "newer loadbsd required: %d\n", kvers); 364 1.30 jklos if (kvers > KERNEL_STARTUP_VERSION) { 365 1.30 jklos printf("****************************************************\n" 366 1.30 jklos "*** Notice: this kernel has features which require\n" 367 1.30 jklos "*** a newer version of loadbsd. To allow the use of\n" 368 1.30 jklos "*** any newer features or capabilities, you should\n" 369 1.30 jklos "*** update to a newer version of loadbsd\n" 370 1.30 jklos "****************************************************\n"); 371 1.17 jtc sleep(3); /* even more time to see that message */ 372 1.17 jtc } 373 1.30 jklos 374 1.12 chopps /* 375 1.12 chopps * give them a chance to read the information... 376 1.12 chopps */ 377 1.12 chopps sleep(2); 378 1.12 chopps 379 1.30 jklos nkcd = (int *)marks[MARK_END]; 380 1.30 jklos esym = 0; 381 1.12 chopps /* 382 1.30 jklos * If symbols loaded and kernel can handle them, set esym to end. 383 1.12 chopps */ 384 1.30 jklos if (marks[MARK_SYM] != marks[MARK_START]) { 385 1.30 jklos if (kvers > 1) { 386 1.30 jklos esym = (void *)(marks[MARK_END] - marks[MARK_START]); 387 1.30 jklos } 388 1.30 jklos else { 389 1.30 jklos /* 390 1.30 jklos * suppress symbols 391 1.30 jklos */ 392 1.30 jklos nkcd = (int *)marks[MARK_SYM]; 393 1.30 jklos } 394 1.10 chopps } 395 1.30 jklos 396 1.12 chopps *nkcd = ncd; 397 1.27 aymeric kcd = (struct ConfigDev *)(nkcd + 1); 398 1.30 jklos while((cd = FindConfigDev(cd, -1, -1))) { 399 1.38 phx u_char *ba = kcd->cd_BoardAddr; 400 1.38 phx 401 1.30 jklos memcpy(kcd, cd, sizeof(*kcd)); 402 1.38 phx if (((cpuid >> 24) == 0x7d) && ((u_long)ba < 0x1000000)) { 403 1.20 is if (t_flag) 404 1.38 phx printf("Transformed Z2 device from %08lx ", (u_long)ba); 405 1.38 phx ba += 0x3000000; 406 1.38 phx kcd->cd_BoardAddr = ba; 407 1.20 is if (t_flag) 408 1.38 phx printf("to %08lx\n", (u_long)ba); 409 1.20 is } 410 1.20 is ++kcd; 411 1.20 is } 412 1.12 chopps 413 1.12 chopps kmemlist = (struct boot_memlist *)kcd; 414 1.12 chopps kmemlist->m_nseg = memlist.m_nseg; 415 1.12 chopps for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++) 416 1.12 chopps kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix]; 417 1.19 mhitch 418 1.30 jklos if (kvers > 2 && Z_flag == 0) { 419 1.19 mhitch /* 420 1.19 mhitch * Kernel supports direct load to fastmem, and the -Z 421 1.19 mhitch * option was not specified. Copy startup code to end 422 1.19 mhitch * of kernel image and set start_it. 423 1.19 mhitch */ 424 1.38 phx if (ksize >= fmemsz) { 425 1.38 phx printf("Kernel size %lu exceeds best Fast Memory segment of %lu\n", 426 1.38 phx ksize, fmemsz); 427 1.38 phx err(20, "Insufficient Fast Memory for kernel"); 428 1.38 phx } 429 1.38 phx if (kp < fmem) { 430 1.20 is printf("Kernel at %08lx, Fastmem used at %08lx\n", 431 1.30 jklos (u_long)kp, (u_long)fmem); 432 1.30 jklos err(20, "Can't copy upwards yet.\nDefragment your memory and try again OR try the -p OR try the -Z options."); 433 1.20 is } 434 1.38 phx start_it = (void (*)())(kp + ksize + 256); 435 1.38 phx memcpy((void *)start_it, (void *)startit, startit_sz); 436 1.19 mhitch CacheClearU(); 437 1.19 mhitch printf("*** Loading from %08lx to Fastmem %08lx ***\n", 438 1.30 jklos (u_long)kp, (u_long)fmem); 439 1.19 mhitch sleep(2); 440 1.19 mhitch } else { 441 1.19 mhitch /* 442 1.36 msaitoh * Either the kernel doesn't support loading directly to 443 1.19 mhitch * fastmem or the -Z flag was given. Verify kernel image 444 1.19 mhitch * fits into chipmem. 445 1.19 mhitch */ 446 1.19 mhitch if (ksize >= cmemsz) { 447 1.38 phx printf("Kernel size %lu exceeds Chip Memory of %lu\n", 448 1.19 mhitch ksize, cmemsz); 449 1.19 mhitch err(20, "Insufficient Chip Memory for kernel"); 450 1.19 mhitch } 451 1.19 mhitch Z_flag = 1; 452 1.30 jklos printf("*** Loading from %08lx to Chipmem ***\n", (u_long)kp); 453 1.19 mhitch } 454 1.19 mhitch 455 1.12 chopps /* 456 1.12 chopps * if test option set, done 457 1.12 chopps */ 458 1.20 is if (t_flag) { 459 1.12 chopps exit(0); 460 1.20 is } 461 1.30 jklos 462 1.12 chopps /* 463 1.12 chopps * XXX AGA startup - may need more 464 1.12 chopps */ 465 1.16 chopps LoadView(NULL); /* Don't do this if AGA active? */ 466 1.30 jklos start_it(kp, ksize, marks[MARK_ENTRY] - marks[MARK_START], fmem, fmemsz, cmemsz, 467 1.30 jklos boothowto, esym, cpuid, eclock_freq, amiga_flags, I_flag, Z_flag == 0); 468 1.12 chopps /*NOTREACHED*/ 469 1.12 chopps } 470 1.1 mw 471 1.1 mw void 472 1.30 jklos get_mem_config(void **fmem, u_long *fmemsz, u_long *cmemsz) 473 1.1 mw { 474 1.12 chopps struct MemHeader *mh, *nmh; 475 1.30 jklos u_int nmem, eseg, segsz, seg, nseg, nsegsz; 476 1.12 chopps char mempri; 477 1.12 chopps 478 1.12 chopps nmem = 0; 479 1.12 chopps mempri = -128; 480 1.12 chopps *fmemsz = 0; 481 1.12 chopps *cmemsz = 0; 482 1.38 phx *fmem = NULL; 483 1.12 chopps 484 1.12 chopps /* 485 1.38 phx * walk through the exec memory list 486 1.12 chopps */ 487 1.12 chopps Forbid(); 488 1.20 is for (mh = (void *) SysBase->MemList.lh_Head; 489 1.20 is nmh = (void *) mh->mh_Node.ln_Succ; mh = nmh) { 490 1.20 is 491 1.20 is nseg = (u_int)mh->mh_Lower; 492 1.20 is nsegsz = (u_int)mh->mh_Upper - nseg; 493 1.20 is 494 1.20 is segsz = nsegsz; 495 1.20 is seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, 0L); 496 1.20 is nsegsz -= segsz, nseg += segsz; 497 1.20 is for (;segsz; 498 1.27 aymeric segsz = nsegsz, 499 1.20 is seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, DMA_Continue), 500 1.20 is nsegsz -= segsz, nseg += segsz, ++nmem) { 501 1.20 is 502 1.20 is if (t_flag) 503 1.20 is printf("Translated %08x sz %08x to %08x sz %08x\n", 504 1.20 is nseg - segsz, nsegsz + segsz, seg, segsz); 505 1.30 jklos 506 1.20 is eseg = seg + segsz; 507 1.20 is 508 1.20 is if ((cpuid >> 24) == 0x7D) { 509 1.20 is /* DraCo MMU table kludge */ 510 1.30 jklos 511 1.20 is segsz = ((segsz -1) | 0xfffff) + 1; 512 1.20 is seg = eseg - segsz; 513 1.20 is 514 1.27 aymeric /* 515 1.27 aymeric * Only use first SIMM to boot; we know it is VA==PA. 516 1.20 is * Enter into table and continue. Yes, 517 1.20 is * this is ugly. 518 1.20 is */ 519 1.20 is if (seg != 0x40000000) { 520 1.20 is memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 521 1.20 is memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 522 1.20 is memlist.m_seg[nmem].ms_size = segsz; 523 1.20 is memlist.m_seg[nmem].ms_start = seg; 524 1.20 is ++nmem; 525 1.27 aymeric continue; 526 1.20 is } 527 1.20 is 528 1.20 is memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 529 1.20 is memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 530 1.20 is memlist.m_seg[nmem].ms_size = DRACOMMUMARGIN; 531 1.20 is memlist.m_seg[nmem].ms_start = seg; 532 1.20 is 533 1.20 is ++nmem; 534 1.20 is seg += DRACOMMUMARGIN; 535 1.30 jklos segsz -= DRACOMMUMARGIN; 536 1.20 is } 537 1.12 chopps 538 1.20 is memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 539 1.20 is memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 540 1.20 is memlist.m_seg[nmem].ms_size = segsz; 541 1.20 is memlist.m_seg[nmem].ms_start = seg; 542 1.30 jklos 543 1.20 is if ((mh->mh_Attributes & (MEMF_CHIP|MEMF_FAST)) == MEMF_CHIP) { 544 1.27 aymeric /* 545 1.27 aymeric * there should hardly be more than one entry for 546 1.27 aymeric * chip mem, but handle it the same nevertheless 547 1.20 is * cmem always starts at 0, so include vector area 548 1.20 is */ 549 1.20 is memlist.m_seg[nmem].ms_start = seg = 0; 550 1.20 is /* 551 1.20 is * round to multiple of 512K 552 1.20 is */ 553 1.20 is segsz = (segsz + 512 * 1024 - 1) & -(512 * 1024); 554 1.20 is memlist.m_seg[nmem].ms_size = segsz; 555 1.20 is if (segsz > *cmemsz) 556 1.20 is *cmemsz = segsz; 557 1.20 is continue; 558 1.20 is } 559 1.27 aymeric /* 560 1.20 is * some heuristics.. 561 1.12 chopps */ 562 1.29 thorpej seg &= -AOUT_LDPGSZ; 563 1.29 thorpej eseg = (eseg + AOUT_LDPGSZ - 1) & -AOUT_LDPGSZ; 564 1.30 jklos 565 1.12 chopps /* 566 1.27 aymeric * get the mem back stolen by incore kickstart on 567 1.20 is * A3000 with V36 bootrom. 568 1.12 chopps */ 569 1.20 is if (eseg == 0x07f80000) 570 1.20 is eseg = 0x08000000; 571 1.30 jklos 572 1.20 is /* 573 1.20 is * or by zkick on a A2000. 574 1.20 is */ 575 1.20 is if (seg == 0x280000 && 576 1.20 is strcmp(mh->mh_Node.ln_Name, "zkick memory") == 0) 577 1.20 is seg = 0x200000; 578 1.21 is /* 579 1.21 is * or by Fusion Forty fastrom 580 1.21 is */ 581 1.21 is if ((seg & ~(1024*1024-1)) == 0x11000000) { 582 1.27 aymeric /* 583 1.21 is * XXX we should test the name. 584 1.21 is * Unfortunately, the memory is just called 585 1.21 is * "32 bit memory" which isn't very specific. 586 1.21 is */ 587 1.21 is seg = 0x11000000; 588 1.21 is } 589 1.30 jklos 590 1.20 is segsz = eseg - seg; 591 1.20 is memlist.m_seg[nmem].ms_start = seg; 592 1.12 chopps memlist.m_seg[nmem].ms_size = segsz; 593 1.20 is /* 594 1.38 phx * If this segment is smaller than minmemsz (default: 2M), 595 1.20 is * don't use it to load the kernel 596 1.20 is */ 597 1.38 phx if (segsz < minmemsz) 598 1.20 is continue; 599 1.20 is /* 600 1.27 aymeric * if p_flag is set, select memory by priority 601 1.20 is * instead of size 602 1.20 is */ 603 1.20 is if ((!p_flag && segsz > *fmemsz) || (p_flag && 604 1.20 is mempri <= mh->mh_Node.ln_Pri && segsz > *fmemsz)) { 605 1.20 is *fmemsz = segsz; 606 1.20 is *fmem = (void *)seg; 607 1.20 is mempri = mh->mh_Node.ln_Pri; 608 1.20 is } 609 1.12 chopps 610 1.12 chopps } 611 1.1 mw } 612 1.12 chopps memlist.m_nseg = nmem; 613 1.12 chopps Permit(); 614 1.1 mw } 615 1.1 mw 616 1.10 chopps /* 617 1.10 chopps * Try to determine the machine ID by searching the resident module list 618 1.10 chopps * for modules only present on specific machines. (Thanks, Bill!) 619 1.10 chopps */ 620 1.10 chopps void 621 1.30 jklos get_cpuid(void) 622 1.10 chopps { 623 1.11 chopps cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */ 624 1.30 jklos if ((cpuid & AFB_68020) == 0) 625 1.31 wiz err(20, "CPU not supported"); 626 1.11 chopps if (cpuid & 0xffff0000) { 627 1.24 is if ((cpuid >> 24) == 0x7D) 628 1.20 is return; 629 1.20 is 630 1.11 chopps switch (cpuid >> 16) { 631 1.11 chopps case 500: 632 1.11 chopps case 600: 633 1.11 chopps case 1000: 634 1.11 chopps case 1200: 635 1.11 chopps case 2000: 636 1.11 chopps case 3000: 637 1.11 chopps case 4000: 638 1.11 chopps return; 639 1.11 chopps default: 640 1.38 phx printf("machine Amiga %lu is not recognized\n", 641 1.11 chopps cpuid >> 16); 642 1.12 chopps exit(1); 643 1.11 chopps } 644 1.11 chopps } 645 1.18 chopps if (FindResident("A4000 Bonus") || FindResident("A4000 bonus") 646 1.18 chopps || FindResident("A1000 Bonus")) 647 1.16 chopps cpuid |= 4000 << 16; 648 1.16 chopps else if (FindResident("A3000 Bonus") || FindResident("A3000 bonus")) 649 1.16 chopps cpuid |= 3000 << 16; 650 1.16 chopps else if (OpenResource("card.resource")) { 651 1.37 phx UBYTE alicerev = *((UBYTE *)0xdff004) & 0x6f; 652 1.37 phx if (alicerev == 0x22 || alicerev == 0x23) 653 1.37 phx cpuid |= 1200 << 16; /* AGA + PCMCIA = A1200 */ 654 1.37 phx else 655 1.37 phx cpuid |= 600 << 16; /* noAGA + PCMCIA = A600 */ 656 1.20 is } else if (OpenResource("draco.resource")) { 657 1.20 is cpuid |= (32000 | DRACOREVISION) << 16; 658 1.10 chopps } 659 1.12 chopps /* 660 1.12 chopps * Nothing found, it's probably an A2000 or A500 661 1.12 chopps */ 662 1.16 chopps if ((cpuid >> 16) == 0) 663 1.10 chopps cpuid |= 2000 << 16; 664 1.10 chopps } 665 1.1 mw 666 1.12 chopps void 667 1.30 jklos get_eclock(void) 668 1.12 chopps { 669 1.12 chopps /* Fix for 1.3 startups? */ 670 1.14 chopps if (SysBase->LibNode.lib_Version > 36) 671 1.14 chopps eclock_freq = SysBase->ex_EClockFrequency; 672 1.14 chopps else 673 1.14 chopps eclock_freq = (GfxBase->DisplayFlags & PAL) ? 674 1.14 chopps 709379 : 715909; 675 1.14 chopps } 676 1.14 chopps 677 1.14 chopps void 678 1.30 jklos get_AGA(void) 679 1.14 chopps { 680 1.14 chopps /* 681 1.14 chopps * Determine if an AGA mode is active 682 1.14 chopps */ 683 1.12 chopps } 684 1.12 chopps 685 1.12 chopps void 686 1.30 jklos usage(void) 687 1.6 chopps { 688 1.38 phx fprintf(stderr, "usage: %s [-abhklpstACDSVZ] [-c machine] [-m size] [-M size] [-n mode] [-I sync-inhibit] kernel\n", 689 1.12 chopps program_name); 690 1.12 chopps exit(1); 691 1.6 chopps } 692 1.6 chopps 693 1.12 chopps void 694 1.30 jklos verbose_usage(void) 695 1.12 chopps { 696 1.37 phx fprintf(stderr, "\n\ 697 1.37 phx NAME\n\ 698 1.37 phx \t%s - loads NetBSD from amiga dos.\n\ 699 1.37 phx SYNOPSIS\n\ 700 1.38 phx \t%s [-abhklpstACDSVZ] [-c machine] [-m size] [-M size] [-n mode] [-I sync-inhibit] kernel\n\ 701 1.37 phx OPTIONS\n\ 702 1.37 phx \t-a Boot up to multiuser mode.\n\ 703 1.37 phx \t-A Use AGA display mode, if available.\n\ 704 1.37 phx \t-b Ask for which root device.\n\ 705 1.38 phx \t It is possible to have multiple roots and choose between them.\n\ 706 1.37 phx \t-c Set machine type. [e.g 3000; use 32000+N for DraCo rev. N]\n\ 707 1.37 phx \t-C Use Serial Console.\n\ 708 1.37 phx \t-D Enter debugger\n\ 709 1.37 phx \t-h This help message.\n\ 710 1.37 phx \t-I Inhibit sync negotiation. Option value is bit-encoded targets.\n\ 711 1.37 phx \t-k Reserve the first 4M of fast mem [Some one else\n\ 712 1.37 phx \t is going to have to answer what that it is used for].\n\ 713 1.38 phx \t-l Use the largest memory segment for loading the kernel.\n\ 714 1.37 phx \t-m Tweak amount of available memory, for finding minimum amount\n\ 715 1.37 phx \t of memory required to run. Sets fastmem size to specified\n\ 716 1.37 phx \t size in Kbytes.\n\ 717 1.38 phx \t-M Request a minimum size in Mbytes for the kernel's memory\n\ 718 1.38 phx \t segment. Defaults to 2M.\n\ 719 1.37 phx \t-n Enable multiple non-contiguous memory: value = 0 (disabled),\n\ 720 1.37 phx \t 1 (two segments), 2 (all avail segments), 3 (same as 2?).\n\ 721 1.38 phx \t-p Use highest priority fastmem segment for loading the kernel.\n\ 722 1.38 phx \t This is the default.\n\ 723 1.37 phx \t-q Boot up in quiet mode.\n\ 724 1.37 phx \t-s Boot up in singleuser mode (default).\n\ 725 1.37 phx \t-S Include kernel symbol table.\n\ 726 1.37 phx \t-t This is a *test* option. It prints out the memory\n\ 727 1.37 phx \t list information being passed to the kernel and also\n\ 728 1.37 phx \t exits without actually starting NetBSD.\n\ 729 1.37 phx \t-v Boot up in verbose mode.\n\ 730 1.37 phx \t-V Version of loadbsd program.\n\ 731 1.37 phx \t-Z Force kernel load to chipmem.\n\ 732 1.37 phx HISTORY\n\ 733 1.12 chopps \tThis version supports Kernel version 720 +\n", 734 1.12 chopps program_name, program_name); 735 1.12 chopps exit(1); 736 1.12 chopps } 737 1.12 chopps 738 1.30 jklos static void 739 1.30 jklos _Vdomessage(int doerrno, const char *fmt, va_list args) 740 1.12 chopps { 741 1.12 chopps fprintf(stderr, "%s: ", program_name); 742 1.12 chopps if (fmt) { 743 1.12 chopps vfprintf(stderr, fmt, args); 744 1.12 chopps fprintf(stderr, ": "); 745 1.12 chopps } 746 1.37 phx if (doerrno) { 747 1.12 chopps fprintf(stderr, "%s", strerror(errno)); 748 1.12 chopps } 749 1.12 chopps fprintf(stderr, "\n"); 750 1.12 chopps } 751 1.12 chopps 752 1.12 chopps void 753 1.12 chopps err(int eval, const char *fmt, ...) 754 1.12 chopps { 755 1.12 chopps va_list ap; 756 1.12 chopps va_start(ap, fmt); 757 1.30 jklos _Vdomessage(1, fmt, ap); 758 1.30 jklos va_end(ap); 759 1.30 jklos exit(eval); 760 1.12 chopps } 761 1.12 chopps 762 1.12 chopps void 763 1.12 chopps warn(const char *fmt, ...) 764 1.12 chopps { 765 1.12 chopps va_list ap; 766 1.12 chopps va_start(ap, fmt); 767 1.30 jklos _Vdomessage(1, fmt, ap); 768 1.12 chopps va_end(ap); 769 1.12 chopps } 770