|
|
1.1 ! root 1: / $Header: /newbits/conf/boot/RCS/boot.m,v 1.4 91/11/08 13:18:38 bin Exp Locker: bin $ ! 2: / (lgl- ! 3: / The information contained herein is a trade secret of Mark Williams ! 4: / Company, and is confidential information. It is provided under a ! 5: / license agreement, and may be copied or disclosed only under the ! 6: / terms of that agreement. Any reproduction or disclosure of this ! 7: / material without the express written authorization of Mark Williams ! 8: / Company or persuant to the license agreement is unlawful. ! 9: / ! 10: / COHERENT Version 3.2.1 ! 11: / Copyright (c) 1982, 1983, 1984, 1991. ! 12: / An unpublished work by Mark Williams Company, Chicago. ! 13: / All rights reserved. ! 14: / -lgl) ! 15: ! 16: //////// ! 17: / ! 18: / Bootstrap block for the IBM ! 19: / PC. This code, which lives in sector 1, ! 20: / track 0 of the floppy (or sector 1 of a hard disk partition) ! 21: / gets read into location 0x7C00 by the ROM. ! 22: / The code relocates itself to location 0x2060:0x0000 ! 23: / (128K above the fixed memory used by the ROM). The system image is read ! 24: / in beginning at paragraph 0x0060. ! 25: / ! 26: / $Log: boot.m,v $ ! 27: / * Revision 1.4 91/11/08 13:18:38 bin ! 28: / * Piggy update for building secondary boot for tboot ! 29: / * ! 30: / Revision 1.7 91/11/08 11:31:13 piggy ! 31: / Attempted to integrate pboot into these sources. Still not working. ! 32: / Updated secondary boot for use with tertiary boot code. ! 33: / ! 34: / Revision 1.4 91/09/17 10:35:59 piggy ! 35: / Uses 4 byte disk blocks, so can boot from anywhere on disk. ! 36: / Points ds:si at useful data for tertiary boot. ! 37: / Loads /tboot by default. ! 38: / ! 39: / Revision 1.1 88/03/24 16:44:09 src ! 40: / Initial revision ! 41: / ! 42: / 87/10/04 Allan Cornish /usr/src/sys/i8086/boot/boot.s ! 43: / Number of heads now defined by NHD macro. Should be 1 for f*d*, 2 for f*a*. ! 44: / ! 45: / 85/10/04 Allan Cornish /usr/src/sys/i8086/boot/boot.s ! 46: / Bootstrap extended to increase max file size from 64 Kbytes to 128 Kbytes. ! 47: / The private code segment is now loaded, where previously it had to be empty. ! 48: / File name editing enhanced to help cursor stay in the 14 char entry field, ! 49: / and to provide a destructive backspace. ! 50: / ! 51: / 85/01/04 Allan Cornish ! 52: / Added backspace editing of file name. ! 53: / ! 54: //////// ! 55: ! 56: #ifndef NHD ! 57: #define NHD 1 / num of heads per drive [1 for f9d0]. ! 58: #endif ! 59: ! 60: #ifndef NSPT ! 61: #define NSPT 9 / num of sectors per track on floppy. ! 62: #define NTRK 40 / num of tracks on floppy. ! 63: #endif ! 64: ! 65: ! 66: #ifndef CNTRL ! 67: #define CNTRL 8 ! 68: #endif ! 69: ! 70: #ifndef WPCC ! 71: #define WPCC 0xFFFF ! 72: #endif ! 73: ! 74: NSTK = 256 / num of bytes of stack. ! 75: BS = 0x08 / BS character. ! 76: CR = 0x0D / CR character. ! 77: LF = 0x0A / LF character. ! 78: SP = 0x20 / Backspace character. ! 79: BOOTLC = 0x7C00 / Boot location (ROM). ! 80: BOOTS = 0 / boot segment (ROM). ! 81: RBOOTS = 0x2060 / Relocated boot segment. ! 82: BSHIFT = 9 / Shift, bytes to blocks. ! 83: ROOTINO = 2 / Root inode # ! 84: INOORG = 2 / First inode block. ! 85: IBSHIFT = 3 / Shift, inode to blocks ! 86: IOSHIFT = 6 / Shift, inode to bytes ! 87: INOMASK = 0x0007 / Mask, inode to offset ! 88: DIRSIZE = 14 / Directory size. ! 89: DIRSIZ2 = 7 / Directory size / 2. ! 90: BUFSIZE = 512 / Block size. ! 91: HDRSIZE = 44 / L.out header size. ! 92: HDRSIZ2 = 22 / L.out header size / 2. ! 93: BUFMSK2 = 0x00FF / Block [word] mask, for reads. ! 94: DISK = 0x13 / Disk Interrupt ! 95: KEYBD = 0x16 / Keyboard Interrupt ! 96: READ1 = 0x0201 / read one sector ! 97: DADDR = 4 / number of bytes in a disk block number ! 98: ND = 10 / num of direct blocks. ! 99: NIND = 128 / num of blocks in indirect block. ! 100: NINDX2 = 256 / NIND * 2 (number of words in indirect) ! 101: ISIZE = 8 / Offset of "di_size". ! 102: IADDR = 12 / Offset of "di_addr". ! 103: JMPF = 0xEA / Jump far, direct. ! 104: LMAGIC = 0 / Offset of "l_magic" ! 105: LFLAG = 2 / Offset of "l_flag" ! 106: LSHRI = 10 / Offset of "l_ssize[SHRI]" ! 107: LPRVI = 14 / Offset of "l_ssize[PRVI]" ! 108: LSHRD = 22 / Offset of "l_ssize[SHRD]" ! 109: LPRVD = 26 / Offset of "l_ssize[PRVD]" ! 110: LBSSD = 30 / Offset of "l_ssize[BSSD]" ! 111: LFMAG = 0x0107 / Magic number. ! 112: LFSEP = 0x02 / Sep I/D flag bit. ! 113: SYSBASE = 0x0060 / System load base paragraph. ! 114: FIRST = 8 / relative start of partition ! 115: ! 116: / Hard disk controller port addresses. ! 117: HF_REG = 0x3F6 ! 118: NSEC_REG= 0x1F2 ! 119: SEC_REG = 0x1F3 ! 120: HDRV_REG= 0x1F6 ! 121: CSR_REG = 0x1F7 ! 122: BSY_ST = 0x80 ! 123: SETPARM_CMD= 0x91 ! 124: ! 125: //////// ! 126: / Overall structure of boot.s (the secondary boot): ! 127: / ! 128: / boot: relocate secondary to high memory (0x2060:0x0000) ! 129: / if needed, get hard disk parameters from bios ! 130: / jump far to high memory (RBOOTS:entry) ! 131: / entry: open directory "/" ! 132: / search: while filename not found ! 133: / walk through "/" looking for filename (in nbuf) ! 134: / if not found, ask for another name (call input:), and loop to search ! 135: / found: open file that we just found ! 136: / read the l.out header (verify magic number, get partition sizes) ! 137: / load the shared and private code segments as one (call load:) ! 138: / load the initialized data segment (call load:) ! 139: / jump far to the newly loaded program ! 140: / ! 141: //////// ! 142: ! 143: //////// ! 144: / ! 145: / Bootstrap mainline. Relocate the ! 146: / boot to high memory, so it will not be written ! 147: / over by the system. Read in a file name. Look up ! 148: / the file name by following out the directory ! 149: / structure. Read in the image and jump to it. ! 150: / ! 151: //////// ! 152: ! 153: boot: xor di, di ! 154: mov ds, di ! 155: mov si, $BOOTLC / Make DS:SI point at the code ! 156: / "mov es, 1f(si)" really means "mov es, $RBOOTS". Clever Intel... :-( ! 157: mov es, 1f(si) / Make ES:DI point at where it goes ! 158: mov cx, $512 / cx = # of bytes to move ! 159: cld ! 160: rep / Move the bootstrap ! 161: movsb / to high memory. ! 162: ! 163: / Check to see if we were invoked by mboot. (That means we are booting ! 164: / off a hard disk and need to load disk parameters. ) ! 165: ! 166: / mboot sets bx = sp ! 167: cmp bx, sp / trick to tell ! 168: jne 0f / whether or not xt ! 169: ! 170: / Assertion: at this point we know we are booting off a hard disk. ! 171: mov si, bp / set si to partition table ! 172: ! 173: movb dl, (si) / get drive number ! 174: movb ah, $8 / get drive parameters ! 175: int DISK ! 176: jc 0f / abort on error ! 177: ! 178: movb al, ch / fetch cyl(lo) ! 179: movb ah, cl / move cyl(hi), sects ! 180: rolb ah, $1 / shift cylinder high to ! 181: rolb ah, $1 / the least sig bits ! 182: andb ah, $3 / mask out cylinder bits ! 183: ! 184: mov di, $traks / point to drive ! 185: stosw / set number of tracks ! 186: ! 187: movb al, $0x3F / sector mask ! 188: andb al,cl / mask sector ! 189: stosb / set sector ! 190: ! 191: movb al, dh / get max head ! 192: inc ax / change to # of heads [incb al] ! 193: stosb / set number of heads ! 194: ! 195: movsb / set drive ! 196: add si, $FIRST-1 / point to first block ! 197: movsw ! 198: movsw / fetch first block ! 199: ! 200: / Set registers. ! 201: ! 202: 0: mov bp, $stack+NSTK / stack pointer value ! 203: mov ax, es ! 204: mov ds, ax ! 205: mov ss, ax ! 206: mov sp, bp ! 207: ! 208: / Jump to (relocated) boot. ! 209: ! 210: .byte JMPF ! 211: .word entry ! 212: 1: .word RBOOTS ! 213: ! 214: //////// ! 215: / ! 216: / This is the equivalent of "open()", ! 217: / but takes an inode instead of a pathname. ! 218: / ! 219: / Read the inode specified by "ax" ! 220: / into the external variable "iaddr". ! 221: / ! 222: / Makes a list of block numbers in "iaddr" ! 223: / consisting of the 10 direct block numbers, the 128 ! 224: / block numbers pointed to the singly indirect block, ! 225: / and the first 128 block numbers pointed to by the ! 226: / first doubly indirect block. ! 227: / ! 228: / Note that "iread" can only access the first 256 ! 229: / block numbers in this list, so the last 10 are ! 230: / ignored. ! 231: / ! 232: / Note that block numbers are actually 32 bits on disk-- ! 233: / this routine only uses the lower 16 bits. ! 234: / In fact, iaddr is loaded with 16 bit numbers, not 32 bit. ! 235: / ! 236: / No checking is done to make sure that ! 237: / the inumber is in range on the filesystem. ! 238: / Sets dx and cx to 0. ! 239: / Mungs si, di, ax. ! 240: / ! 241: //////// ! 242: ! 243: igrab: dec ax / Make origin 0 and ! 244: push ax / remember for later use. ! 245: ! 246: / We assume that the inode table appears in the first 32 meg of disk. ! 247: / Look up the inode in the inode table. ! 248: movb cl, $IBSHIFT / Convert to ! 249: shr ax, cl / inode block number, ! 250: inc ax / then to physical block number, ! 251: inc ax ! 252: sub bx, bx / Assume inode within first 32 meg. ! 253: call bread / and read in the data. ! 254: ! 255: pop ax / Get i-number back. ! 256: and ax, $INOMASK / Get inode within block ! 257: movb cl, $IOSHIFT / and convert to ! 258: shl ax, cl / a byte offset in the block. ! 259: add si, ax / si = inode pointer. ! 260: ! 261: / Assertion: si now points at the start of the desired ! 262: / inode structure (see <sys/inode.h>). ! 263: ! 264: / Copy out the direct block numbers to iaddr. ! 265: add si, $IADDR / Point at address field. ! 266: mov di, $iaddr / Copy out area. ! 267: ! 268: / The block numbers in the inode on disk are stored as ! 269: / 3 bytes: msb, lsw. lsw is lsb, msb. We want to store them ! 270: / in memory as msw, lsw, just like the inodes in the indirect ! 271: / blocks on disk. So we need to cast msb as msw. ! 272: movb cl, $ND / cx = # of direct blocks ! 273: sub ax, ax / cast byte in al to word in ax ! 274: 0: lodsb / al = msb for direct byte ! 275: stosw / store msb cast as a word ! 276: movsw / store lsw. ! 277: loop 0b ! 278: ! 279: lodsb / Get the msb for the indirect block. ! 280: xchg bx, ax / (implicit cast of msb to msw) ! 281: lodsw / Get the lsw for the indirect block. ! 282: call bread / Read (first) indirect block. ! 283: ! 284: / Copy out the singly indirect block numbers to iaddr. ! 285: / These are stored on disk as 4 byte numbers: msw, lsw ! 286: / where each word is lsb, msb. This is how we store them ! 287: / in memory. ! 288: mov cx, $NINDX2 ! 289: rep ! 290: movsw ! 291: ! 292: ! 293: / Finish by reading the first block of the file into bbuf. ! 294: sub dx, dx / Set dh to first block number in iaddr. ! 295: / jmp iread / Done return through iread. ! 296: ! 297: //////// ! 298: / ! 299: / This routine reads the virtual ! 300: / block iaddr[dh] (the dhth block number ! 301: / in iaddr) into the buffer "bbuf". ! 302: / It uses the mapping data that ! 303: / has been provided by a previous call to igrab ! 304: / On return "si" points at "bbuf". ! 305: / Holes in files (sparse blocks) are correctly done. ! 306: / mungs ax, bx, si. ! 307: / clears cx. ! 308: / ! 309: /////// ! 310: ! 311: iread: ! 312: sub bx, bx / Convert from words to blocks. ! 313: movb bl, dh / ! 314: ! 315: / Block numbers are 4 bytes long, stored msw, lsw. ! 316: shl bx, $2 / Compute index into iaddr table. ! 317: push iaddr(bx) / fetch msw ! 318: inc bx ! 319: inc bx ! 320: mov ax, iaddr(bx) / fetch lsw ! 321: pop bx / put msw where it belongs ! 322: / jmp bread / Yes, return through "bread". ! 323: ! 324: //////// ! 325: / ! 326: / Read a block from the floppy disk, ! 327: / drive A:, using the code in the IBM firmware. ! 328: / The physical block # is in ax and bx. ! 329: / Register bx is the MSW, and ax is the LSW. ! 330: / ! 331: //////// ! 332: ! 333: bread: push es / Save registers ! 334: push di ! 335: push dx ! 336: ! 337: push ds ! 338: pop es / set ES to the address of the buffer ! 339: ! 340: mov di, bp / Blast the buffer contents. ! 341: mov cx, $BUFSIZE / For block 0, this fills the buffer ! 342: rep / with zeros. ! 343: stosb ! 344: ! 345: / Block #0 is the sparse block--it means a block of all zeros. ! 346: test ax, ax / if block 0, return zeroed buffer ! 347: jnz 3f ! 348: test bx, bx ! 349: jz 2f ! 350: ! 351: / Translate block number into cylinder, head, and sector. ! 352: 3: push bx ! 353: pop dx ! 354: / xor dx, dx / extend block number ! 355: add ax, first / add first block ! 356: adc dx, first+2 / add rest ! 357: ! 358: mov bx, ax / save block number ! 359: movb al, heads / get number of heads ! 360: movb cl, sects / get number of sectors ! 361: mulb cl / calculate sectors per cylinder ! 362: xchg bx,ax / swap block/sectors ! 363: div bx / calculate track ! 364: xchg dx, ax / put track in DX ! 365: divb cl / calculate head/sector ! 366: ! 367: movb cl, ah / set sector ! 368: inc cx / sectors start at 1 [incb cl] ! 369: ! 370: cmp dx, traks / check for second side ! 371: jb 0f ! 372: sub dx, traks / fold track ! 373: inc ax / next head [incb al] ! 374: ! 375: 0: rorb dh, $1 / rotate track(low) into ! 376: rorb dh, $1 / msbits of DX ! 377: orb cl, dh / set track(high) ! 378: movb ch, dl / set track(low) ! 379: movb dh, al / set head ! 380: movb dl, drive / set drive ! 381: mov bx, bp / set offset [bbuf] ! 382: ! 383: mov ax, $READ1 / Read, 1 sector. ! 384: int DISK / Disk I/O. ! 385: jnc 2f / Jump if no error. ! 386: mov ax, $READ1 / try again ! 387: int DISK ! 388: jc error ! 389: ! 390: 2: mov si, bp / set SI to point to buffer for return ! 391: sub cx, cx / clear CX here to save space ! 392: ! 393: pop dx / restore registers. ! 394: pop di ! 395: pop es ! 396: ret / return. ! 397: ! 398: / Prompt with a "?" and read the file name ! 399: / into "nbuf". No character editing facilites ! 400: / are provided. ! 401: ! 402: error: mov sp, bp / Reset stack ! 403: ! 404: input: mov di, $nbuf / di=name buffer pointer ! 405: mov cx, $DIRSIZE / cx=size of ! 406: / Preprocessor blows up if we use single-quote question mark. ! 407: movb al, $0077 / set prompt to ?. ! 408: 0: call putc ! 409: ! 410: 1: movb ah, $0 / Get ASCII opcode. ! 411: int KEYBD / Read keyboard ROM call. ! 412: ! 413: 2: cmpb al, $CR / CR ? ! 414: je 3f / Yup, do next thing ! 415: ! 416: jcxz 1b / skip over too big name ! 417: stosb / put it into the buffer, ! 418: dec cx / adjust char count ! 419: jmp 0b / and continue. ! 420: ! 421: 3: movb al, $CR ! 422: call putc ! 423: movb al, $LF ! 424: call putc ! 425: ! 426: movb al, $0 / zero out ! 427: rep ! 428: stosb / rest of name ! 429: ! 430: //////// ! 431: / This is where we jump after boot has been relocated. ! 432: / ! 433: / Open "/"; we are going to search for "autoboot". ! 434: //////// ! 435: entry: mov ax, $ROOTINO / ax = current inode ! 436: call igrab / Read in inode and set dx ! 437: ! 438: //////// ! 439: / Search directory for filename in nbuf. ! 440: / Assume directory size = 64 Kbytes. ! 441: / This assumption works because block numbers ! 442: / from the inode beyond end of file are zero. ! 443: //////// ! 444: ! 445: search: orb dl, dl / On block boundry ? ! 446: jnz 0f / Nope. ! 447: call iread / Read block, set si. ! 448: ! 449: 0: movb cl, $DIRSIZE / cx = count left ! 450: mov di, $nbuf / Point at name buffer and ! 451: lodsw / ax = inumber, this entry. ! 452: or ax, ax / Empty directory slot ? ! 453: je 1f / Yes, skip. ! 454: repe / compare the ! 455: cmpsb / two file names. ! 456: je found / If eq, go and get inode. ! 457: ! 458: 1: add si, cx / Advance by count remaining. ! 459: add dx, $DIRSIZ2+1 / Bump [word] seek pointer ! 460: jg search / Scan up to 64 Kbytes of directory. ! 461: ! 462: jmp input / File not found. ! 463: ! 464: ! 465: //////// ! 466: / ! 467: / Found the file so read it in. ! 468: / ax = inode number of file ! 469: / ! 470: //////// ! 471: ! 472: found: call igrab / read in inode and first block ! 473: cmp LMAGIC(si),$LFMAG / Check the magic number. ! 474: jne error / not Ok. ! 475: ! 476: / push LBSSD(si) / Push the uninitialized data size. ! 477: ! 478: / Get the total size of shared and private data segments. ! 479: / They are contigious on disk. see <l.out.h> ! 480: mov ax, LSHRD(si) / Push the sum ! 481: add ax, LPRVD(si) / of the shared and private ! 482: push ax / [initialized] data sizes. ! 483: / If this is not a sep I/D executable, then we ! 484: / do not want to load the non-existent data segment. ! 485: andb LFLAG(si), $LFSEP / check image flags. ! 486: pushf / Push result of test. ! 487: mov ax, LSHRI(si) / Get the sum of the ! 488: add ax, LPRVI(si) / shared and private code sizes. ! 489: ! 490: / Find the start of the first segment on disk. ! 491: mov dx, $HDRSIZ2 / Seek after header and ! 492: add si, $HDRSIZE / set buffer pointer appropriately. ! 493: mov es, 1f / Set ES:DI to point to the load ! 494: sub di, di / base of the new system. ! 495: ! 496: / Load the code segment. ! 497: call load / Load code. ! 498: ! 499: / Skip loading the data segment for non-sep I/D executables. ! 500: popf / Pop sep I/D flag test ! 501: jz 0f / Not sep. ! 502: ! 503: / Assertion: at this point we are dealing with a sep I/D ! 504: / l.out executable. ! 505: ! 506: / Calculate load point for data segment. ! 507: add di, $15 / Round up the system code ! 508: movb cl, $4 / size to 16 byte ! 509: shr di, cl / paragraphs. ! 510: mov ax, es / fetch program base ! 511: add ax, di / Compute the data base and ! 512: mov es, ax / set up ES:DI to point ! 513: sub di, di / at it. ! 514: ! 515: 0: pop ax / Pop off initialized data size and ! 516: / Load the initialized data segment. ! 517: call load / load the image. ! 518: ! 519: mov si, $useful / Point ds:si at the useful data ! 520: / for the tertiary boot. ! 521: ! 522: / pop cx / Pop off uninitialized data size and ! 523: / rep / clear it. ! 524: / stosb ! 525: ! 526: / Run the program that we just loaded. ! 527: .byte JMPF / Jump to offset ! 528: .word 0x0100 / 0x0100 (after base) in system ! 529: 1: .word SYSBASE / code segment. ! 530: ! 531: //////// ! 532: / ! 533: / Load a segment from an l.out file into memory. ! 534: / The "dx" register holds the ! 535: / seek pointer into the file. The "si" holds ! 536: / a pointer into the "bbuf". The "es:di" pair ! 537: / holds the target address. The "ax" holds ! 538: / the number of bytes to load. On return the ! 539: / "ax" must equal 0 (the caller assumes this ! 540: / and uses "al" to clear the BSS). ! 541: / ! 542: / Note that since the number of bytes to load is ! 543: / stored in a 16 bit register, a segment may be no ! 544: / longer than 64K. For small model this is just fine. ! 545: //////// ! 546: ! 547: load: or ax, ax / Any left ? ! 548: jz return / Jump if all loaded. ! 549: ! 550: mov cx, $bbuf+BUFSIZE / Compute the number of bytes ! 551: sub cx, si / remaining in the block. ! 552: jnz 0f / Jump if some. ! 553: ! 554: push ax / Save count registers, then ! 555: call iread / read the next block ! 556: pop ax / of the file. ! 557: mov cx, $BUFSIZE / We now have a full block. ! 558: ! 559: 0: cmp cx, ax / More than we need ? ! 560: jbe 1f / Nope. ! 561: mov cx, ax / Only take what we need. ! 562: ! 563: 1: sub ax, cx / Fix up the count ! 564: shr cx, $1 / ! 565: add dx, cx / Fix up the seek [word] address, then ! 566: rep / copy the words from the block ! 567: movsw / buffer to the load point and ! 568: jmp load / loop until done. ! 569: ! 570: //////// ! 571: / ! 572: / Write the character in "al" out to ! 573: / the display, using routines in the ROM. ! 574: / Like most calls to the ROM, this routine spends ! 575: / most of its time saving and restoring the ! 576: / registers. ! 577: / ! 578: / Note: The ZF in the PSW word must be preserved. ! 579: / ! 580: //////// ! 581: ! 582: putc: push si / Save registers. ! 583: push di ! 584: push bp ! 585: ! 586: mov bx, $0x0007 / Page 0, white on black ! 587: movb ah, $0x0E / Write TTY. ! 588: int 0x10 / Call video I/O in ROM. ! 589: ! 590: pop bp / Restore registers. ! 591: pop di ! 592: pop si ! 593: return: ret / Return ! 594: ! 595: //////// ! 596: / ! 597: / Data. There is some pure data in ! 598: / the "prvd" segment. This data is moved to the ! 599: / new memory when the boot is relocated. All buffers ! 600: / are in the BSS, and are not actually moved, or even ! 601: / saved in the boot block. ! 602: / ! 603: //////// ! 604: ! 605: .prvd ! 606: ! 607: / Do not rearrange ANY of the following variables. If you ! 608: / need to add variables, they must come BEFORE or AFTER these. ! 609: / If you want to teach the tertiary boot about any variables you ! 610: / add, put them after double word "first". ! 611: ! 612: ! 613: .even ! 614: useful: / Useful variables for the tertiary boot. ! 615: nbuf: .ascii "tboot" / Name buffer. ! 616: .blkb DIRSIZE-5 / rest of buffer (5=sizeof("tboot")) ! 617: ! 618: traks: .word NTRK / Number of cylinders on drive we are booting off of. ! 619: sects: .byte NSPT / Number of sectors per track for our drive. ! 620: heads: .byte NHD / Number of heads on drive we are booting off of. ! 621: ! 622: drive: .byte 0 / Drive our partition resides upon. ! 623: first: .word 0 / First block of our partition (?) ! 624: .word 0 ! 625: cntrl: .byte CNTRL / Control byte ! 626: wpcc: .word WPCC / ! 627: ! 628: / This magic pair of bytes must be the last two bytes of ! 629: / the sector (address 0x1FE), otherwise mboot will refuse ! 630: / to execute it. ! 631: / If needed, uncomment the .blkb and adjust the number appropriately. ! 632: ! 633: .blkb 0x28 / Padding needed to make magic byte line up ! 634: ! 635: .byte 0x55,0xAA ! 636: ! 637: .bssd ! 638: stack: .blkb NSTK / Local Stack and name buffer ! 639: bbuf: .blkb BUFSIZE / Block buffer [must follow stack]. ! 640: iaddr: .blkw ND+ND+NIND+NIND / Inode map words.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.