loadbsd.c revision 1.37 1 1.37 phx /* $NetBSD: loadbsd.c,v 1.37 2022/09/06 17:50:18 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.9 chopps */
108 1.37 phx static const char _version[] = "$VER: LoadBSD 3.2 (02.09.2022)";
109 1.9 chopps
110 1.12 chopps /*
111 1.19 mhitch * Kernel startup interface version
112 1.12 chopps * 1: first version of loadbsd
113 1.12 chopps * 2: needs esym location passed in a4
114 1.19 mhitch * 3: load kernel image into fastmem rather than chipmem
115 1.19 mhitch * MAX: highest version with backward compatibility.
116 1.12 chopps */
117 1.30 jklos #define KERNEL_STARTUP_VERSION 3
118 1.19 mhitch #define KERNEL_STARTUP_VERSION_MAX 9
119 1.10 chopps
120 1.20 is #define DRACOREVISION (*(UBYTE *)0x02000009)
121 1.20 is #define DRACOMMUMARGIN 0x200000
122 1.20 is
123 1.12 chopps #define MAXMEMSEG 16
124 1.12 chopps struct boot_memlist {
125 1.12 chopps u_int m_nseg; /* num_mem; */
126 1.12 chopps struct boot_memseg {
127 1.12 chopps u_int ms_start;
128 1.12 chopps u_int ms_size;
129 1.12 chopps u_short ms_attrib;
130 1.12 chopps short ms_pri;
131 1.12 chopps } m_seg[MAXMEMSEG];
132 1.12 chopps };
133 1.12 chopps struct boot_memlist memlist;
134 1.12 chopps struct boot_memlist *kmemlist;
135 1.12 chopps
136 1.37 phx int getopt(int, char * const [], const char *);
137 1.30 jklos void get_mem_config (void **, u_long *, u_long *);
138 1.30 jklos void get_cpuid (void);
139 1.30 jklos void get_eclock (void);
140 1.30 jklos void get_AGA (void);
141 1.30 jklos void usage (void);
142 1.30 jklos void verbose_usage (void);
143 1.30 jklos void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *,
144 1.30 jklos int, int, u_long, u_long, int);
145 1.30 jklos extern u_long startit_sz;
146 1.12 chopps
147 1.5 mw extern char *optarg;
148 1.5 mw extern int optind;
149 1.5 mw
150 1.30 jklos struct ExpansionBase *ExpansionBase = NULL;
151 1.30 jklos struct GfxBase *GfxBase = NULL;
152 1.30 jklos
153 1.12 chopps int k_flag;
154 1.12 chopps int p_flag;
155 1.12 chopps int t_flag;
156 1.12 chopps int reqmemsz;
157 1.12 chopps int S_flag;
158 1.17 jtc u_long I_flag;
159 1.19 mhitch int Z_flag;
160 1.12 chopps u_long cpuid;
161 1.12 chopps long eclock_freq;
162 1.16 chopps long amiga_flags;
163 1.12 chopps char *program_name;
164 1.20 is u_char *kp;
165 1.30 jklos u_long kpsz;
166 1.30 jklos
167 1.37 phx static void err(int, const char *fmt, ...);
168 1.37 phx
169 1.37 phx
170 1.30 jklos void
171 1.30 jklos exit_func(void)
172 1.30 jklos {
173 1.30 jklos if (kp)
174 1.30 jklos FreeMem(kp, kpsz);
175 1.30 jklos if (ExpansionBase)
176 1.30 jklos CloseLibrary((struct Library *)ExpansionBase);
177 1.30 jklos if (GfxBase)
178 1.30 jklos CloseLibrary((struct Library *)GfxBase);
179 1.30 jklos }
180 1.1 mw
181 1.10 chopps int
182 1.30 jklos main(int argc, char **argv)
183 1.1 mw {
184 1.12 chopps struct ConfigDev *cd, *kcd;
185 1.30 jklos u_long fmemsz, cmemsz, ksize, marks[MARK_MAX];
186 1.30 jklos int boothowto, ncd, i, mem_ix, ch;
187 1.30 jklos u_short kvers;
188 1.12 chopps int *nkcd;
189 1.12 chopps void *fmem;
190 1.12 chopps char *esym;
191 1.30 jklos void (*start_it) (void *, u_long, u_long, void *, u_long, u_long,
192 1.30 jklos int, void *, int, int, u_long, u_long, int) = startit;
193 1.30 jklos char *kernel_name;
194 1.30 jklos
195 1.30 jklos atexit(exit_func);
196 1.12 chopps
197 1.12 chopps program_name = argv[0];
198 1.12 chopps boothowto = RB_SINGLE;
199 1.12 chopps
200 1.12 chopps if (argc < 2)
201 1.12 chopps usage();
202 1.30 jklos
203 1.12 chopps if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL)
204 1.12 chopps err(20, "can't open graphics library");
205 1.12 chopps if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL)
206 1.12 chopps err(20, "can't open expansion library");
207 1.12 chopps
208 1.35 mhitch while ((ch = getopt(argc, argv, "aAbCc:DhI:km:n:qptsSvVZ")) != -1) {
209 1.12 chopps switch (ch) {
210 1.12 chopps case 'k':
211 1.12 chopps k_flag = 1;
212 1.12 chopps break;
213 1.12 chopps case 'a':
214 1.12 chopps boothowto &= ~(RB_SINGLE);
215 1.12 chopps boothowto |= RB_AUTOBOOT;
216 1.12 chopps break;
217 1.12 chopps case 'b':
218 1.12 chopps boothowto |= RB_ASKNAME;
219 1.12 chopps break;
220 1.12 chopps case 'p':
221 1.12 chopps p_flag = 1;
222 1.12 chopps break;
223 1.12 chopps case 't':
224 1.12 chopps t_flag = 1;
225 1.12 chopps break;
226 1.12 chopps case 'm':
227 1.12 chopps reqmemsz = atoi(optarg) * 1024;
228 1.12 chopps break;
229 1.19 mhitch case 's':
230 1.19 mhitch boothowto &= ~(RB_AUTOBOOT);
231 1.19 mhitch boothowto |= RB_SINGLE;
232 1.19 mhitch break;
233 1.25 jdolecek case 'q':
234 1.25 jdolecek boothowto |= AB_QUIET;
235 1.26 aymeric break;
236 1.25 jdolecek case 'v':
237 1.25 jdolecek boothowto |= AB_VERBOSE;
238 1.25 jdolecek break;
239 1.12 chopps case 'V':
240 1.12 chopps fprintf(stderr,"%s\n",_version + 6);
241 1.12 chopps break;
242 1.12 chopps case 'S':
243 1.12 chopps S_flag = 1;
244 1.12 chopps break;
245 1.12 chopps case 'D':
246 1.12 chopps boothowto |= RB_KDB;
247 1.12 chopps break;
248 1.12 chopps case 'c':
249 1.12 chopps cpuid = atoi(optarg) << 16;
250 1.12 chopps break;
251 1.14 chopps case 'A':
252 1.16 chopps amiga_flags |= 1;
253 1.16 chopps break;
254 1.16 chopps case 'n':
255 1.16 chopps i = atoi(optarg);
256 1.37 phx if (i >= 0 && i <= 3) {
257 1.37 phx amiga_flags &= ~(3 << 1);
258 1.16 chopps amiga_flags |= i << 1;
259 1.37 phx }
260 1.16 chopps else
261 1.16 chopps err(20, "-n option must be 0, 1, 2, or 3");
262 1.14 chopps break;
263 1.35 mhitch case 'C':
264 1.35 mhitch amiga_flags |= (1 << 3);
265 1.35 mhitch break;
266 1.17 jtc case 'I':
267 1.17 jtc I_flag = strtoul(optarg, NULL, 16);
268 1.17 jtc break;
269 1.19 mhitch case 'Z':
270 1.19 mhitch Z_flag = 1;
271 1.19 mhitch break;
272 1.12 chopps case 'h':
273 1.12 chopps verbose_usage();
274 1.12 chopps default:
275 1.12 chopps usage();
276 1.12 chopps }
277 1.12 chopps }
278 1.12 chopps argc -= optind;
279 1.12 chopps argv += optind;
280 1.12 chopps
281 1.12 chopps if (argc != 1)
282 1.12 chopps usage();
283 1.30 jklos
284 1.30 jklos kernel_name = argv[0];
285 1.12 chopps
286 1.12 chopps for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++)
287 1.12 chopps ;
288 1.20 is get_cpuid();
289 1.12 chopps get_mem_config(&fmem, &fmemsz, &cmemsz);
290 1.12 chopps get_eclock();
291 1.14 chopps get_AGA();
292 1.12 chopps
293 1.30 jklos /*
294 1.30 jklos * XXX Call loadfile with COUNT* options to get size
295 1.30 jklos * XXX Allocate memory for kernel + additional data
296 1.30 jklos * XXX Call loadfile with LOAD* options to load text/data/symbols
297 1.30 jklos */
298 1.30 jklos marks[MARK_START] = 0;
299 1.30 jklos if (loadfile(kernel_name, marks,
300 1.30 jklos COUNT_TEXT|COUNT_TEXTA|COUNT_DATA|COUNT_BSS|
301 1.30 jklos (S_flag ? (COUNT_SYM|COUNT_HDR) : 0)) == -1) {
302 1.30 jklos err(20, "unable to parse kernel image");
303 1.30 jklos }
304 1.30 jklos ksize = ((marks[MARK_END] + 3) & ~3)
305 1.30 jklos + sizeof(*nkcd) + ncd * sizeof(*cd)
306 1.30 jklos + sizeof(*nkcd) + memlist.m_nseg * sizeof(struct boot_memseg);
307 1.12 chopps
308 1.12 chopps if (t_flag) {
309 1.12 chopps for (i = 0; i < memlist.m_nseg; ++i) {
310 1.12 chopps printf("mem segment %d: start=%08lx size=%08lx"
311 1.12 chopps " attribute=%04lx pri=%d\n",
312 1.30 jklos i + 1,
313 1.30 jklos memlist.m_seg[i].ms_start,
314 1.12 chopps memlist.m_seg[i].ms_size,
315 1.12 chopps memlist.m_seg[i].ms_attrib,
316 1.12 chopps memlist.m_seg[i].ms_pri);
317 1.10 chopps }
318 1.30 jklos printf("kernel size: %ld\n", ksize);
319 1.12 chopps }
320 1.30 jklos
321 1.30 jklos kpsz = ksize + 256 + startit_sz;
322 1.30 jklos kp = (u_char *)AllocMem(kpsz, MEMF_FAST|MEMF_REVERSE);
323 1.12 chopps if (kp == NULL)
324 1.30 jklos err(20, "failed alloc %d", ksize);
325 1.12 chopps
326 1.30 jklos marks[MARK_START] = (u_long)kp;
327 1.30 jklos if (loadfile(kernel_name, marks,
328 1.30 jklos LOAD_TEXT|LOAD_TEXTA|LOAD_DATA|LOAD_BSS|
329 1.30 jklos (S_flag ? (LOAD_SYM|LOAD_HDR) : 0)) == -1) {
330 1.30 jklos err(20, "unable to load kernel image");
331 1.30 jklos }
332 1.30 jklos marks[MARK_END] = (marks[MARK_END] + 3) & ~3;
333 1.12 chopps
334 1.12 chopps if (k_flag) {
335 1.12 chopps fmem += 4 * 1024 * 1024;
336 1.12 chopps fmemsz -= 4 * 1024 * 1024;
337 1.12 chopps }
338 1.12 chopps if (reqmemsz && reqmemsz <= fmemsz)
339 1.12 chopps fmemsz = reqmemsz;
340 1.30 jklos
341 1.12 chopps if (boothowto & RB_AUTOBOOT)
342 1.12 chopps printf("Autobooting...");
343 1.12 chopps if (boothowto & RB_ASKNAME)
344 1.12 chopps printf("Askboot...");
345 1.12 chopps
346 1.30 jklos printf("Using %ld%c FASTMEM at 0x%lx, %ldM CHIPMEM\n",
347 1.12 chopps (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20,
348 1.30 jklos (fmemsz & 0xfffff) ? 'K' : 'M', (u_long)fmem, cmemsz >> 20);
349 1.30 jklos
350 1.30 jklos kvers = *(u_short *)(marks[MARK_ENTRY] - 2);
351 1.30 jklos if (kvers == 0x4e73) kvers = 0;
352 1.30 jklos if (kvers > KERNEL_STARTUP_VERSION_MAX)
353 1.30 jklos err(20, "newer loadbsd required: %d\n", kvers);
354 1.30 jklos if (kvers > KERNEL_STARTUP_VERSION) {
355 1.30 jklos printf("****************************************************\n"
356 1.30 jklos "*** Notice: this kernel has features which require\n"
357 1.30 jklos "*** a newer version of loadbsd. To allow the use of\n"
358 1.30 jklos "*** any newer features or capabilities, you should\n"
359 1.30 jklos "*** update to a newer version of loadbsd\n"
360 1.30 jklos "****************************************************\n");
361 1.17 jtc sleep(3); /* even more time to see that message */
362 1.17 jtc }
363 1.30 jklos
364 1.12 chopps /*
365 1.12 chopps * give them a chance to read the information...
366 1.12 chopps */
367 1.12 chopps sleep(2);
368 1.12 chopps
369 1.30 jklos nkcd = (int *)marks[MARK_END];
370 1.30 jklos esym = 0;
371 1.12 chopps /*
372 1.30 jklos * If symbols loaded and kernel can handle them, set esym to end.
373 1.12 chopps */
374 1.30 jklos if (marks[MARK_SYM] != marks[MARK_START]) {
375 1.30 jklos if (kvers > 1) {
376 1.30 jklos esym = (void *)(marks[MARK_END] - marks[MARK_START]);
377 1.30 jklos }
378 1.30 jklos else {
379 1.30 jklos /*
380 1.30 jklos * suppress symbols
381 1.30 jklos */
382 1.30 jklos nkcd = (int *)marks[MARK_SYM];
383 1.30 jklos }
384 1.10 chopps }
385 1.30 jklos
386 1.12 chopps *nkcd = ncd;
387 1.27 aymeric kcd = (struct ConfigDev *)(nkcd + 1);
388 1.30 jklos while((cd = FindConfigDev(cd, -1, -1))) {
389 1.30 jklos memcpy(kcd, cd, sizeof(*kcd));
390 1.20 is if (((cpuid >> 24) == 0x7d) &&
391 1.20 is ((u_long)kcd->cd_BoardAddr < 0x1000000)) {
392 1.20 is if (t_flag)
393 1.30 jklos printf("Transformed Z2 device from %08lx ", (u_long)kcd->cd_BoardAddr);
394 1.20 is kcd->cd_BoardAddr += 0x3000000;
395 1.20 is if (t_flag)
396 1.30 jklos printf("to %08lx\n", (u_long)kcd->cd_BoardAddr);
397 1.20 is }
398 1.20 is ++kcd;
399 1.20 is }
400 1.12 chopps
401 1.12 chopps kmemlist = (struct boot_memlist *)kcd;
402 1.12 chopps kmemlist->m_nseg = memlist.m_nseg;
403 1.12 chopps for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++)
404 1.12 chopps kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix];
405 1.19 mhitch
406 1.30 jklos if (kvers > 2 && Z_flag == 0) {
407 1.19 mhitch /*
408 1.19 mhitch * Kernel supports direct load to fastmem, and the -Z
409 1.19 mhitch * option was not specified. Copy startup code to end
410 1.19 mhitch * of kernel image and set start_it.
411 1.19 mhitch */
412 1.20 is if ((void *)kp < fmem) {
413 1.20 is printf("Kernel at %08lx, Fastmem used at %08lx\n",
414 1.30 jklos (u_long)kp, (u_long)fmem);
415 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.");
416 1.20 is }
417 1.30 jklos start_it = (void (*)())kp + ksize + 256;
418 1.30 jklos memcpy(start_it, startit, startit_sz);
419 1.19 mhitch CacheClearU();
420 1.19 mhitch printf("*** Loading from %08lx to Fastmem %08lx ***\n",
421 1.30 jklos (u_long)kp, (u_long)fmem);
422 1.19 mhitch sleep(2);
423 1.19 mhitch } else {
424 1.19 mhitch /*
425 1.36 msaitoh * Either the kernel doesn't support loading directly to
426 1.19 mhitch * fastmem or the -Z flag was given. Verify kernel image
427 1.19 mhitch * fits into chipmem.
428 1.19 mhitch */
429 1.19 mhitch if (ksize >= cmemsz) {
430 1.30 jklos printf("Kernel size %ld exceeds Chip Memory of %ld\n",
431 1.19 mhitch ksize, cmemsz);
432 1.19 mhitch err(20, "Insufficient Chip Memory for kernel");
433 1.19 mhitch }
434 1.19 mhitch Z_flag = 1;
435 1.30 jklos printf("*** Loading from %08lx to Chipmem ***\n", (u_long)kp);
436 1.19 mhitch }
437 1.19 mhitch
438 1.12 chopps /*
439 1.12 chopps * if test option set, done
440 1.12 chopps */
441 1.20 is if (t_flag) {
442 1.12 chopps exit(0);
443 1.20 is }
444 1.30 jklos
445 1.12 chopps /*
446 1.12 chopps * XXX AGA startup - may need more
447 1.12 chopps */
448 1.16 chopps LoadView(NULL); /* Don't do this if AGA active? */
449 1.30 jklos start_it(kp, ksize, marks[MARK_ENTRY] - marks[MARK_START], fmem, fmemsz, cmemsz,
450 1.30 jklos boothowto, esym, cpuid, eclock_freq, amiga_flags, I_flag, Z_flag == 0);
451 1.12 chopps /*NOTREACHED*/
452 1.12 chopps }
453 1.1 mw
454 1.1 mw void
455 1.30 jklos get_mem_config(void **fmem, u_long *fmemsz, u_long *cmemsz)
456 1.1 mw {
457 1.12 chopps struct MemHeader *mh, *nmh;
458 1.30 jklos u_int nmem, eseg, segsz, seg, nseg, nsegsz;
459 1.12 chopps char mempri;
460 1.12 chopps
461 1.12 chopps nmem = 0;
462 1.12 chopps mempri = -128;
463 1.12 chopps *fmemsz = 0;
464 1.12 chopps *cmemsz = 0;
465 1.12 chopps
466 1.12 chopps /*
467 1.12 chopps * walk thru the exec memory list
468 1.12 chopps */
469 1.12 chopps Forbid();
470 1.20 is for (mh = (void *) SysBase->MemList.lh_Head;
471 1.20 is nmh = (void *) mh->mh_Node.ln_Succ; mh = nmh) {
472 1.20 is
473 1.20 is nseg = (u_int)mh->mh_Lower;
474 1.20 is nsegsz = (u_int)mh->mh_Upper - nseg;
475 1.20 is
476 1.20 is segsz = nsegsz;
477 1.20 is seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, 0L);
478 1.20 is nsegsz -= segsz, nseg += segsz;
479 1.20 is for (;segsz;
480 1.27 aymeric segsz = nsegsz,
481 1.20 is seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, DMA_Continue),
482 1.20 is nsegsz -= segsz, nseg += segsz, ++nmem) {
483 1.20 is
484 1.20 is if (t_flag)
485 1.20 is printf("Translated %08x sz %08x to %08x sz %08x\n",
486 1.20 is nseg - segsz, nsegsz + segsz, seg, segsz);
487 1.30 jklos
488 1.20 is eseg = seg + segsz;
489 1.20 is
490 1.20 is if ((cpuid >> 24) == 0x7D) {
491 1.20 is /* DraCo MMU table kludge */
492 1.30 jklos
493 1.20 is segsz = ((segsz -1) | 0xfffff) + 1;
494 1.20 is seg = eseg - segsz;
495 1.20 is
496 1.27 aymeric /*
497 1.27 aymeric * Only use first SIMM to boot; we know it is VA==PA.
498 1.20 is * Enter into table and continue. Yes,
499 1.20 is * this is ugly.
500 1.20 is */
501 1.20 is if (seg != 0x40000000) {
502 1.20 is memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes;
503 1.20 is memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri;
504 1.20 is memlist.m_seg[nmem].ms_size = segsz;
505 1.20 is memlist.m_seg[nmem].ms_start = seg;
506 1.20 is ++nmem;
507 1.27 aymeric continue;
508 1.20 is }
509 1.20 is
510 1.20 is memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes;
511 1.20 is memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri;
512 1.20 is memlist.m_seg[nmem].ms_size = DRACOMMUMARGIN;
513 1.20 is memlist.m_seg[nmem].ms_start = seg;
514 1.20 is
515 1.20 is ++nmem;
516 1.20 is seg += DRACOMMUMARGIN;
517 1.30 jklos segsz -= DRACOMMUMARGIN;
518 1.20 is }
519 1.12 chopps
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.30 jklos
525 1.20 is if ((mh->mh_Attributes & (MEMF_CHIP|MEMF_FAST)) == MEMF_CHIP) {
526 1.27 aymeric /*
527 1.27 aymeric * there should hardly be more than one entry for
528 1.27 aymeric * chip mem, but handle it the same nevertheless
529 1.20 is * cmem always starts at 0, so include vector area
530 1.20 is */
531 1.20 is memlist.m_seg[nmem].ms_start = seg = 0;
532 1.20 is /*
533 1.20 is * round to multiple of 512K
534 1.20 is */
535 1.20 is segsz = (segsz + 512 * 1024 - 1) & -(512 * 1024);
536 1.20 is memlist.m_seg[nmem].ms_size = segsz;
537 1.20 is if (segsz > *cmemsz)
538 1.20 is *cmemsz = segsz;
539 1.20 is continue;
540 1.20 is }
541 1.27 aymeric /*
542 1.20 is * some heuristics..
543 1.12 chopps */
544 1.29 thorpej seg &= -AOUT_LDPGSZ;
545 1.29 thorpej eseg = (eseg + AOUT_LDPGSZ - 1) & -AOUT_LDPGSZ;
546 1.30 jklos
547 1.12 chopps /*
548 1.27 aymeric * get the mem back stolen by incore kickstart on
549 1.20 is * A3000 with V36 bootrom.
550 1.12 chopps */
551 1.20 is if (eseg == 0x07f80000)
552 1.20 is eseg = 0x08000000;
553 1.30 jklos
554 1.20 is /*
555 1.20 is * or by zkick on a A2000.
556 1.20 is */
557 1.20 is if (seg == 0x280000 &&
558 1.20 is strcmp(mh->mh_Node.ln_Name, "zkick memory") == 0)
559 1.20 is seg = 0x200000;
560 1.21 is /*
561 1.21 is * or by Fusion Forty fastrom
562 1.21 is */
563 1.21 is if ((seg & ~(1024*1024-1)) == 0x11000000) {
564 1.27 aymeric /*
565 1.21 is * XXX we should test the name.
566 1.21 is * Unfortunately, the memory is just called
567 1.21 is * "32 bit memory" which isn't very specific.
568 1.21 is */
569 1.21 is seg = 0x11000000;
570 1.21 is }
571 1.30 jklos
572 1.20 is segsz = eseg - seg;
573 1.20 is memlist.m_seg[nmem].ms_start = seg;
574 1.12 chopps memlist.m_seg[nmem].ms_size = segsz;
575 1.20 is /*
576 1.20 is * If this segment is smaller than 2M,
577 1.20 is * don't use it to load the kernel
578 1.20 is */
579 1.20 is if (segsz < 2 * 1024 * 1024)
580 1.20 is continue;
581 1.20 is /*
582 1.27 aymeric * if p_flag is set, select memory by priority
583 1.20 is * instead of size
584 1.20 is */
585 1.20 is if ((!p_flag && segsz > *fmemsz) || (p_flag &&
586 1.20 is mempri <= mh->mh_Node.ln_Pri && segsz > *fmemsz)) {
587 1.20 is *fmemsz = segsz;
588 1.20 is *fmem = (void *)seg;
589 1.20 is mempri = mh->mh_Node.ln_Pri;
590 1.20 is }
591 1.12 chopps
592 1.12 chopps }
593 1.1 mw }
594 1.12 chopps memlist.m_nseg = nmem;
595 1.12 chopps Permit();
596 1.1 mw }
597 1.1 mw
598 1.10 chopps /*
599 1.10 chopps * Try to determine the machine ID by searching the resident module list
600 1.10 chopps * for modules only present on specific machines. (Thanks, Bill!)
601 1.10 chopps */
602 1.10 chopps void
603 1.30 jklos get_cpuid(void)
604 1.10 chopps {
605 1.11 chopps cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */
606 1.30 jklos if ((cpuid & AFB_68020) == 0)
607 1.31 wiz err(20, "CPU not supported");
608 1.11 chopps if (cpuid & 0xffff0000) {
609 1.24 is if ((cpuid >> 24) == 0x7D)
610 1.20 is return;
611 1.20 is
612 1.11 chopps switch (cpuid >> 16) {
613 1.11 chopps case 500:
614 1.11 chopps case 600:
615 1.11 chopps case 1000:
616 1.11 chopps case 1200:
617 1.11 chopps case 2000:
618 1.11 chopps case 3000:
619 1.11 chopps case 4000:
620 1.11 chopps return;
621 1.11 chopps default:
622 1.30 jklos printf("machine Amiga %ld is not recognized\n",
623 1.11 chopps cpuid >> 16);
624 1.12 chopps exit(1);
625 1.11 chopps }
626 1.11 chopps }
627 1.18 chopps if (FindResident("A4000 Bonus") || FindResident("A4000 bonus")
628 1.18 chopps || FindResident("A1000 Bonus"))
629 1.16 chopps cpuid |= 4000 << 16;
630 1.16 chopps else if (FindResident("A3000 Bonus") || FindResident("A3000 bonus"))
631 1.16 chopps cpuid |= 3000 << 16;
632 1.16 chopps else if (OpenResource("card.resource")) {
633 1.37 phx UBYTE alicerev = *((UBYTE *)0xdff004) & 0x6f;
634 1.37 phx if (alicerev == 0x22 || alicerev == 0x23)
635 1.37 phx cpuid |= 1200 << 16; /* AGA + PCMCIA = A1200 */
636 1.37 phx else
637 1.37 phx cpuid |= 600 << 16; /* noAGA + PCMCIA = A600 */
638 1.20 is } else if (OpenResource("draco.resource")) {
639 1.20 is cpuid |= (32000 | DRACOREVISION) << 16;
640 1.10 chopps }
641 1.12 chopps /*
642 1.12 chopps * Nothing found, it's probably an A2000 or A500
643 1.12 chopps */
644 1.16 chopps if ((cpuid >> 16) == 0)
645 1.10 chopps cpuid |= 2000 << 16;
646 1.10 chopps }
647 1.1 mw
648 1.12 chopps void
649 1.30 jklos get_eclock(void)
650 1.12 chopps {
651 1.12 chopps /* Fix for 1.3 startups? */
652 1.14 chopps if (SysBase->LibNode.lib_Version > 36)
653 1.14 chopps eclock_freq = SysBase->ex_EClockFrequency;
654 1.14 chopps else
655 1.14 chopps eclock_freq = (GfxBase->DisplayFlags & PAL) ?
656 1.14 chopps 709379 : 715909;
657 1.14 chopps }
658 1.14 chopps
659 1.14 chopps void
660 1.30 jklos get_AGA(void)
661 1.14 chopps {
662 1.14 chopps /*
663 1.14 chopps * Determine if an AGA mode is active
664 1.14 chopps */
665 1.12 chopps }
666 1.12 chopps
667 1.33 perry __asm("
668 1.1 mw .text
669 1.1 mw
670 1.1 mw _startit:
671 1.1 mw movel sp,a3
672 1.1 mw movel 4:w,a6
673 1.20 is lea pc@(start_super),a5
674 1.1 mw jmp a6@(-0x1e) | supervisor-call
675 1.1 mw
676 1.1 mw start_super:
677 1.1 mw movew #0x2700,sr
678 1.1 mw
679 1.1 mw | the BSD kernel wants values into the following registers:
680 1.1 mw | a0: fastmem-start
681 1.1 mw | d0: fastmem-size
682 1.1 mw | d1: chipmem-size
683 1.16 chopps | d3: Amiga specific flags
684 1.12 chopps | d4: E clock frequency
685 1.5 mw | d5: AttnFlags (cpuid)
686 1.3 mw | d7: boothowto
687 1.8 chopps | a4: esym location
688 1.17 jtc | a2: Inhibit sync flags
689 1.10 chopps | All other registers zeroed for possible future requirements.
690 1.1 mw
691 1.20 is lea pc@(_startit),sp | make sure we have a good stack ***
692 1.20 is
693 1.1 mw movel a3@(4),a1 | loaded kernel
694 1.1 mw movel a3@(8),d2 | length of loaded kernel
695 1.14 chopps | movel a3@(12),sp | entry point in stack pointer
696 1.20 is movel a3@(12),a6 | push entry point ***
697 1.1 mw movel a3@(16),a0 | fastmem-start
698 1.1 mw movel a3@(20),d0 | fastmem-size
699 1.1 mw movel a3@(24),d1 | chipmem-size
700 1.3 mw movel a3@(28),d7 | boothowto
701 1.8 chopps movel a3@(32),a4 | esym
702 1.10 chopps movel a3@(36),d5 | cpuid
703 1.12 chopps movel a3@(40),d4 | E clock frequency
704 1.16 chopps movel a3@(44),d3 | Amiga flags
705 1.17 jtc movel a3@(48),a2 | Inhibit sync flags
706 1.19 mhitch movel a3@(52),d6 | Load to fastmem flag
707 1.8 chopps subl a5,a5 | target, load to 0
708 1.1 mw
709 1.20 is cmpb #0x7D,a3@(36) | is it DraCo?
710 1.20 is beq nott | yes, switch off MMU later
711 1.20 is
712 1.20 is | no, it is an Amiga:
713 1.20 is
714 1.20 is | movew #0xf00,0xdff180 |red
715 1.20 is | moveb #0,0x200003c8
716 1.20 is | moveb #63,0x200003c9
717 1.20 is | moveb #0,0x200003c9
718 1.20 is | moveb #0,0x200003c9
719 1.20 is
720 1.20 is movew #(1<<9),0xdff096 | disable DMA on Amigas.
721 1.20 is
722 1.20 is | ------ mmu off start -----
723 1.20 is
724 1.20 is btst #3,d5 | AFB_68040,SysBase->AttnFlags
725 1.5 mw beq not040
726 1.5 mw
727 1.20 is | Turn off 68040/060 MMU
728 1.5 mw
729 1.20 is subl a3,a3
730 1.20 is .word 0x4e7b,0xb003 | movec a3,tc
731 1.20 is .word 0x4e7b,0xb806 | movec a3,urp
732 1.20 is .word 0x4e7b,0xb807 | movec a3,srp
733 1.20 is .word 0x4e7b,0xb004 | movec a3,itt0
734 1.20 is .word 0x4e7b,0xb005 | movec a3,itt1
735 1.20 is .word 0x4e7b,0xb006 | movec a3,dtt0
736 1.20 is .word 0x4e7b,0xb007 | movec a3,dtt1
737 1.5 mw bra nott
738 1.5 mw
739 1.5 mw not040:
740 1.20 is lea pc@(zero),a3
741 1.1 mw pmove a3@,tc | Turn off MMU
742 1.20 is lea pc@(nullrp),a3
743 1.1 mw pmove a3@,crp | Turn off MMU some more
744 1.1 mw pmove a3@,srp | Really, really, turn off MMU
745 1.1 mw
746 1.1 mw | Turn off 68030 TT registers
747 1.1 mw
748 1.20 is btst #2,d5 | AFB_68030,SysBase->AttnFlags
749 1.1 mw beq nott | Skip TT registers if not 68030
750 1.20 is lea pc@(zero),a3
751 1.1 mw .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..)
752 1.1 mw .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..)
753 1.1 mw
754 1.1 mw nott:
755 1.20 is | ---- mmu off end ----
756 1.20 is | movew #0xf60,0xdff180 | orange
757 1.20 is | moveb #0,0x200003c8
758 1.20 is | moveb #63,0x200003c9
759 1.20 is | moveb #24,0x200003c9
760 1.20 is | moveb #0,0x200003c9
761 1.1 mw
762 1.20 is | ---- copy kernel start ----
763 1.1 mw
764 1.19 mhitch tstl d6 | Can we load to fastmem?
765 1.19 mhitch beq L0 | No, leave destination at 0
766 1.19 mhitch movl a0,a5 | Move to start of fastmem chunk
767 1.20 is addl a0,a6 | relocate kernel entry point
768 1.1 mw L0:
769 1.19 mhitch movl a1@+,a5@+
770 1.19 mhitch subl #4,d2
771 1.1 mw bcc L0
772 1.1 mw
773 1.30 jklos lea pc@(ckend),a1
774 1.20 is movl a5,sp@-
775 1.20 is movl #_startit_end - ckend,d2
776 1.20 is L2:
777 1.20 is movl a1@+,a5@+
778 1.20 is subl #4,d2
779 1.20 is bcc L2
780 1.20 is
781 1.20 is btst #3,d5
782 1.20 is jeq L1
783 1.20 is .word 0xf4f8
784 1.30 jklos L1:
785 1.30 jklos movql #0,d2 | switch off cache to ensure we use
786 1.20 is movec d2,cacr | valid kernel data
787 1.20 is
788 1.20 is | movew #0xFF0,0xdff180 | yellow
789 1.20 is | moveb #0,0x200003c8
790 1.20 is | moveb #63,0x200003c9
791 1.20 is | moveb #0,0x200003c9
792 1.20 is | moveb #0,0x200003c9
793 1.20 is rts
794 1.20 is
795 1.21 is | ---- copy kernel end ----
796 1.20 is
797 1.20 is ckend:
798 1.20 is | movew #0x0ff,0xdff180 | petrol
799 1.20 is | moveb #0,0x200003c8
800 1.20 is | moveb #0,0x200003c9
801 1.20 is | moveb #63,0x200003c9
802 1.20 is | moveb #63,0x200003c9
803 1.20 is
804 1.20 is movl d5,d2
805 1.20 is roll #8,d2
806 1.20 is cmpb #0x7D,d2
807 1.20 is jne noDraCo
808 1.20 is
809 1.20 is | DraCo: switch off MMU now:
810 1.20 is
811 1.20 is subl a3,a3
812 1.20 is .word 0x4e7b,0xb003 | movec a3,tc
813 1.20 is .word 0x4e7b,0xb806 | movec a3,urp
814 1.20 is .word 0x4e7b,0xb807 | movec a3,srp
815 1.20 is .word 0x4e7b,0xb004 | movec a3,itt0
816 1.20 is .word 0x4e7b,0xb005 | movec a3,itt1
817 1.20 is .word 0x4e7b,0xb006 | movec a3,dtt0
818 1.20 is .word 0x4e7b,0xb007 | movec a3,dtt1
819 1.30 jklos
820 1.20 is noDraCo:
821 1.9 chopps moveq #0,d2 | zero out unused registers
822 1.14 chopps moveq #0,d6 | (might make future compatibility
823 1.14 chopps movel d6,a1 | would have known contents)
824 1.9 chopps movel d6,a3
825 1.9 chopps movel d6,a5
826 1.20 is movel a6,sp | entry point into stack pointer
827 1.9 chopps movel d6,a6
828 1.20 is
829 1.20 is | movew #0x0F0,0xdff180 | green
830 1.20 is | moveb #0,0x200003c8
831 1.20 is | moveb #0,0x200003c9
832 1.20 is | moveb #63,0x200003c9
833 1.20 is | moveb #0,0x200003c9
834 1.20 is
835 1.20 is jmp sp@ | jump to kernel entry point
836 1.1 mw
837 1.1 mw | A do-nothing MMU root pointer (includes the following long as well)
838 1.1 mw
839 1.1 mw nullrp: .long 0x7fff0001
840 1.1 mw zero: .long 0
841 1.1 mw
842 1.19 mhitch _startit_end:
843 1.1 mw
844 1.30 jklos .data
845 1.30 jklos _startit_sz: .long _startit_end-_startit
846 1.30 jklos
847 1.30 jklos .text
848 1.1 mw ");
849 1.1 mw
850 1.12 chopps void
851 1.30 jklos usage(void)
852 1.6 chopps {
853 1.35 mhitch fprintf(stderr, "usage: %s [-abhkpstACDSVZ] [-c machine] [-m mem] [-n mode] [-I sync-inhibit] kernel\n",
854 1.12 chopps program_name);
855 1.12 chopps exit(1);
856 1.6 chopps }
857 1.6 chopps
858 1.12 chopps void
859 1.30 jklos verbose_usage(void)
860 1.12 chopps {
861 1.37 phx fprintf(stderr, "\n\
862 1.37 phx NAME\n\
863 1.37 phx \t%s - loads NetBSD from amiga dos.\n\
864 1.37 phx SYNOPSIS\n\
865 1.37 phx \t%s [-abhkpstADSVZ] [-c machine] [-m mem] [-n flags] [-I sync-inhibit] kernel\n\
866 1.37 phx OPTIONS\n\
867 1.37 phx \t-a Boot up to multiuser mode.\n\
868 1.37 phx \t-A Use AGA display mode, if available.\n\
869 1.37 phx \t-b Ask for which root device.\n\
870 1.37 phx \t Its possible to have multiple roots and choose between them.\n\
871 1.37 phx \t-c Set machine type. [e.g 3000; use 32000+N for DraCo rev. N]\n\
872 1.37 phx \t-C Use Serial Console.\n\
873 1.37 phx \t-D Enter debugger\n\
874 1.37 phx \t-h This help message.\n\
875 1.37 phx \t-I Inhibit sync negotiation. Option value is bit-encoded targets.\n\
876 1.37 phx \t-k Reserve the first 4M of fast mem [Some one else\n\
877 1.37 phx \t is going to have to answer what that it is used for].\n\
878 1.37 phx \t-m Tweak amount of available memory, for finding minimum amount\n\
879 1.37 phx \t of memory required to run. Sets fastmem size to specified\n\
880 1.37 phx \t size in Kbytes.\n\
881 1.37 phx \t-n Enable multiple non-contiguous memory: value = 0 (disabled),\n\
882 1.37 phx \t 1 (two segments), 2 (all avail segments), 3 (same as 2?).\n\
883 1.37 phx \t-p Use highest priority fastmem segement instead of the largest\n\
884 1.37 phx \t segment. The higher priority segment is usually faster\n\
885 1.37 phx \t (i.e. 32 bit memory), but some people have smaller amounts\n\
886 1.37 phx \t of 32 bit memory.\n\
887 1.37 phx \t-q Boot up in quiet mode.\n\
888 1.37 phx \t-s Boot up in singleuser mode (default).\n\
889 1.37 phx \t-S Include kernel symbol table.\n\
890 1.37 phx \t-t This is a *test* option. It prints out the memory\n\
891 1.37 phx \t list information being passed to the kernel and also\n\
892 1.37 phx \t exits without actually starting NetBSD.\n\
893 1.37 phx \t-v Boot up in verbose mode.\n\
894 1.37 phx \t-V Version of loadbsd program.\n\
895 1.37 phx \t-Z Force kernel load to chipmem.\n\
896 1.37 phx HISTORY\n\
897 1.12 chopps \tThis version supports Kernel version 720 +\n",
898 1.12 chopps program_name, program_name);
899 1.12 chopps exit(1);
900 1.12 chopps }
901 1.12 chopps
902 1.30 jklos static void
903 1.30 jklos _Vdomessage(int doerrno, const char *fmt, va_list args)
904 1.12 chopps {
905 1.12 chopps fprintf(stderr, "%s: ", program_name);
906 1.12 chopps if (fmt) {
907 1.12 chopps vfprintf(stderr, fmt, args);
908 1.12 chopps fprintf(stderr, ": ");
909 1.12 chopps }
910 1.37 phx if (doerrno) {
911 1.12 chopps fprintf(stderr, "%s", strerror(errno));
912 1.12 chopps }
913 1.12 chopps fprintf(stderr, "\n");
914 1.12 chopps }
915 1.12 chopps
916 1.12 chopps void
917 1.12 chopps err(int eval, const char *fmt, ...)
918 1.12 chopps {
919 1.12 chopps va_list ap;
920 1.12 chopps va_start(ap, fmt);
921 1.30 jklos _Vdomessage(1, fmt, ap);
922 1.30 jklos va_end(ap);
923 1.30 jklos exit(eval);
924 1.12 chopps }
925 1.12 chopps
926 1.30 jklos #if 0
927 1.12 chopps void
928 1.12 chopps errx(int eval, const char *fmt, ...)
929 1.12 chopps {
930 1.12 chopps va_list ap;
931 1.12 chopps va_start(ap, fmt);
932 1.30 jklos _Vdomessage(0, fmt, ap);
933 1.30 jklos va_end(ap);
934 1.30 jklos exit(eval);
935 1.12 chopps }
936 1.30 jklos #endif
937 1.12 chopps
938 1.12 chopps void
939 1.12 chopps warn(const char *fmt, ...)
940 1.12 chopps {
941 1.12 chopps va_list ap;
942 1.12 chopps va_start(ap, fmt);
943 1.30 jklos _Vdomessage(1, fmt, ap);
944 1.12 chopps va_end(ap);
945 1.12 chopps }
946 1.12 chopps
947 1.30 jklos #if 0
948 1.12 chopps void
949 1.12 chopps warnx(const char *fmt, ...)
950 1.6 chopps {
951 1.12 chopps va_list ap;
952 1.12 chopps va_start(ap, fmt);
953 1.30 jklos _Vdomessage(0, fmt, ap);
954 1.12 chopps va_end(ap);
955 1.20 is }
956 1.30 jklos #endif
957