bootmain.c revision 1.5.2.4 1 1.5.2.4 skrll /* $NetBSD: bootmain.c,v 1.5.2.4 2005/11/10 14:00:15 skrll Exp $ */
2 1.1 minoura
3 1.1 minoura /*-
4 1.1 minoura * Copyright (c) 1993, 1994 Takumi Nakamura.
5 1.1 minoura * Copyright (c) 1999, 2000 Itoh Yasufumi.
6 1.1 minoura * Copyright (c) 2001 Minoura Makoto.
7 1.1 minoura *
8 1.1 minoura * Redistribution and use in source and binary forms, with or without
9 1.1 minoura * modification, are permitted provided that the following conditions
10 1.1 minoura * are met:
11 1.1 minoura * 1. Redistributions of source code must retain the above copyright
12 1.1 minoura * notice, this list of conditions and the following disclaimer.
13 1.1 minoura * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 minoura * notice, this list of conditions and the following disclaimer in the
15 1.1 minoura * documentation and/or other materials provided with the distribution.
16 1.1 minoura * 3. All advertising materials mentioning features or use of this software
17 1.1 minoura * must display the following acknowledgement:
18 1.1 minoura * This product includes software developed by Takumi Nakamura.
19 1.1 minoura * 4. Neither the name of the University nor the names of its contributors
20 1.1 minoura * may be used to endorse or promote products derived from this software
21 1.1 minoura * without specific prior written permission.
22 1.1 minoura *
23 1.1 minoura * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 minoura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 minoura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 minoura * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 minoura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 minoura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 minoura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 minoura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 minoura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 minoura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 minoura * SUCH DAMAGE.
34 1.1 minoura */
35 1.1 minoura
36 1.1 minoura #include <sys/param.h>
37 1.1 minoura #include <sys/reboot.h>
38 1.1 minoura #include <sys/types.h>
39 1.1 minoura #include <sys/exec_aout.h>
40 1.1 minoura #include <ufs/ufs/dinode.h>
41 1.1 minoura #include <ufs/ffs/fs.h>
42 1.1 minoura #include <ufs/ufs/dir.h>
43 1.1 minoura #include <machine/bootinfo.h>
44 1.1 minoura #ifdef SCSI_ADHOC_BOOTPART
45 1.1 minoura #include <machine/disklabel.h>
46 1.1 minoura #endif
47 1.5.2.1 skrll #include <lib/libsa/stand.h>
48 1.1 minoura
49 1.1 minoura #include "boot_ufs.h"
50 1.1 minoura #include "readufs.h"
51 1.1 minoura #include "exec_image.h"
52 1.1 minoura #include "../../x68k/iodevice.h"
53 1.1 minoura #define IODEVbase ((volatile struct IODEVICE *)PHYS_IODEV)
54 1.1 minoura
55 1.1 minoura /* for debug; */
56 1.1 minoura unsigned int startregs[16];
57 1.1 minoura
58 1.1 minoura #ifdef SCSI_ADHOC_BOOTPART
59 1.1 minoura static int get_scsi_part (void);
60 1.1 minoura #endif
61 1.1 minoura #ifdef BOOT_DEBUG
62 1.1 minoura static int get_scsi_host_adapter (char *);
63 1.1 minoura #else
64 1.1 minoura static int get_scsi_host_adapter (void);
65 1.1 minoura #endif
66 1.1 minoura
67 1.1 minoura #ifdef BOOT_DEBUG
68 1.1 minoura void print_hex (unsigned int, int);
69 1.1 minoura #endif
70 1.1 minoura
71 1.1 minoura static int load_file (const char*, unsigned int, struct exec *);
72 1.5.2.4 skrll static int load_file_ino (ino32_t, const char*, unsigned int, struct exec *);
73 1.1 minoura
74 1.1 minoura void bootufs (void) __attribute__ ((__noreturn__));
75 1.1 minoura
76 1.1 minoura #ifdef BOOT_DEBUG
77 1.1 minoura void
78 1.1 minoura print_hex(x, l)
79 1.1 minoura unsigned int x; /* */
80 1.1 minoura int l; /* */
81 1.1 minoura {
82 1.1 minoura
83 1.1 minoura if (l > 0) {
84 1.1 minoura print_hex(x >> 4, l - 1);
85 1.1 minoura x &= 0x0F;
86 1.1 minoura if (x > 9)
87 1.1 minoura x += 7;
88 1.1 minoura B_PUTC((unsigned int) '0' + x);
89 1.1 minoura }
90 1.1 minoura }
91 1.1 minoura #endif
92 1.1 minoura
93 1.1 minoura #ifdef SCSI_ADHOC_BOOTPART
94 1.1 minoura /*
95 1.1 minoura * get partition # from partition start position
96 1.1 minoura */
97 1.1 minoura
98 1.1 minoura #define NPART 15
99 1.1 minoura #define PARTTBL_TOP ((unsigned)4) /* pos of part inf in 512byte-blocks */
100 1.1 minoura #define MAXPART 6
101 1.1 minoura const unsigned char partition_conv[MAXPART + 1] = { 0, 1, 3, 4, 5, 6, 7 };
102 1.1 minoura
103 1.1 minoura static int
104 1.1 minoura get_scsi_part()
105 1.1 minoura {
106 1.1 minoura struct {
107 1.1 minoura u_int32_t magic; /* 0x5836384B ("X68K") */
108 1.1 minoura u_int32_t parttotal;
109 1.1 minoura u_int32_t diskblocks;
110 1.1 minoura u_int32_t diskblocks2; /* backup? */
111 1.1 minoura struct dos_partition parttbl[NPART];
112 1.1 minoura unsigned char formatstr[256];
113 1.1 minoura unsigned char rest[512];
114 1.1 minoura } partbuf;
115 1.1 minoura int i;
116 1.1 minoura u_int32_t part_top;
117 1.1 minoura
118 1.1 minoura #ifdef BOOT_DEBUG
119 1.1 minoura B_PRINT("seclen: ");
120 1.1 minoura print_hex(SCSI_BLKLEN, 8); /* 0: 256, 1: 512, 2: 1024 */
121 1.1 minoura B_PRINT(", topsec: ");
122 1.1 minoura print_hex(SCSI_PARTTOP, 8); /* partition top in sector */
123 1.1 minoura #endif
124 1.1 minoura /*
125 1.1 minoura * read partition table
126 1.1 minoura */
127 1.1 minoura RAW_READ0(&partbuf, PARTTBL_TOP, sizeof partbuf);
128 1.1 minoura
129 1.1 minoura part_top = SCSI_PARTTOP >> (2 - SCSI_BLKLEN);
130 1.1 minoura for (i = 0; i < MAXPART; i++)
131 1.1 minoura if ((u_int32_t) partbuf.parttbl[i].dp_start == part_top)
132 1.1 minoura goto found;
133 1.1 minoura
134 1.1 minoura BOOT_ERROR("Can't boot from this partition");
135 1.1 minoura /* NOTREACHED */
136 1.1 minoura found:
137 1.1 minoura #ifdef BOOT_DEBUG
138 1.1 minoura B_PRINT("; sd");
139 1.1 minoura B_PUTC(ID + '0'); /* SCSI ID (not NetBSD unit #) */
140 1.1 minoura B_PUTC((unsigned int) partition_conv[i] + 'a');
141 1.1 minoura B_PRINT("\r\n");
142 1.1 minoura #endif
143 1.1 minoura return partition_conv[i];
144 1.1 minoura }
145 1.1 minoura #endif /* SCSI_ADHOC_BOOTPART */
146 1.1 minoura
147 1.1 minoura /*
148 1.1 minoura * Check the type of SCSI interface
149 1.1 minoura */
150 1.1 minoura #ifdef BOOT_DEBUG
151 1.1 minoura static int
152 1.1 minoura get_scsi_host_adapter(devstr)
153 1.1 minoura char *devstr;
154 1.1 minoura #else
155 1.1 minoura static int
156 1.1 minoura get_scsi_host_adapter(void)
157 1.1 minoura #endif
158 1.1 minoura {
159 1.1 minoura char *bootrom;
160 1.1 minoura int ha;
161 1.1 minoura
162 1.1 minoura #ifdef BOOT_DEBUG
163 1.1 minoura B_PRINT(" at ");
164 1.1 minoura *(int *)devstr = '/' << 24 | 's' << 16 | 'p' << 8 | 'c';
165 1.1 minoura *(int *)(devstr + 4) = '@' << 24 | '0' << 16 | '/' << 8 | 's';
166 1.1 minoura *(int *)(devstr + 8) = 'd' << 24 | '@' << 16 | '0' << 8 | ',';
167 1.1 minoura *(int *)(devstr + 12) = '0' << 24 | ':' << 16 | 'a' << 8 | '\0';
168 1.1 minoura #endif
169 1.1 minoura
170 1.1 minoura bootrom = (char *) (BOOT_INFO & 0x00ffffe0);
171 1.1 minoura /*
172 1.1 minoura * bootrom+0x24 "SCSIIN" ... Internal SCSI (spc@0)
173 1.1 minoura * "SCSIEX" ... External SCSI (spc@1 or mha@0)
174 1.1 minoura */
175 1.1 minoura if (*(u_short *)(bootrom + 0x24 + 4) == 0x494e) { /* "IN" */
176 1.1 minoura #ifdef BOOT_DEBUG
177 1.1 minoura B_PRINT("spc0");
178 1.1 minoura #endif
179 1.1 minoura ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
180 1.1 minoura } else if (badbaddr(&IODEVbase->io_exspc.bdid)) {
181 1.1 minoura #ifdef BOOT_DEBUG
182 1.1 minoura B_PRINT("mha0");
183 1.1 minoura #endif
184 1.1 minoura ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
185 1.1 minoura #ifdef BOOT_DEBUG
186 1.1 minoura *(int *)devstr = '/' << 24 | 'm' << 16 | 'h' << 8 | 'a';
187 1.1 minoura #endif
188 1.1 minoura } else {
189 1.1 minoura #ifdef BOOT_DEBUG
190 1.1 minoura B_PRINT("spc1");
191 1.1 minoura #endif
192 1.1 minoura ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
193 1.1 minoura #ifdef BOOT_DEBUG
194 1.1 minoura devstr[5] = '1';
195 1.1 minoura #endif
196 1.1 minoura }
197 1.1 minoura
198 1.1 minoura return ha;
199 1.1 minoura }
200 1.1 minoura
201 1.1 minoura static int
202 1.1 minoura load_file(path, addr, header)
203 1.1 minoura const char *path;
204 1.1 minoura unsigned int addr;
205 1.1 minoura struct exec *header;
206 1.1 minoura {
207 1.1 minoura
208 1.1 minoura return load_file_ino(ufs_lookup_path(path), path, addr, header);
209 1.1 minoura }
210 1.1 minoura
211 1.1 minoura static int
212 1.1 minoura load_file_ino(ino, fn, addr, header)
213 1.5.2.4 skrll ino32_t ino;
214 1.1 minoura const char *fn; /* for message only */
215 1.1 minoura unsigned int addr;
216 1.1 minoura struct exec *header;
217 1.1 minoura {
218 1.5 itohy union ufs_dinode dinode;
219 1.1 minoura
220 1.1 minoura /* look-up the file */
221 1.1 minoura if (ino == 0 || ufs_get_inode(ino, &dinode)) {
222 1.1 minoura B_PRINT(fn);
223 1.1 minoura B_PRINT(": not found\r\n");
224 1.1 minoura return 0;
225 1.1 minoura }
226 1.1 minoura
227 1.1 minoura ufs_read(&dinode, (void *)addr, 0, sizeof(struct exec));
228 1.1 minoura memcpy(header, (void *)addr, sizeof(struct exec));
229 1.1 minoura
230 1.1 minoura if ((N_GETMAGIC(*header) != OMAGIC) ||
231 1.1 minoura (N_GETMID(*header) != MID_M68K)) {
232 1.1 minoura B_PRINT(fn);
233 1.1 minoura B_PRINT(": inappropriate format");
234 1.1 minoura return 0;
235 1.1 minoura }
236 1.1 minoura
237 1.1 minoura /* read text and data */
238 1.2 minoura ufs_read(&dinode, ((char *)addr)-sizeof(struct exec), 0,/* XXX */
239 1.1 minoura header->a_text+header->a_data);
240 1.1 minoura
241 1.1 minoura /* clear out bss */
242 1.1 minoura memset((char*) addr + header->a_text+header->a_data,
243 1.1 minoura 0, header->a_bss);
244 1.1 minoura
245 1.1 minoura /* PLANNED: fallback NMAGIC loader for the kernel. */
246 1.1 minoura
247 1.1 minoura /* return the image size. */
248 1.1 minoura return header->a_text+header->a_data+header->a_bss;
249 1.1 minoura }
250 1.1 minoura
251 1.1 minoura
252 1.1 minoura void
253 1.1 minoura bootufs(void)
254 1.1 minoura {
255 1.1 minoura int bootdev;
256 1.1 minoura #ifdef BOOT_DEBUG
257 1.1 minoura int i;
258 1.1 minoura char bootdevstr[16];
259 1.1 minoura #endif
260 1.1 minoura struct exec header;
261 1.1 minoura int size;
262 1.3 minoura extern const char bootprog_name[], bootprog_rev[];
263 1.1 minoura
264 1.1 minoura #ifdef BOOT_DEBUG
265 1.1 minoura /* for debug; */
266 1.1 minoura for (i = 0; i < 16; i++) {
267 1.1 minoura print_hex(startregs[i], 8);
268 1.1 minoura B_PRINT((i & 7) == 7 ? "\r\n" : " ");
269 1.1 minoura }
270 1.1 minoura #endif
271 1.3 minoura
272 1.3 minoura B_PRINT(bootprog_name);
273 1.3 minoura B_PRINT(" rev."); B_PRINT(bootprog_rev);
274 1.3 minoura B_PRINT("\r\n");
275 1.1 minoura
276 1.1 minoura /*
277 1.1 minoura * get boot device
278 1.1 minoura */
279 1.1 minoura if (BINF_ISFD(&BOOT_INFO)) {
280 1.1 minoura /* floppy */
281 1.1 minoura #ifdef BOOT_DEBUG
282 1.1 minoura *(int *)bootdevstr = ('f' << 24 | 'd' << 16 | '@' << 8 | '0') +
283 1.1 minoura (BOOT_INFO & 3);
284 1.1 minoura bootdevstr[4] = '\0';
285 1.1 minoura #endif
286 1.1 minoura bootdev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, BOOT_INFO & 3,
287 1.1 minoura (FDSECMINMAX.minsec.N == 3) ? 0 : 2);
288 1.1 minoura } else {
289 1.1 minoura /* SCSI */
290 1.1 minoura int part, ha;
291 1.1 minoura
292 1.1 minoura #ifdef SCSI_ADHOC_BOOTPART
293 1.4 minoura if (SCSI_PARTTOP == 0)
294 1.4 minoura part = 0;
295 1.4 minoura else
296 1.4 minoura part = get_scsi_part();
297 1.1 minoura #else
298 1.1 minoura part = 0; /* sd?a only */
299 1.1 minoura #endif
300 1.1 minoura #ifndef BOOT_DEBUG
301 1.1 minoura ha = get_scsi_host_adapter();
302 1.1 minoura #else
303 1.1 minoura ha = get_scsi_host_adapter(bootdevstr);
304 1.1 minoura bootdevstr[10] = '0' + (ID & 7);
305 1.1 minoura bootdevstr[14] = 'a' + part;
306 1.1 minoura #endif
307 1.1 minoura bootdev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD, ha >> 4, ha & 15,
308 1.1 minoura ID & 7, 0, part);
309 1.1 minoura }
310 1.1 minoura #ifdef BOOT_DEBUG
311 1.1 minoura B_PRINT("boot device: ");
312 1.1 minoura B_PRINT(bootdevstr);
313 1.1 minoura #endif
314 1.1 minoura B_PRINT("\r\n");
315 1.1 minoura
316 1.1 minoura /* initialize filesystem code */
317 1.1 minoura if (ufs_init()) {
318 1.1 minoura BOOT_ERROR("bogus super block: "
319 1.1 minoura "");
320 1.1 minoura /* NOTREACHED */
321 1.1 minoura }
322 1.1 minoura #if defined(BOOT_DEBUG) && defined(USE_FFS) && defined(USE_LFS)
323 1.1 minoura B_PRINT("file system: ");
324 1.1 minoura B_PUTC(ufs_info.fstype == UFSTYPE_FFS ?
325 1.1 minoura (unsigned int) 'F' : (unsigned int) 'L');
326 1.1 minoura B_PRINT("FS\r\n");
327 1.1 minoura #endif
328 1.1 minoura
329 1.1 minoura #ifdef BOOT_DEBUG
330 1.1 minoura B_PRINT("\r\nlooking up secondary boot... ");
331 1.1 minoura #endif
332 1.1 minoura
333 1.1 minoura /*
334 1.1 minoura * Look for the 2nd stage boot.
335 1.1 minoura */
336 1.1 minoura
337 1.1 minoura /* Try "boot" first */
338 1.1 minoura size = load_file("boot", BOOT_TEXTADDR, &header);
339 1.1 minoura #ifdef BOOT_DEBUG
340 1.1 minoura B_PRINT("done.\r\n");
341 1.1 minoura #endif
342 1.1 minoura if (size > 0)
343 1.1 minoura exec_image(BOOT_TEXTADDR, /* image loaded at */
344 1.1 minoura BOOT_TEXTADDR, /* image executed at */
345 1.1 minoura header.a_entry, /* entry point */
346 1.1 minoura size, /* image size */
347 1.1 minoura bootdev, RB_SINGLE); /* arguments */
348 1.1 minoura
349 1.1 minoura B_PRINT("can't load the secondary bootstrap.;"
350 1.1 minoura "trying /netbsd...\r\n");
351 1.1 minoura
352 1.1 minoura /* fallback to /netbsd. */
353 1.1 minoura /* always fails since NMAGIC loader is not yet implemented. */
354 1.1 minoura
355 1.1 minoura size = load_file("netbsd", 0x6000, &header);
356 1.1 minoura if (size > 0) {
357 1.1 minoura if (*((short *)(0x6000 + header.a_entry - 2)) != 0) {
358 1.1 minoura B_PRINT("boot interface of /netbsd is too new!\r\n");
359 1.1 minoura goto fail;
360 1.1 minoura }
361 1.1 minoura exec_image(0x6000, /* image loaded at */
362 1.1 minoura 0, /* image executed at */
363 1.1 minoura header.a_entry, /* entry point */
364 1.1 minoura size, /* image size */
365 1.1 minoura bootdev, RB_SINGLE); /* arguments */
366 1.1 minoura /* NOTREACHED */
367 1.1 minoura }
368 1.1 minoura
369 1.1 minoura fail:
370 1.1 minoura BOOT_ERROR("can't load the secondary bootstrap nor the kernel.");
371 1.1 minoura /* NOTREACHED */
372 1.1 minoura }
373