--- /dev/null
+.386P\r
+;This boot sector is STUFFed to the gills to do a single\r
+;stage boot of the MMURTL OS which is about 160K stored as\r
+;a loadable image beginning at cluster 2 on the disk. The OS must\r
+;be stored contiguously in each of the following logical sectors.\r
+;The actual number of sectors is stored in the data param nOSSectors.\r
+\r
+CSEG SEGMENT WORD 'Code' USE16\r
+ ASSUME CS:CSEG, DS:CSEG, ES:Nothing\r
+\r
+ORG 0h\r
+\r
+ JMP SHORT Bootup\r
+ NOP\r
+\r
+;This 59 byte structure follows the 3 jump bytes above\r
+;and is found on all MS-DOS FAT compatible\r
+;disks. This contains additional information about the file system\r
+;on this disk that the operating needs to know. The boot sector code also\r
+;needs some of this information if this is a bootable disk.\r
+\r
+Herald DB 'MURTL1.0'\r
+nBytesPerSect DW 0200h ;nBytes/Sector\r
+nSectPerClstr DB 01h ;Sect/Cluster\r
+nRsvdSect DW 0001h ;Resvd sectors\r
+nFATS DB 02 ;nFATs\r
+nRootDirEnts DW 00E0h ;Root Dir entries max\r
+nTotalSectors DW 0B40h ;nTotal Sectors (0 = <32Mb)\r
+bMedia DB 0F0h ;media desc. (worthless)\r
+nSectPerFAT DW 0009h ;nSect in FAT\r
+nSectPerTrack DW 0012h ;nSectors/track\r
+nHeads DW 0002h ;nHeads\r
+nHidden DD 00000000h ;nHidden Sectors (first whole track on HD)\r
+nTotalSect32 DD 00000000h ;nTotalSectors if > 32Mb\r
+bBootDrive DB 00h ;Drive boot sector came from\r
+ResvdByte DB 00h ;Used for temp storage of Sector to Read\r
+ExtBootSig DB 29h ; Ext Boot Signature (always 29h)\r
+nOSSectors DW 0140h ; (140 sectors max) Was Volume ID number\r
+ResvdWord DW 0000h\r
+Volname DB 'RICH ' ;11 bytes for volume name\r
+FatType DB 'FAT12 ' ;8 bytes for FAT name (Type)\r
+\r
+\r
+;The following are pointers to my IDT and GDT after my OS loads\r
+; and are not part of the above boot sector structure.\r
+\r
+IDTptr DW 7FFh ;LIMIT 256 IDT Slots\r
+ DD 0000h ;BASE (Linear)\r
+\r
+GDTptr DW 17FFh ;LIMIT 768 slots\r
+ DD 0800h ;BASE (Linear)\r
+\r
+;This is where we jump from those first 3 bytes\r
+\r
+BootUp:\r
+\r
+;Boot blocks first instruction starts here after initial jump from beginning\r
+ CLI ;Clear interrupts\r
+\r
+ ;Stick the stack at 98000h (an arbitrary location)\r
+\r
+ MOV AX,9000h\r
+ MOV SS, AX\r
+ MOV SP, 8000h\r
+\r
+;Move this boot sector UP to 90000h Linear.\r
+\r
+ MOV AX, 09000h\r
+ MOV ES, AX\r
+ XOR DI, DI\r
+ MOV AX, 7C0h\r
+ MOV DS, AX\r
+ XOR SI, SI\r
+ MOV CX, 512\r
+ REP MOVSB\r
+\r
+ ; Now we jump UP to where we moved it.\r
+\r
+ MOV AX, 09000h ;Segment\r
+ PUSH AX\r
+ MOV AX, 6Fh ;Offset to new location\r
+ PUSH AX\r
+ RETF\r
+\r
+; Now set DS equal to ES which is 9000h\r
+ PUSH ES\r
+ POP DS\r
+ MOV CX, nSectPerTrack\r
+\r
+ XOR AX, AX\r
+ MOV DS, AX\r
+ MOV BX, 0078h ;Int 1E FDC Params!\r
+ LDS SI, DS:[BX]\r
+\r
+ MOV BYTE PTR [SI+4], CL\r
+ MOV BYTE PTR [SI+9], 0Fh\r
+\r
+ PUSH ES\r
+ POP DS\r
+ PUSH DS\r
+\r
+ STI\r
+\r
+ MOV DL, bBootDrive ;Required for Disk System Reset\r
+ XOR AX, AX\r
+\r
+ INT 13h ;Reset Disk Controller (DL has drive num)\r
+ JC SHORT BadBoot ;Reset failed...\r
+\r
+ POP DS\r
+\r
+ ;The controller is reset, now let's read some stuff!!\r
+ ;We are gonna skip checking to see if the first file\r
+ ;really IS the OS. We need the space for other code.\r
+\r
+ MOV SI, OFFSET MsgLoad\r
+ CALL PutChars\r
+\r
+ ;What we do now is calcualte our way to the third cluster\r
+ ;on the disk and read in the total number of OS sectors in\r
+ ;logical sector order. (3rd cluster is really the first allocated\r
+ ; cluster because first 2 are unused).\r
+ ;The layout of the Disk is:\r
+ ; Boot Sector (at logical sector 0)\r
+ ; Hidden Sectors (optional)\r
+ ; FATS (1 or more)\r
+ ; Additional Reserved sectors (optional)\r
+ ; Root Directory (n Sectors long)\r
+\r
+ XOR AX, AX\r
+ MOV AL, nFATS\r
+ MUL WORD PTR nSectPerFAT\r
+ ADD AX, WORD PTR nHidden ;\r
+ ADC DX, WORD PTR nHidden+2\r
+ ADD AX, nRsvdSect\r
+ MOV CX, AX ;Save in CX\r
+\r
+ ;CX now has a Word that contains the sector of the Root\r
+\r
+ ;Calculate the size of the root directory and skip past it\r
+ ;to the first allocated sectors (this is where the OS or\r
+ ;stage one of the a two stage loader should be).\r
+\r
+ MOV AX,0020h ;Size of Dir Entry\r
+ MUL WORD PTR nRootDirEnts\r
+ MOV BX, nBytesPerSect\r
+ DIV BX\r
+ ADD AX, CX\r
+\r
+ ;AX is at sector for cluster 0, but cluster 0 and 1 don't exist\r
+ ;so we are really at cluster 2 like we want to be.\r
+\r
+ MOV CX, nOSSectors ;Number of OS sectors to read\r
+ JMP SHORT ContinueBoot\r
+\r
+;Bad boot goes here and displays a message then\r
+;waits for a key to reboot (or tries to) via int 19h\r
+\r
+BadBoot:\r
+ MOV SI, OFFSET MsgBadDisk\r
+ CALL PutChars\r
+\r
+ XOR AX,AX\r
+ INT 16h ;Wait for keystroke\r
+ INT 19h ;Sys Reboot\r
+\r
+PutChars:\r
+ LODSB\r
+ OR AL,AL\r
+ JZ SHORT Done\r
+ MOV AH, 0Eh\r
+ MOV BX,0007\r
+ INT 10h\r
+ JMP SHORT PutChars\r
+Done:\r
+ RETN\r
+\r
+ContinueBoot:\r
+ MOV BX, 06000h ;This is segment where we load the OS.\r
+ MOV ES, BX\r
+\r
+NextSector:\r
+ PUSH AX\r
+ PUSH CX\r
+ PUSH DX\r
+ PUSH ES\r
+\r
+ XOR BX, BX\r
+\r
+; Read a logical sector to ES:BX\r
+; AX has Logical Sector Number\r
+;\r
+ MOV SI, nSectPerTrack\r
+ DIV SI ;Divide LogicalSect by nSectPerTrack\r
+ INC DL ;Sector numbering begins at 1 (not 0)\r
+ MOV ResvdByte, DL ;Sector to read\r
+ XOR DX, DX ;Logical Track left in AX\r
+ DIV WORD PTR nHeads ;Leaves Head in DL, Cyl in AX\r
+ MOV DH, bBootDrive\r
+ XCHG DL, DH ;Head to DH, Drive to DL\r
+ MOV CX, AX ;Cyl into CX\r
+ XCHG CL, CH ;Low 8 bits of Cyl to CH, Hi 2 bits to CL\r
+ SHL CL, 6 ; shifted to bits 6 and 7\r
+ OR CL, BYTE PTR ResvdByte ;OR with Sector number\r
+ MOV AL, 1 ;Number of sectors\r
+ MOV AH, 2 ;Read\r
+ INT 13h ;Read that sucker!\r
+ JC SHORT BadBoot\r
+\r
+ MOV SI, OFFSET MsgDot\r
+ CALL PutChars\r
+\r
+ POP ES\r
+ POP DX\r
+ POP CX\r
+ POP AX\r
+\r
+ MOV BX, ES\r
+ ADD BX, 20h ;512 bytes for segment\r
+ MOV ES, BX\r
+ INC AX ;Next Sector\r
+ LOOP NextSector\r
+\r
+ ;At this point we have the OS loaded in a contigous section\r
+ ;from 60000 linear up to about 80000 linear.\r
+ ;Now we disable interrupts, turn on the A20 line, move\r
+ ;it down to address 0, set protected mode and JUMP!\r
+\r
+ CLI\r
+ XOR CX,CX\r
+IBEmm0:\r
+ IN AL,64h\r
+ TEST AL,02h\r
+ LOOPNZ IBEmm0\r
+ MOV AL,0D1h\r
+ OUT 64h,AL\r
+ XOR CX,CX\r
+IBEmm1:\r
+ IN AL,64h\r
+ TEST AL,02h\r
+ LOOPNZ IBEmm1\r
+ MOV AL,0DFh\r
+ OUT 60h,AL\r
+ XOR CX,CX\r
+IBEmm2:\r
+ IN AL,64h\r
+ TEST AL,02h\r
+ LOOPNZ IBEmm2\r
+\r
+ ;A20 line should be ON Now\r
+ ;So move the OS\r
+\r
+ ; Set up our new DS to where we moved the data\r
+ ; We must do this before each 32K load cause we use DS */\r
+\r
+ MOV DX, 8000h\r
+\r
+ ; Move 64K data chunk from linear 60000h to linear 0\r
+\r
+ MOV BX, 06000h\r
+ MOV DS, BX\r
+ XOR SI, SI\r
+ XOR AX, AX\r
+ MOV ES,AX\r
+ XOR DI,DI\r
+ MOV CX, DX\r
+ CLD ;\r
+ REP MOVSW ;WORD move\r
+\r
+ ; Move first 64K code chunk from linear 70000h to 10000h\r
+\r
+ MOV BX, 07000h\r
+ MOV DS, BX\r
+ XOR SI, SI\r
+ MOV AX,1000h\r
+ MOV ES,AX\r
+ XOR DI,DI\r
+ MOV CX, DX\r
+ REP MOVSW ;WORD move\r
+\r
+ ; Move last code (32K) from linear 80000h to 18000h\r
+\r
+ MOV DS, DX ;DX is 8000h anyway\r
+ XOR SI, SI\r
+ MOV AX,2000h\r
+ MOV ES,AX\r
+ XOR DI,DI\r
+ MOV CX, DX\r
+ REP MOVSB ;BYTE move\r
+\r
+ MOV BX, 9000h\r
+ MOV DS, BX\r
+\r
+ XOR EDX, EDX\r
+ MOV DL, bBootDrive ;OS can find bootdrive in DL on entry\r
+\r
+ LIDT FWORD PTR IDTptr\r
+ LGDT FWORD PTR GDTptr\r
+\r
+ MOV EAX,CR0\r
+ OR AL,1\r
+ MOV CR0,EAX\r
+ JMP $+2\r
+ NOP\r
+ NOP\r
+\r
+ MOV BX, 10h\r
+ MOV DS,BX\r
+ MOV ES,BX\r
+ MOV FS,BX\r
+ MOV GS,BX\r
+ MOV SS,BX\r
+\r
+ ;We define a far jump with 48 bit pointer manually\r
+\r
+ DB 66h\r
+ DB 67h\r
+ DB 0EAh\r
+ DD 10000h\r
+ DW 8h\r
+\r
+MsgNone DB ' '\r
+MsgBadDisk DB 0Dh, 0Ah, 'Bad Boot Disk!', 00h\r
+MsgLoad DB 0Dh, 0Ah, 'Loading MMURTL', 00h\r
+MsgDot DB '.', 00h\r
+\r
+BootSig DW 0AA5Fh\r
+\r
+CSEG ENDS\r
+ END\r
+\r
+;Character Message stuff to save for troubleshooting\r
+; MOV BX, 0B800h\r
+; MOV ES, BX\r
+; XOR BX,BX\r
+; MOV WORD PTR ES:[BX], 4730h\r