
;    Simplexity boot loader
;    Copyright (C) 2009  Bogdan Barbu

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

SignatureWord:						EQU	0AA55H
ECCCorrectedDataError:					EQU	11H
White:							EQU	0111B

%defstr	ErrorMsg1 Invalid partition table.
%defstr	ErrorMsg2 Error loading operating system.
%defstr	ErrorMsg3 Missing operating system.

%strlen	ErrorCnt1 ErrorMsg1
%strlen	ErrorCnt2 ErrorMsg2
%strlen	ErrorCnt3 ErrorMsg3

STRUC	PartitionTableField
	BootIndicator:					RESB	1
	StartingCHS:					RESB	3
	SystemID:					RESB	1
	EndingCHS:					RESB	3
	RelativeSectors:				RESD	1
	TotalSectors:					RESD	1
ENDSTRUC

STRUC	DeviceAddressPacket
	PacketSizeInBytes:				RESB	1
	Reserved1:					RESB	1
	NumberOfBlocksToTransfer:			RESB	1
	Reserved2:					RESB	1
	AddressOfTransferBuffer:			RESD	1
	StartingLogicalBlockAddress:			RESQ	1
	FlatAddressOfTheTransferBuffer64Bit:		RESQ	1
ENDSTRUC

							ORG	400H+256

MasterBootCode:						; Set up stack
							XOR	AX,AX
							MOV	SS,AX
							MOV	SP,7C00H

							; Clear needed segment registers
							MOV	ES,AX
							MOV	DX,AX

							; Chaining mechanism
							MOV	CX,512/4
							MOV	SI,7C00H
							MOV	DI,$$
							CLD
							REP MOVSD
							JMP	Scan

Scan:							; Scan the partition table for the active partition
							MOV	SI,PartitionTable
.Check:							CMP	BYTE [SI+BootIndicator],00H
							JZ	.Next
							CMP	BYTE [SI+BootIndicator],80H
							JNE	Error1
							PUSH	SI
.Next:							ADD	SI,16
							CMP	SI,EndOfSectorMarker
							JL	.Check
							CMP	SP,7C00H-2
							JL	Error1
							JG	Error3

Load:							; Load a copy of the boot sector from the active partition into memory
							POP	SI

.LBA:							; Check extensions present
							MOV	AH,41H
							MOV	BX,55AAH
							INT	13H
							JC	.CHS
							CMP	BX,0AA55H
							JNE	.CHS
							BT	CX,0
							JNC	.CHS

							; Find the starting sector of the active partition
							MOV	EAX,[SI+RelativeSectors]
							MOV	[DiskAddressPacket+StartingLogicalBlockAddress],EAX
							; Extended read
							MOV	AH,42H
							MOV	SI,DiskAddressPacket
							INT	13H
							JMP	.Check

.CHS:							; Value-check for fixed disk interface
							BT	DX,7
							JNC	Error2

							; Read desired sector into memory
							MOV	AX,0201H
							; Find the starting sector of the active partition
							MOV	CX,[SI+StartingCHS+1]
							MOV	DH,[SI+StartingCHS]
							INT	13H

.Check:							JNC	Transfer
							CMP	AH,ECCCorrectedDataError
							JNE	Error2

Transfer:						; Transfer control to the executable code in the boot sector
							CMP	WORD [EndOfSectorMarker],SignatureWord
							JE	7C00H
							JMP	Error3

Error:							PUSH	CX

							; Read cursor position
							MOV	AH,03H
							XOR	BH,BH
							INT	10H

							POP	CX

							; Write string
							MOV	AX,1300H
							MOV	BX,White
							INT	10H

							; Set cursor position
							MOV	AH,02H
							INC	DH
							INT	10H

							; Return control to the BIOS
							INT	18H

%assign	i 0
%rep	3
	%assign	i i+1
	Error %+ i:					MOV	CX,ErrorCnt %+ i
							MOV	BP,ErrorStr %+ i
							JMP	Error
	ErrorStr %+ i:					DB	ErrorMsg %+ i
%endrep

							ALIGN	8

DiskAddressPacket:
	ISTRUC DeviceAddressPacket
		AT PacketSizeInBytes,			DB	FlatAddressOfTheTransferBuffer64Bit
		AT Reserved1,				DB	00H
		AT NumberOfBlocksToTransfer,		DB	01H
		AT Reserved2,				DB	00H
		AT AddressOfTransferBuffer,		DD	00000000H
		AT StartingLogicalBlockAddress,		DQ	0000000000000000H
		AT FlatAddressOfTheTransferBuffer64Bit,	DQ	0000000000000000H
	IEND

							TIMES	01B8H-($-$$) \
							DB	00H
DiskSignature:						DB	00H
							TIMES	01BEH-($-$$) \
							DB	00H
PartitionTable:						TIMES	(512-2)-($-$$) \
							DB	00H
EndOfSectorMarker:					DW	SignatureWord
