loadbsd.c revision 1.38 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