1: /* 2: * SCCS id @(#)boot.c 2.1 (Berkeley) 8/5/83 3: */ 4: 5: #include <sys/param.h> 6: #include <sys/seg.h> 7: #include <sys/ino.h> 8: #include <sys/inode.h> 9: #include <sys/filsys.h> 10: #include <sys/dir.h> 11: #include <sys/reboot.h> 12: #include <sys/koverlay.h> 13: #include <a.out.h> 14: #include "../saio.h" 15: 16: #undef btoc 17: #define KB * 1024L 18: 19: #define KISD0 ((u_short *) 0172300) 20: #define KISD3 ((u_short *) 0172306) 21: #define KDSD0 ((u_short *) 0172320) 22: #undef KISA0 23: #define KISA0 ((u_short *) 0172340) 24: #define KISA3 ((u_short *) 0172346) 25: #define KDSA0 ((u_short *) 0172360) 26: 27: #define SEG_DATA 01 28: #define SEG_TEXT 02 29: #define SEG_OVLY 04 30: 31: extern int cputype; 32: extern bool_t ksep; /* Is kernel mode currently separated */ 33: extern bool_t sep_id; /* Does the cpu support separate I/D? */ 34: extern int bootopts, bootdev, checkword; 35: char module[] = "Boot"; /* This program's name (used by trap) */ 36: char line[100] = RB_DEFNAME; 37: bool_t overlaid = 0; 38: u_short pdrproto[16 + NOVL] = {0}; 39: struct exec exec; 40: struct ovlhdr ovlhdr; 41: unsigned btoc(); 42: 43: struct loadmap { 44: int seg_type; 45: long seg_len; 46: }; 47: struct loadtable { 48: short lt_magic; 49: struct loadmap *lt_map; 50: }; 51: 52: struct loadmap load407[] = { 53: SEG_DATA, 56 KB, 54: 0, 0 KB 55: }; 56: struct loadmap load410[] = { 57: SEG_TEXT, 48 KB, 58: SEG_DATA, 56 KB, 59: 0, 0 KB 60: }; 61: struct loadmap load411[] = { 62: SEG_DATA, 56 KB, 63: SEG_TEXT, 64 KB, 64: 0, 0 KB 65: }; 66: struct loadmap load430[] = { 67: SEG_TEXT, 16 KB, /* minumum, 8 KB + 1 */ 68: SEG_OVLY, 8 KB, 69: SEG_DATA, 24 KB, 70: SEG_OVLY, 8 KB, 71: SEG_OVLY, 8 KB, 72: SEG_OVLY, 8 KB, 73: SEG_OVLY, 8 KB, 74: SEG_OVLY, 8 KB, 75: SEG_OVLY, 8 KB, 76: 0, 0 KB 77: }; 78: struct loadmap load431[] = { 79: SEG_DATA, 56 KB, /* minumum, 48 KB + 1 */ 80: SEG_TEXT, 56 KB, 81: SEG_OVLY, 8 KB, 82: SEG_OVLY, 8 KB, 83: SEG_OVLY, 8 KB, 84: SEG_OVLY, 8 KB, 85: SEG_OVLY, 8 KB, 86: SEG_OVLY, 8 KB, 87: SEG_OVLY, 8 KB, 88: 0, 0 KB 89: }; 90: 91: struct loadtable loadtable[] = { 92: A_MAGIC1, load407, 93: A_MAGIC2, load410, 94: A_MAGIC3, load411, 95: A_MAGIC5, load430, 96: A_MAGIC6, load431 97: }; 98: 99: main () 100: { 101: int i, j; 102: int retry = 0; 103: struct loadtable *setup (); 104: 105: segflag = 2; /* device drivers care about this */ 106: 107: printf ("\n%d%s\n", cputype, module); 108: #ifdef UCB_AUTOBOOT 109: /* 110: * The machine language will have gotten the bootopts 111: * if we're an autoboot and will pass them along. 112: * If r2 (checkword) was the complement of bootopts, 113: * this is an automatic reboot, otherwise do it the hard way. 114: */ 115: if (checkword != ~bootopts) 116: #endif 117: bootopts = RB_SINGLE | RB_ASKNAME; 118: do { 119: if (bootopts & RB_ASKNAME) { 120: printf (": "); 121: gets (line); 122: } 123: else 124: printf (": %s\n", line); 125: if (line[0] == '\0') { 126: printf (": %s\n", RB_DEFNAME); 127: i = open (RB_DEFNAME, 0); 128: } 129: else 130: i = open (line, 0); 131: j = -1; 132: if (i >= 0) { 133: j = checkunix (i, setup (i)); 134: (void) close (i); 135: } 136: if (++retry > 2) 137: bootopts = RB_SINGLE | RB_ASKNAME; 138: } while (j < 0); 139: 140: } 141: 142: struct loadtable * 143: setup (io) 144: register io; 145: { 146: register i; 147: 148: exec.a_magic = getw (io); 149: exec.a_text = (unsigned) getw (io); 150: exec.a_data = (unsigned) getw (io); 151: exec.a_bss = (unsigned) getw (io); 152: 153: /* 154: * Space over the remainder of the exec header. We do this 155: * instead of seeking because the input might be a tape which 156: * doesn't know how to seek. 157: */ 158: getw (io); getw (io); getw (io); getw (io); 159: 160: /* 161: * If overlaid, get overlay header. 162: */ 163: if (exec.a_magic == A_MAGIC5 || exec.a_magic == A_MAGIC6) { 164: overlaid++; 165: ovlhdr.max_ovl = getw (io); 166: for (i = 0; i < NOVL; i++) 167: ovlhdr.ov_siz[i] = (unsigned) getw (io); 168: } 169: 170: for (i = 0; i < sizeof (loadtable) / sizeof (struct loadtable); i++) 171: if (loadtable[i].lt_magic == exec.a_magic) 172: return (&loadtable[i]); 173: 174: printf ("Bad magic number 0%o\n", exec.a_magic); 175: return ((struct loadtable *) NULL); 176: } 177: 178: 179: checkunix (io, lt) 180: struct loadtable *lt; 181: { 182: char *segname; 183: register ovseg, segtype; 184: register unsigned seglen; 185: struct loadmap *lm = lt->lt_map; 186: 187: if (lt == (struct loadtable *) NULL) 188: return (-1); 189: 190: /* 191: * Check and set I & D space requirements. 192: */ 193: if (exec.a_magic == A_MAGIC3 || exec.a_magic == A_MAGIC6) 194: if (!sep_id) { 195: printf ("Cannot load separate I & D object files\n"); 196: return (-1); 197: } 198: else 199: setsep (); 200: else 201: if (sep_id) 202: setnosep (); 203: 204: /* 205: * Check the sizes of each segment. 206: */ 207: ovseg = 0; 208: while (segtype = lm->seg_type) { 209: switch (segtype) { 210: case SEG_TEXT: 211: /* 212: * Round text size to nearest page. 213: */ 214: if (exec.a_magic == A_MAGIC2) 215: seglen = ctob (stoc (ctos (btoc (exec.a_text)))); 216: else 217: seglen = exec.a_text; 218: segname = "Text"; 219: break; 220: 221: case SEG_DATA: 222: seglen = exec.a_data + exec.a_bss; 223: segname = "Data"; 224: if (exec.a_magic == A_MAGIC1) 225: seglen += exec.a_text; 226: else 227: /* 228: * Force a complaint if the file 229: * won't fit. It's here instead 230: * of in the SEG_TEXT case above 231: * because it's more likely to be 232: * a data overflow problem. 233: */ 234: if (exec.a_magic == A_MAGIC2) 235: seglen += ctob (stoc (ctos (btoc (exec.a_text)))); 236: break; 237: 238: case SEG_OVLY: 239: seglen = ovlhdr.ov_siz[ovseg]; 240: segname = "Overlay"; 241: ovseg++; 242: break; 243: 244: default: 245: /* 246: * This ``cannot happen.'' 247: */ 248: printf ("Unknown segment type in load table: %d\n", segtype); 249: return (-1); 250: /*NOTREACHED*/ 251: } 252: 253: seglen = ctob (btoc (seglen)); 254: if (((long) seglen) > lm->seg_len) { 255: if (segtype == SEG_OVLY) 256: printf ("%s %d too large by %D bytes", segname, ovseg, lm->seg_len - ((long) seglen)); 257: else 258: printf ("%s too large by %D bytes", segname, lm->seg_len - ((long) seglen)); 259: return (-1); 260: } 261: if (segtype == SEG_TEXT) 262: switch (exec.a_magic) { 263: case A_MAGIC5: 264: if (seglen <= 8 KB) { 265: printf("Base segment too small, 8K minimum\n"); 266: return(-1); 267: } 268: break; 269: case A_MAGIC6: 270: if (seglen <= 48 KB) { 271: printf("Base segment too small, 48K minimum\n"); 272: return(-1); 273: } 274: break; 275: default: 276: break; 277: } 278: 279: lm++; 280: } 281: /* 282: * 431's (overlaid separate I/D) could be larger than 283: * 128 KB; relocate the bootstrap to 192K. 284: */ 285: if (exec.a_magic == A_MAGIC6) 286: if (reloc() < 0) { 287: printf("Not enough memory\n"); 288: return(-1); 289: } 290: 291: copyunix (io, lt); 292: setregs (lt); 293: return (0); 294: } 295: 296: copyunix (io, lt) 297: register io; 298: struct loadtable *lt; 299: { 300: int i; 301: bool_t donedata = 0; 302: register addr; 303: register unsigned seglen; 304: off_t segoff; 305: int segtype; 306: int nseg, phys, ovseg; 307: struct loadmap *lm = lt->lt_map; 308: 309: /* 310: * Load the segments and set up prototype PDRs. 311: */ 312: nseg = 0; 313: phys = 0; 314: ovseg = 0; 315: lm = lt->lt_map; 316: while (segtype = lm++->seg_type) { 317: 318: segoff = (off_t) N_TXTOFF(exec); 319: 320: switch (segtype) { 321: case SEG_TEXT: 322: seglen = exec.a_text; 323: break; 324: 325: case SEG_DATA: 326: seglen = exec.a_data; 327: if (exec.a_magic != A_MAGIC1) { 328: segoff += (off_t) exec.a_text; 329: if (overlaid) 330: for (i = 0; i < NOVL; i++) 331: segoff += (off_t) ovlhdr.ov_siz[i]; 332: } 333: else 334: seglen += exec.a_text; 335: donedata++; 336: break; 337: 338: case SEG_OVLY: 339: seglen = ovlhdr.ov_siz[ovseg]; 340: segoff += exec.a_text; 341: for (i = 0; i < ovseg; i++) 342: segoff += (off_t) ovlhdr.ov_siz[i]; 343: ovseg++; 344: break; 345: 346: } 347: 348: if (!seglen) 349: continue; 350: setseg (phys); 351: if (exec.a_magic != A_MAGIC1) 352: (void) lseek (io, segoff, 0); 353: for (addr = 0; addr < seglen; addr += 2) 354: mtpi (getw (io), addr); 355: 356: if (segtype == SEG_DATA) { 357: clrseg (addr, exec.a_bss); 358: seglen += exec.a_bss; 359: } 360: 361: pdrproto[nseg++] = btoc (seglen); 362: if (!donedata) 363: seglen = ctob (stoc (ctos (btoc (seglen)))); 364: phys += btoc (seglen); 365: } 366: } 367: 368: /* 369: * Set the real segmentation registers. 370: */ 371: setregs (lt) 372: struct loadtable *lt; 373: { 374: register i; 375: register u_short *par_base, *pdr_base; 376: bool_t donedata = 0; 377: int phys, segtype; 378: int nseg, ntextpgs, novlypgs, npages, pagelen; 379: struct loadmap *lm = lt->lt_map; 380: 381: nseg = 0; 382: phys = 0; 383: ntextpgs = 0; 384: novlypgs = 0; 385: 386: setseg (0); 387: if (exec.a_magic == A_MAGIC1) 388: return; 389: 390: /* 391: * First deny access to all except I/O page. 392: */ 393: par_base = KISA0; 394: pdr_base = KISD0; 395: for (i = 0; i < (ksep ? 8 : 7); i++) { 396: *par_base++ = 0; 397: *pdr_base++ = NOACC; 398: } 399: if (ksep) { 400: par_base = KDSA0; 401: pdr_base = KDSD0; 402: for (i = 0; i < 7; i++) { 403: *par_base++ = 0; 404: *pdr_base++ = NOACC; 405: } 406: } 407: 408: if (overlaid) { 409: /* 410: * We must write the prototype overlay register table. 411: * N.B.: we assume that 412: * the table lies in the first 8k of kernel virtual 413: * space, and 414: * 415: * the appropriate page lies at physical 0. 416: */ 417: if (ksep) 418: *KDSD0 = ((128 -1) << 8) | RW; 419: else 420: *KISD0 = ((128 -1) << 8) | RW; 421: par_base = &(((u_short *) OVLY_TABLE_BASE)[0]); 422: pdr_base = &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL]); 423: for (i = 0; i < NOVL; i++) { 424: mtpd (0, par_base++); 425: mtpd (NOACC, pdr_base++); 426: } 427: } 428: 429: /* 430: * Now set all registers which should be nonzero. 431: */ 432: lm = lt->lt_map; 433: while (segtype = lm++->seg_type) { 434: if (!(npages = ctos (pdrproto[nseg]))) 435: continue; 436: 437: switch (segtype) { 438: case SEG_TEXT: 439: /* 440: * Text always starts at KI0; 441: */ 442: par_base = KISA0; 443: pdr_base = KISD0; 444: ntextpgs += npages; 445: break; 446: 447: case SEG_DATA: 448: if (overlaid) 449: if (ksep) { 450: par_base = I_DATA_PAR_BASE; 451: pdr_base = I_DATA_PDR_BASE; 452: } 453: else 454: { 455: par_base = N_DATA_PAR_BASE; 456: pdr_base = N_DATA_PDR_BASE; 457: } 458: else 459: if (ksep) { 460: par_base = KDSA0; 461: pdr_base = KDSD0; 462: } 463: else 464: { 465: par_base = &KISA0[ntextpgs + novlypgs]; 466: pdr_base = &KISD0[ntextpgs + novlypgs]; 467: } 468: donedata++; 469: break; 470: 471: case SEG_OVLY: 472: par_base = &(((u_short *) OVLY_TABLE_BASE)[1 + novlypgs]); 473: pdr_base = &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL + 1 + novlypgs]); 474: novlypgs += npages; 475: break; 476: 477: } 478: 479: for (i = 0; i < npages; i++) { 480: pagelen = MIN (btoc ((int) (8 KB)), pdrproto[nseg]); 481: if (segtype == SEG_OVLY) { 482: mtpd (phys, par_base); 483: mtpd (((pagelen - 1) << 8) | RO, pdr_base); 484: } 485: else 486: { 487: *par_base = phys; 488: if (segtype == SEG_TEXT) 489: if (ksep) 490: *pdr_base = ((pagelen - 1) << 8) | RO; 491: else 492: /* 493: * Nonseparate kernels will 494: * write into text page 0 495: * when first booted. 496: */ 497: if (i == 0) 498: *pdr_base = ((pagelen - 1) << 8) | RW; 499: else 500: *pdr_base = ((pagelen - 1) << 8) | RO; 501: else 502: *pdr_base = ((pagelen - 1) << 8) | RW; 503: } 504: par_base++, pdr_base++; 505: if (donedata) 506: phys += pagelen; 507: else 508: phys += stoc (ctos (pagelen)); 509: pdrproto[nseg] -= pagelen; 510: } 511: 512: nseg++; 513: } 514: 515: /* 516: * Phys now contains the address of the start of 517: * free memory. We set K[ID]6 now or systrap to 518: * kernel mode will clobber text at 0140000. 519: */ 520: if (ksep) { 521: KDSA0[6] = phys; 522: KDSD0[6] = (stoc(1) - 1) << 8 | RW; 523: } 524: else 525: { 526: KISA0[6] = phys; 527: KISD0[6] = (stoc(1) - 1) << 8 | RW; 528: } 529: 530: if (overlaid) 531: mtpd (phys, &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL + 1 + NOVL])); 532: } 533: 534: unsigned 535: btoc (nclicks) 536: unsigned nclicks; 537: { 538: return ((unsigned) (((((long) nclicks) + ((long) 63)) >> 6))); 539: }