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