1 /* $NetBSD: bootxx.c,v 1.35 2009/03/23 13:52:32 tsutsui Exp $ */
4 * Copyright (c) 1982, 1986 The Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)boot.c 7.15 (Berkeley) 5/4/91
34 #include <sys/param.h>
35 #include <sys/reboot.h>
36 #include <sys/disklabel.h>
38 #include <sys/exec_elf.h>
39 #include <sys/exec_aout.h>
41 #include <lib/libsa/stand.h>
42 #include <lib/libsa/ufs.h>
43 #include <lib/libsa/cd9660.h>
44 #include <lib/libsa/ustarfs.h>
46 #include <lib/libkern/libkern.h>
48 #include <machine/pte.h>
49 #include <machine/sid.h>
50 #include <machine/mtpr.h>
51 #include <machine/reg.h>
52 #include <machine/rpb.h>
53 #include "../vax/gencons.h"
55 #include "../mba/mbareg.h"
56 #include "../mba/hpreg.h"
58 #define NRSP 1 /* Kludge */
59 #define NCMD 1 /* Kludge */
61 #include <dev/mscp/mscp.h>
62 #include <dev/mscp/mscpreg.h>
64 #include "../boot/data.h"
66 #define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */
70 void romread_uvax(int lbn
, int size
, void *buf
, struct rpb
*rpb
);
71 void hpread(int block
);
72 int read750(int block
, int *regs
);
73 int unit_init(int, struct rpb
*, int);
75 struct open_file file
;
82 struct udadevice
{u_short udaip
;u_short udasa
;};
83 volatile struct udadevice
*csr
;
92 * The boot block are used by 11/750, 8200, MicroVAX II/III, VS2000,
93 * VS3100/??, VS4000 and VAX6000/???, and only when booting from disk.
105 vax_cputype
= (mfpr(PR_SID
) >> 24) & 0xFF;
109 rpb
= (void *)0xf0000; /* Safe address right now */
110 bqo
= (void *)0xf1000;
111 if (from
== FROMMV
) {
113 * now relocate rpb/bqo (which are used by ROM-routines)
115 bcopy ((void *)bootregs
[11], rpb
, sizeof(struct rpb
));
116 bcopy ((void*)rpb
->iovec
, bqo
, rpb
->iovecsz
);
118 memset(rpb
, 0, sizeof(struct rpb
));
119 rpb
->devtyp
= bootregs
[0];
120 rpb
->unit
= bootregs
[3];
121 rpb
->rpb_bootr5
= bootregs
[5];
122 rpb
->csrphy
= bootregs
[2];
123 rpb
->adpphy
= bootregs
[1]; /* BI node on 8200 */
124 if (rpb
->devtyp
!= BDEV_HP
&& vax_cputype
== VAX_TYP_750
)
126 (bootregs
[1] == 0xffe000 ? 0xf30000 : 0xf32000);
129 rpb
->iovec
= (int)bqo
;
131 io
= open("/boot.vax", 0);
133 io
= open("/boot", 0);
137 read(io
, (void *)&hdr
.aout
, sizeof(hdr
.aout
));
138 if (N_GETMAGIC(hdr
.aout
) == OMAGIC
&& N_GETMID(hdr
.aout
) == MID_VAX
) {
140 entry
= hdr
.aout
.a_entry
;
141 if (entry
< sizeof(hdr
.aout
))
142 entry
= sizeof(hdr
.aout
);
143 read(io
, (void *) entry
, hdr
.aout
.a_text
+ hdr
.aout
.a_data
);
144 memset((void *) (entry
+ hdr
.aout
.a_text
+ hdr
.aout
.a_data
),
146 } else if (memcmp(hdr
.elf
.e_ident
, ELFMAG
, SELFMAG
) == 0) {
148 size_t off
= sizeof(hdr
.elf
);
149 vax_load_failure
+= 2;
150 read(io
, (char *)&hdr
.elf
+ sizeof(hdr
.aout
),
151 sizeof(hdr
.elf
) - sizeof(hdr
.aout
));
152 if (hdr
.elf
.e_machine
!= EM_VAX
|| hdr
.elf
.e_type
!= ET_EXEC
153 || hdr
.elf
.e_phnum
!= 1)
156 entry
= hdr
.elf
.e_entry
;
157 if (hdr
.elf
.e_phoff
!= sizeof(hdr
.elf
))
160 read(io
, &ph
, sizeof(ph
));
162 if (ph
.p_type
!= PT_LOAD
)
165 while (off
< ph
.p_offset
) {
167 read(io
, &tmp
, sizeof(tmp
));
170 read(io
, (void *) hdr
.elf
.e_entry
, ph
.p_filesz
);
171 memset((void *) (hdr
.elf
.e_entry
+ ph
.p_filesz
), 0,
172 ph
.p_memsz
- ph
.p_filesz
);
182 * Write an extremely limited version of a (us)tar filesystem, suitable
183 * for loading secondary-stage boot loader.
184 * - Can only load file "boot".
185 * - Must be the first file on tape.
187 struct fs_ops file_system
[] = {
189 { ufs_open
, 0, ufs_read
, 0, 0, ufs_stat
},
192 { cd9660_open
, 0, cd9660_read
, 0, 0, cd9660_stat
},
195 { ustarfs_open
, 0, ustarfs_read
, 0, 0, ustarfs_stat
},
199 int nfsys
= (sizeof(file_system
) / sizeof(struct fs_ops
));
202 int tar_open(char *path
, struct open_file
*f
);
203 ssize_t
tar_read(struct open_file
*f
, void *buf
, size_t size
, size_t *resid
);
206 tar_open(char *path
, struct open_file
*f
)
208 char *buf
= alloc(512);
211 romstrategy(0, 0, 8192, 512, buf
, 0);
212 if (memcmp(buf
, "boot", 5) || memcmp(&buf
[257], "ustar", 5))
213 return EINVAL
; /* Not a ustarfs with "boot" first */
218 tar_read(struct open_file
*f
, void *buf
, size_t size
, size_t *resid
)
220 romstrategy(0, 0, (8192+512), size
, buf
, 0);
228 devopen(struct open_file
*f
, const char *fname
, char **file
)
230 *file
= (char *)fname
;
235 * Reinit the VMB boot device.
237 if (bqo
->unit_init
&& (moved
++ == 0)) {
240 initfn
= rpb
->iovec
+ bqo
->unit_init
;
241 if (rpb
->devtyp
== BDEV_UDA
|| rpb
->devtyp
== BDEV_TK
) {
243 * This reset do not seem to be done in the
244 * ROM routines, so we have to do it manually.
246 csr
= (struct udadevice
*)rpb
->csrphy
;
248 while ((csr
->udasa
& MP_STEP1
) == 0)
252 * AP (R12) have a pointer to the VMB argument list,
253 * wanted by bqo->unit_init.
255 unit_init(initfn
, rpb
, bootregs
[12]);
260 extern struct disklabel romlabel
;
263 romstrategy(void *sc
, int func
, daddr_t dblk
, size_t size
, void *buf
, size_t *rsize
)
271 if (romlabel
.d_magic
== DISKMAGIC
&& romlabel
.d_magic2
== DISKMAGIC
) {
272 if (romlabel
.d_npartitions
> 1) {
273 block
+= romlabel
.d_partitions
[0].p_offset
;
274 if (romlabel
.d_partitions
[0].p_fstype
== FS_RAID
) {
275 block
+= RF_PROTECTED_SECTORS
;
280 if (from
== FROMMV
) {
281 romread_uvax(block
, size
, cbuf
, rpb
);
282 } else /* if (from == FROM750) */ {
284 if (rpb
->devtyp
== BDEV_HP
)
287 read750(block
, (int *)bootregs
);
288 memcpy(cbuf
, 0, 512);
301 * The 11/750 boot ROM for Massbus disks doesn't seen to have layout info
302 * for all RP disks (not RP07 at least) so therefore a very small and dumb
303 * device driver is used. It assumes that there is a label on the disk
304 * already that has valid layout info. If there is no label, we can't boot
308 #define MBA_WCSR(reg, val) \
309 ((void)(*(volatile u_int32_t *)((adpadr) + (reg)) = (val)));
310 #define MBA_RCSR(reg) \
311 (*(volatile u_int32_t *)((adpadr) + (reg)))
312 #define HP_WCSR(reg, val) \
313 ((void)(*(volatile u_int32_t *)((unitadr) + (reg)) = (val)));
314 #define HP_RCSR(reg) \
315 (*(volatile u_int32_t *)((unitadr) + (reg)))
320 int adpadr
= bootregs
[1];
321 int unitadr
= adpadr
+ MUREG(bootregs
[3], 0);
323 struct disklabel
*dp
;
326 dp
= (struct disklabel
*)(LABELOFFSET
+ &start
);
327 MBA_WCSR(MAPREG(0), PG_V
);
329 MBA_WCSR(MBA_VAR
, 0);
330 MBA_WCSR(MBA_BC
, (~512) + 1);
333 * Avoid four subroutine calls by using hardware division.
337 "ediv %4,%%r0,%0,%1;"
340 : "=g"(cn
),"=g"(sn
),"=g"(tn
)
341 : "g"(bn
),"g"(dp
->d_secpercyl
),"g"(dp
->d_nsectors
)
344 cn
= bn
/ dp
->d_secpercyl
;
345 sn
= bn
% dp
->d_secpercyl
;
346 tn
= sn
/ dp
->d_nsectors
;
347 sn
= sn
% dp
->d_nsectors
;
350 HP_WCSR(HP_DA
, (tn
<< 8) | sn
);
351 HP_WCSR(HP_CS1
, HPCS_READ
);
353 while (MBA_RCSR(MBA_SR
) & MBASR_DTBUSY
)
359 static char *top
= (char*)end
;
370 dealloc(void *ptr
, size_t size
)
375 romclose(struct open_file
*f
)
385 * On KA88 we may get C-S/C-Q from the console.
388 while (mfpr(PR_RXCS
) & GC_DON
) {
389 if ((mfpr(PR_RXDB
) & 0x7f) == 19) {
391 while ((mfpr(PR_RXCS
) & GC_DON
) == 0)
393 if ((mfpr(PR_RXDB
) & 0x7f) == 17)
399 while ((mfpr(PR_TXCS
) & GC_RDY
) == 0)
402 mtpr(ch
& 0377, PR_TXDB
);