;boot.asm - Master Boot Record v0.1 Alpha
;Created by Timothy Williams on 041317-2157

Bits 16             ;Tell NASM that we are in Real 16-Bit Mode
org 0x0600          ;origin of start

;Set up segments and stack, then copy MBR from 0x7C00 to 0x0600
start:
cli
xor ax, ax
mov ss, ax
mov sp, 0x7C00
push ax
push ax
pop ds
pop es
sti

cld
mov si, 0x7C00
mov di, 0x0600
mov cx, 0x0200
rep movsb

push es
push MBR_Main
retf

;By the way, if your BIOS for some reasons happens  to load this sector to 07C0:0000, (of course, if it will happen), this will fix that

MBR_Main:
mov cx, 0x04
mov bp, PT1_Status
Check_Table:
cmp [bp], BYTE 0x00
jnz Invalid_Table
add bp, 0x10
loop Check_Table

int 0x18

;Right here, this starts up the error handler.
Invalid_Table:
lea si, [INVALID_TABLE]
jmp Print_Error
Error_Load:
lea si, [ERROR_LOAD]
jmp Print_Error
Missing_OS:
lea si, [MISSING_OS]
Print_Error:
call PrintS
lea si, [PRESS_KEY]
call PrintS

cbw
int 0x16
mov di, 0x0472
mov [es:di], WORD 0x1234
push 0xFFFF
push 0x0000
retf

;This Sub-Routine simply prints out a null-terminated string pointed to by DS:SI
PrintS:
lodsb
or al, al
jz PrintS_Return
mov ah, 0Eh
mov bx, 0x0007
int 0x10
jmp PrintS
PrintS_Return:
ret

;Here's where our code goes if it finds a bootable partition
Found_Entry:
mov [bp], dl

mov ah, 0x41
mov bx, 0xAA55
int 0x13
jc No_Ext
cmp bx, WORD 0xAA55
jne No_Ext

;Whatever, let's move on.
mov cx, 0x05
mov eax, DWORD [bp+0x08]
mov DWORD [DAP_LBA_LSD], eax
Ext_Read:
mov ah, 0x42
mov dl, [bp]
lea si, [DAP_Size]
int 0x13
jnc Verify_VBR

or cx, cx
jz Error_Load
dec cx

xor ah, ah
int 0x13
jc Error_Load
jmp Ext_Read

;Load VBR to 0000:7C00 without int 13h extensions
No_Ext:
mov di, 0x05
Read_Disk:
mov ax, 0x0201
mov bx, 0x7C00
mov dl, [bp]
mov dh, [bp+0x01]
mov cl, [bp+0x02]
mov ch, [bp+0x03]
int 0x13
jnc Verify_VBR

or di, di
jz Error_Load
dec di

xor ah, ah
int 0x13
jc Error_Load
jmp Read_Disk

Verify_VBR:
mov si, 0x7DF
cmp [si], WORD 0xAA55
jne Missing_OS

stc
push es
push 0x7C00
retf

;Error messages go here. Add more if you want.
INVALID_TABLE       db "ERROR: INVALID PARTITION TABLE. SYSTEM HALTED.", 0
ERROR_LOAD          db "ERROR: COULD NOT LOAD OS. SYSTEM HALTED.", 0
MISSING_OS          db "Missing operating system", 0
PRESS_KEY           db "If you need to restart, press any key to do so.", 0

;DAP - Disk Address Packet
DAP_Size			db 0x10					;Size of packet, always 16 BYTES
DAP_Reserved		db 0x00					;Reserved
DAP_Sectors			dw 0x0001				;Number of sectors to read, one
DAP_Offset			dw 0x7C00				;Read to 0000:7C00
DAP_Segment 		dw 0x0000
DAP_LBA_LSD			dd 0x00000000			;This is where the LBA of our VBR goes, Even though it's a DWORD.
DAP_LBA_MSD			dd 0x00000000			;The DAP takes a QWORD for some reason, why would you ever need to access a QWORD
											;sized LBA in Real mode? Better yet how would you handle one?

times 440-($-$$)	db 0x00					;Make sure code section is 440 bytes
;End of code area

Disk_Sig 			dd 0x00000000			;Disk signature, used to track drives
Reserved 			dw 0x0000				;Reserved

;Partition table - Four 16-Byte entries describing the disk partitioning
PT1_Status			db 0x00					;Drive number/Bootable flag
PT1_First_Head  	db 0x00					;First Head
PT1_First_Sector	db 0x00					;Bits 0-5:First Sector|Bits 6-7 High bits of First Cylinder
PT1_First_Cylinder	db 0x00					;Bits 0-7 Low bits of First Cylinder
PT1_Part_Type		db 0x00					;Partition Type
PT1_Last_Head	  	db 0x00					;Last Head
PT1_Last_Sector		db 0x00					;Bits 0-5:Last Sector|Bits 6-7 High bits of Last Cylinder
PT1_Last_Cylinder	db 0x00					;Bits 0-7 Low bits of Last Cylinder
PT1_First_LBA		dd 0x00000000			;Starting LBA of Partition
PT1_Total_Sectors	dd 0x00000000			;Total Sectors in Partition

PT2_Status			db 0x00
PT2_First_Head  	db 0x00
PT2_First_Sector	db 0x00
PT2_First_Cylinder	db 0x00
PT2_Part_Type		db 0x00
PT2_Last_Head	  	db 0x00
PT2_Last_Sector		db 0x00
PT2_Last_Cylinder	db 0x00
PT2_First_LBA		dd 0x00000000
PT2_Total_Sectors	dd 0x00000000

PT3_Status			db 0x00
PT3_First_Head  	db 0x00
PT3_First_Sector	db 0x00
PT3_First_Cylinder	db 0x00
PT3_Part_Type		db 0x00
PT3_Last_Head	  	db 0x00
PT3_Last_Sector		db 0x00
PT3_Last_Cylinder	db 0x00
PT3_First_LBA		dd 0x00000000
PT3_Total_Sectors	dd 0x00000000

PT4_Status			db 0x00
PT4_First_Head  	db 0x00
PT4_First_Sector	db 0x00
PT4_First_Cylinder	db 0x00
PT4_Part_Type		db 0x00
PT4_Last_Head	  	db 0x00
PT4_Last_Sector		db 0x00
PT4_Last_Cylinder	db 0x00
PT4_First_LBA		dd 0x00000000
PT4_Total_Sectors	dd 0x00000000

					db 0x55					;Indicates that this is a Boot sector
					db 0xAA
