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