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: }

Defined functions

btoc defined in line 534; never used
checkunix defined in line 179; used 1 times
copyunix defined in line 296; used 1 times
main defined in line 99; never used
setregs defined in line 371; used 1 times
setup defined in line 142; used 2 times

Defined variables

exec defined in line 39; used 34 times
line defined in line 36; used 4 times
load407 defined in line 52; used 1 times
  • in line 92
load410 defined in line 56; used 1 times
  • in line 93
load411 defined in line 61; used 1 times
  • in line 94
load430 defined in line 66; used 1 times
  • in line 95
load431 defined in line 78; used 1 times
  • in line 96
loadtable defined in line 91; used 3 times
module defined in line 35; used 1 times
overlaid defined in line 37; used 5 times
ovlhdr defined in line 40; used 6 times
pdrproto defined in line 38; used 4 times

Defined struct's

loadmap defined in line 43; used 18 times
loadtable defined in line 47; used 18 times

Defined macros

KB defined in line 17; used 31 times
KDSA0 defined in line 25; used 3 times
KDSD0 defined in line 21; used 4 times
KISA0 defined in line 23; used 5 times
KISA3 defined in line 24; never used
KISD0 defined in line 19; used 5 times
KISD3 defined in line 20; never used
SEG_DATA defined in line 27; used 6 times
SEG_OVLY defined in line 29; used 16 times
SEG_TEXT defined in line 28; used 6 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1848
Valid CSS Valid XHTML 1.0 Strict