1 /* $NetBSD: bootxx.c,v 1.16 2002/03/29 05:45:08 matt Exp $ */ 2 /*- 3 * Copyright (c) 1982, 1986 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)boot.c 7.15 (Berkeley) 5/4/91 35 */ 36 37 #include "sys/param.h" 38 #include "sys/reboot.h" 39 #include "sys/disklabel.h" 40 #include "sys/exec.h" 41 #include "sys/exec_elf.h" 42 43 #include "lib/libsa/stand.h" 44 #include "lib/libsa/ufs.h" 45 #include "lib/libsa/cd9660.h" 46 #include "lib/libsa/ustarfs.h" 47 48 #include "lib/libkern/libkern.h" 49 50 #include "machine/pte.h" 51 #include "machine/sid.h" 52 #include "machine/mtpr.h" 53 #include "machine/reg.h" 54 #include "machine/rpb.h" 55 #include "../vax/gencons.h" 56 57 #include "../mba/mbareg.h" 58 #include "../mba/hpreg.h" 59 60 #define NRSP 1 /* Kludge */ 61 #define NCMD 1 /* Kludge */ 62 63 #include "dev/mscp/mscp.h" 64 #include "dev/mscp/mscpreg.h" 65 66 #include "../boot/data.h" 67 68 #define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */ 69 70 void Xmain(void); 71 void hoppabort(int); 72 void romread_uvax(int lbn, int size, void *buf, struct rpb *rpb); 73 void hpread(int block); 74 int read750(int block, int *regs); 75 int unit_init(int, struct rpb *, int); 76 77 struct open_file file; 78 79 unsigned *bootregs; 80 struct rpb *rpb; 81 struct bqo *bqo; 82 int vax_cputype; 83 int vax_load_failure; 84 struct udadevice {u_short udaip;u_short udasa;}; 85 volatile struct udadevice *csr; 86 static int moved; 87 88 extern int from; 89 #define FROM750 1 90 #define FROMMV 2 91 #define FROMVMB 4 92 93 /* 94 * The boot block are used by 11/750, 8200, MicroVAX II/III, VS2000, 95 * VS3100/??, VS4000 and VAX6000/???, and only when booting from disk. 96 */ 97 void 98 Xmain() 99 { 100 union { 101 struct exec aout; 102 Elf32_Ehdr elf; 103 } hdr; 104 int io; 105 u_long entry; 106 107 vax_cputype = (mfpr(PR_SID) >> 24) & 0xFF; 108 moved = 0; 109 /* 110 */ 111 rpb = (void *)0xf0000; /* Safe address right now */ 112 bqo = (void *)0xf1000; 113 if (from == FROMMV) { 114 /* 115 * now relocate rpb/bqo (which are used by ROM-routines) 116 */ 117 bcopy ((void *)bootregs[11], rpb, sizeof(struct rpb)); 118 bcopy ((void*)rpb->iovec, bqo, rpb->iovecsz); 119 if (rpb->devtyp == BDEV_SDN) 120 rpb->devtyp = BDEV_SD; /* XXX until driver fixed */ 121 } else { 122 bzero(rpb, sizeof(struct rpb)); 123 rpb->devtyp = bootregs[0]; 124 rpb->unit = bootregs[3]; 125 rpb->rpb_bootr5 = bootregs[5]; 126 rpb->csrphy = bootregs[2]; 127 rpb->adpphy = bootregs[1]; /* BI node on 8200 */ 128 if (rpb->devtyp != BDEV_HP && vax_cputype == VAX_TYP_750) 129 rpb->adpphy = 130 (bootregs[1] == 0xffe000 ? 0xf30000 : 0xf32000); 131 } 132 rpb->rpb_base = rpb; 133 rpb->iovec = (int)bqo; 134 135 io = open("/boot.vax", 0); 136 if (io < 0) 137 io = open("/boot", 0); 138 if (io < 0) 139 asm("halt"); 140 141 read(io, (void *)&hdr.aout, sizeof(hdr.aout)); 142 if (N_GETMAGIC(hdr.aout) == OMAGIC && N_GETMID(hdr.aout) == MID_VAX) { 143 vax_load_failure++; 144 entry = hdr.aout.a_entry; 145 if (entry < sizeof(hdr.aout)) 146 entry = sizeof(hdr.aout); 147 read(io, (void *) entry, hdr.aout.a_text + hdr.aout.a_data); 148 memset((void *) (entry + hdr.aout.a_text + hdr.aout.a_data), 149 0, hdr.aout.a_bss); 150 } else if (memcmp(hdr.elf.e_ident, ELFMAG, SELFMAG) == 0) { 151 Elf32_Phdr ph; 152 size_t off = sizeof(hdr.elf); 153 vax_load_failure += 2; 154 read(io, (caddr_t)(&hdr.elf) + sizeof(hdr.aout), 155 sizeof(hdr.elf) - sizeof(hdr.aout)); 156 if (hdr.elf.e_machine != EM_VAX || hdr.elf.e_type != ET_EXEC 157 || hdr.elf.e_phnum != 1) 158 goto die; 159 vax_load_failure++; 160 entry = hdr.elf.e_entry; 161 if (hdr.elf.e_phoff != sizeof(hdr.elf)) 162 goto die; 163 vax_load_failure++; 164 read(io, &ph, sizeof(ph)); 165 off += sizeof(ph); 166 if (ph.p_type != PT_LOAD) 167 goto die; 168 vax_load_failure++; 169 while (off < ph.p_offset) { 170 u_int32_t tmp; 171 read(io, &tmp, sizeof(tmp)); 172 off += sizeof(tmp); 173 } 174 read(io, (void *) ph.p_paddr, ph.p_filesz); 175 memset((void *) (ph.p_paddr + ph.p_filesz), 0, 176 ph.p_memsz - ph.p_filesz); 177 } else { 178 goto die; 179 } 180 hoppabort(entry); 181 die: 182 asm("halt"); 183 } 184 185 /* 186 * Write an extremely limited version of a (us)tar filesystem, suitable 187 * for loading secondary-stage boot loader. 188 * - Can only load file "boot". 189 * - Must be the first file on tape. 190 */ 191 struct fs_ops file_system[] = { 192 #ifdef NEED_UFS 193 { ufs_open, 0, ufs_read, 0, 0, ufs_stat }, 194 #endif 195 #ifdef NEED_CD9660 196 { cd9660_open, 0, cd9660_read, 0, 0, cd9660_stat }, 197 #endif 198 #ifdef NEED_USTARFS 199 { ustarfs_open, 0, ustarfs_read, 0, 0, ustarfs_stat }, 200 #endif 201 }; 202 203 int nfsys = (sizeof(file_system) / sizeof(struct fs_ops)); 204 205 #if 0 206 int tar_open(char *path, struct open_file *f); 207 ssize_t tar_read(struct open_file *f, void *buf, size_t size, size_t *resid); 208 209 int 210 tar_open(path, f) 211 char *path; 212 struct open_file *f; 213 { 214 char *buf = alloc(512); 215 216 bzero(buf, 512); 217 romstrategy(0, 0, 8192, 512, buf, 0); 218 if (bcmp(buf, "boot", 5) || bcmp(&buf[257], "ustar", 5)) 219 return EINVAL; /* Not a ustarfs with "boot" first */ 220 return 0; 221 } 222 223 ssize_t 224 tar_read(f, buf, size, resid) 225 struct open_file *f; 226 void *buf; 227 size_t size; 228 size_t *resid; 229 { 230 romstrategy(0, 0, (8192+512), size, buf, 0); 231 *resid = size; 232 return 0; /* XXX */ 233 } 234 #endif 235 236 237 int 238 devopen(f, fname, file) 239 struct open_file *f; 240 const char *fname; 241 char **file; 242 { 243 *file = (char *)fname; 244 245 if (from == FROM750) 246 return 0; 247 /* 248 * Reinit the VMB boot device. 249 */ 250 if (bqo->unit_init && (moved++ == 0)) { 251 int initfn; 252 253 initfn = rpb->iovec + bqo->unit_init; 254 if (rpb->devtyp == BDEV_UDA || rpb->devtyp == BDEV_TK) { 255 /* 256 * This reset do not seem to be done in the 257 * ROM routines, so we have to do it manually. 258 */ 259 csr = (struct udadevice *)rpb->csrphy; 260 csr->udaip = 0; 261 while ((csr->udasa & MP_STEP1) == 0) 262 ; 263 } 264 /* 265 * AP (R12) have a pointer to the VMB argument list, 266 * wanted by bqo->unit_init. 267 */ 268 unit_init(initfn, rpb, bootregs[12]); 269 } 270 return 0; 271 } 272 273 extern struct disklabel romlabel; 274 275 int 276 romstrategy(sc, func, dblk, size, buf, rsize) 277 void *sc; 278 int func; 279 daddr_t dblk; 280 size_t size; 281 void *buf; 282 size_t *rsize; 283 { 284 int block = dblk; 285 int nsize = size; 286 287 if (romlabel.d_magic == DISKMAGIC && romlabel.d_magic2 == DISKMAGIC) { 288 if (romlabel.d_npartitions > 1) { 289 block += romlabel.d_partitions[0].p_offset; 290 if (romlabel.d_partitions[0].p_fstype == FS_RAID) { 291 block += RF_PROTECTED_SECTORS; 292 } 293 } 294 } 295 296 if (from == FROMMV) { 297 romread_uvax(block, size, buf, rpb); 298 } else /* if (from == FROM750) */ { 299 while (size > 0) { 300 if (rpb->devtyp == BDEV_HP) 301 hpread(block); 302 else 303 read750(block, bootregs); 304 bcopy(0, buf, 512); 305 size -= 512; 306 (char *)buf += 512; 307 block++; 308 } 309 } 310 311 if (rsize) 312 *rsize = nsize; 313 return 0; 314 } 315 316 /* 317 * The 11/750 boot ROM for Massbus disks doesn't seen to have layout info 318 * for all RP disks (not RP07 at least) so therefore a very small and dumb 319 * device driver is used. It assumes that there is a label on the disk 320 * already that has valid layout info. If there is no label, we can't boot 321 * anyway. 322 */ 323 324 #define MBA_WCSR(reg, val) \ 325 ((void)(*(volatile u_int32_t *)((adpadr) + (reg)) = (val))); 326 #define MBA_RCSR(reg) \ 327 (*(volatile u_int32_t *)((adpadr) + (reg))) 328 #define HP_WCSR(reg, val) \ 329 ((void)(*(volatile u_int32_t *)((unitadr) + (reg)) = (val))); 330 #define HP_RCSR(reg) \ 331 (*(volatile u_int32_t *)((unitadr) + (reg))) 332 333 void 334 hpread(int bn) 335 { 336 int adpadr = bootregs[1]; 337 int unitadr = adpadr + MUREG(bootregs[3], 0); 338 u_int cn, sn, tn; 339 struct disklabel *dp; 340 extern char start; 341 342 dp = (struct disklabel *)(LABELOFFSET + &start); 343 MBA_WCSR(MAPREG(0), PG_V); 344 345 MBA_WCSR(MBA_VAR, 0); 346 MBA_WCSR(MBA_BC, (~512) + 1); 347 #ifdef __GNUC__ 348 /* 349 * Avoid four subroutine calls by using hardware division. 350 */ 351 asm("clrl %%r1;" 352 "movl %3,%%r0;" 353 "ediv %4,%%r0,%0,%1;" 354 "movl %1,%%r0;" 355 "ediv %5,%%r0,%2,%1" 356 : "=g"(cn),"=g"(sn),"=g"(tn) 357 : "g"(bn),"g"(dp->d_secpercyl),"g"(dp->d_nsectors) 358 : "r0","r1","cc"); 359 #else 360 cn = bn / dp->d_secpercyl; 361 sn = bn % dp->d_secpercyl; 362 tn = sn / dp->d_nsectors; 363 sn = sn % dp->d_nsectors; 364 #endif 365 HP_WCSR(HP_DC, cn); 366 HP_WCSR(HP_DA, (tn << 8) | sn); 367 HP_WCSR(HP_CS1, HPCS_READ); 368 369 while (MBA_RCSR(MBA_SR) & MBASR_DTBUSY) 370 ; 371 return; 372 } 373 374 extern char end[]; 375 static char *top = (char*)end; 376 377 void * 378 alloc(size) 379 unsigned size; 380 { 381 void *ut = top; 382 top += size; 383 return ut; 384 } 385 386 void 387 free(ptr, size) 388 void *ptr; 389 unsigned size; 390 { 391 } 392 393 int 394 romclose(f) 395 struct open_file *f; 396 { 397 return 0; 398 } 399 400 #ifdef USE_PRINTF 401 void 402 putchar(int ch) 403 { 404 /* 405 * On KA88 we may get C-S/C-Q from the console. 406 * Must obey it. 407 */ 408 while (mfpr(PR_RXCS) & GC_DON) { 409 if ((mfpr(PR_RXDB) & 0x7f) == 19) { 410 while (1) { 411 while ((mfpr(PR_RXCS) & GC_DON) == 0) 412 ; 413 if ((mfpr(PR_RXDB) & 0x7f) == 17) 414 break; 415 } 416 } 417 } 418 419 while ((mfpr(PR_TXCS) & GC_RDY) == 0) 420 ; 421 mtpr(0, PR_TXCS); 422 mtpr(ch & 0377, PR_TXDB); 423 if (ch == 10) 424 putchar(13); 425 } 426 #endif 427