1 /* $NetBSD: bootmain.c,v 1.11 2009/03/14 21:04:17 dsl Exp $ */
4 * Copyright (c) 1993, 1994 Takumi Nakamura.
5 * Copyright (c) 1999, 2000 Itoh Yasufumi.
6 * Copyright (c) 2001 Minoura Makoto.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
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>
48 #include <lib/libsa/stand.h>
52 #include "exec_image.h"
53 #include "../../x68k/iodevice.h"
54 #define IODEVbase ((volatile struct IODEVICE *)INTIOBASE)
56 /* for debug; µ¯Æ°»þ¤Î¥ì¥¸¥¹¥¿¤¬Æþ¤Ã¤Æ¤¤¤ë */
57 unsigned int startregs
[16];
59 #ifdef SCSI_ADHOC_BOOTPART
60 static int get_scsi_part (void);
63 static int get_scsi_host_adapter (char *);
65 static int get_scsi_host_adapter (void);
69 void print_hex (unsigned int, int);
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
*);
75 void bootufs (void) __attribute__ ((__noreturn__
));
79 print_hex(unsigned int x
, int l
)
85 print_hex(x
>> 4, l
- 1);
89 B_PUTC((unsigned int) '0' + x
);
94 #ifdef SCSI_ADHOC_BOOTPART
96 * get partition # from partition start position
100 #define PARTTBL_TOP ((unsigned)4) /* pos of part inf in 512byte-blocks */
102 const unsigned char partition_conv
[MAXPART
+ 1] = { 0, 1, 3, 4, 5, 6, 7 };
108 u_int32_t magic
; /* 0x5836384B ("X68K") */
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];
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 */
126 * read partition table
128 RAW_READ0(&partbuf
, PARTTBL_TOP
, sizeof partbuf
);
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
)
135 BOOT_ERROR("Can't boot from this partition");
140 B_PUTC(ID
+ '0'); /* SCSI ID (not NetBSD unit #) */
141 B_PUTC((unsigned int) partition_conv
[i
] + 'a');
144 return partition_conv
[i
];
146 #endif /* SCSI_ADHOC_BOOTPART */
149 * Check the type of SCSI interface
153 get_scsi_host_adapter(devstr
)
157 get_scsi_host_adapter(void)
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';
171 bootrom
= (char *) (BOOT_INFO
& 0x00ffffe0);
173 * bootrom+0x24 "SCSIIN" ... Internal SCSI (spc@0)
174 * "SCSIEX" ... External SCSI (spc@1 or mha@0)
176 if (*(u_short
*)(bootrom
+ 0x24 + 4) == 0x494e) { /* "IN" */
180 ha
= (X68K_BOOT_SCSIIF_SPC
<< 4) | 0;
181 } else if (badbaddr(&IODEVbase
->io_exspc
.bdid
)) {
185 ha
= (X68K_BOOT_SCSIIF_MHA
<< 4) | 0;
187 *(int *)devstr
= '/' << 24 | 'm' << 16 | 'h' << 8 | 'a';
193 ha
= (X68K_BOOT_SCSIIF_SPC
<< 4) | 1;
203 load_file(const char *path
, unsigned int addr
, struct exec
*header
)
206 return load_file_ino(ufs_lookup_path(path
), path
, addr
, header
);
210 load_file_ino(ino32_t ino
, const char *fn
, unsigned int addr
, struct exec
*header
)
211 /* fn: for message only */
213 union ufs_dinode dinode
;
215 /* look-up the file */
216 if (ino
== 0 || ufs_get_inode(ino
, &dinode
)) {
218 B_PRINT(": not found\r\n");
222 ufs_read(&dinode
, (void *)addr
, 0, sizeof(struct exec
));
223 memcpy(header
, (void *)addr
, sizeof(struct exec
));
225 if ((N_GETMAGIC(*header
) != OMAGIC
) ||
226 (N_GETMID(*header
) != MID_M68K
)) {
228 B_PRINT(": inappropriate format");
232 /* read text and data */
233 ufs_read(&dinode
, ((char *)addr
)-sizeof(struct exec
), 0,/* XXX */
234 header
->a_text
+header
->a_data
);
237 memset((char*) addr
+ header
->a_text
+header
->a_data
,
240 /* PLANNED: fallback NMAGIC loader for the kernel. */
242 /* return the image size. */
243 return header
->a_text
+header
->a_data
+header
->a_bss
;
257 extern const char bootprog_name
[], bootprog_rev
[];
260 /* for debug; ¥ì¥¸¥¹¥¿¤Î¾õÂÖ¤ò¥×¥ê¥ó¥È¤¹¤ë */
261 for (i
= 0; i
< 16; i
++) {
262 print_hex(startregs
[i
], 8);
263 B_PRINT((i
& 7) == 7 ? "\r\n" : " ");
267 B_PRINT(bootprog_name
);
268 B_PRINT(" rev."); B_PRINT(bootprog_rev
);
274 if (BINF_ISFD(&BOOT_INFO
)) {
277 *(int *)bootdevstr
= ('f' << 24 | 'd' << 16 | '@' << 8 | '0') +
279 bootdevstr
[4] = '\0';
281 bootdev
= X68K_MAKEBOOTDEV(X68K_MAJOR_FD
, BOOT_INFO
& 3,
282 (FDSECMINMAX
.minsec
.N
== 3) ? 0 : 2);
287 #ifdef SCSI_ADHOC_BOOTPART
288 if (SCSI_PARTTOP
== 0)
291 part
= get_scsi_part();
293 part
= 0; /* sd?a only */
296 ha
= get_scsi_host_adapter();
298 ha
= get_scsi_host_adapter(bootdevstr
);
299 bootdevstr
[10] = '0' + (ID
& 7);
300 bootdevstr
[14] = 'a' + part
;
302 bootdev
= X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD
, ha
>> 4, ha
& 15,
306 B_PRINT("boot device: ");
311 /* initialize filesystem code */
313 BOOT_ERROR("bogus super block: "
314 "¥ë¡¼¥È¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬²õ¤ì¤Æ¤¤¤Þ¤¹¡ª");
317 #if defined(BOOT_DEBUG) && defined(USE_FFS) && defined(USE_LFS)
318 B_PRINT("file system: ");
319 B_PUTC(ufs_info
.fstype
== UFSTYPE_FFS
?
320 (unsigned int) 'F' : (unsigned int) 'L');
325 B_PRINT("\r\nlooking up secondary boot... ");
329 * Look for the 2nd stage boot.
332 /* Try "boot" first */
333 size
= load_file("boot", BOOT_TEXTADDR
, &header
);
335 B_PRINT("done.\r\n");
338 exec_image(BOOT_TEXTADDR
, /* image loaded at */
339 BOOT_TEXTADDR
, /* image executed at */
340 header
.a_entry
, /* entry point */
341 size
, /* image size */
342 bootdev
, RB_SINGLE
); /* arguments */
344 B_PRINT("can't load the secondary bootstrap.;"
345 "trying /netbsd...\r\n");
347 /* fallback to /netbsd. */
348 /* always fails since NMAGIC loader is not yet implemented. */
350 size
= load_file("netbsd", 0x6000, &header
);
352 if (*((short *)(0x6000 + header
.a_entry
- 2)) != 0) {
353 B_PRINT("boot interface of /netbsd is too new!\r\n");
356 exec_image(0x6000, /* image loaded at */
357 0, /* image executed at */
358 header
.a_entry
, /* entry point */
359 size
, /* image size */
360 bootdev
, RB_SINGLE
); /* arguments */
365 BOOT_ERROR("can't load the secondary bootstrap nor the kernel.");