; WINDOWS XP FAT32 BOOT SECTOR SOURCE CODE (sector 0, 1st half of VBR)
; by Erdogan Tan - 12/12/2017
; Disassembler: IDA Pro Free by Hex-Rays SA

; Last Modification: 16/12/2017

; ---------------------------------------------------------------------------
; º	This file is generated by The Interactive Disassembler (IDA)	    º
; º	Copyright (c) 2010 by Hex-Rays SA, <support@hex-rays.com>	    º
; º			 Licensed to: Freeware version			    º
; ---------------------------------------------------------------------------
; File Name   :	xp_fat32_bs.bin

		.386
		.model flat

; ---------------------------------------------------------------------------

; Segment type:	Regular
seg000		segment	byte public '' use16
		assume cs:seg000
		assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
; ---------------------------------------------------------------------------
		;org	7C00h
BS_jmpBoot:
		jmp	short loc_5A
		nop	; db 90h
; ---------------------------------------------------------------------------
BS_OEMName:
		db	'FRDOS4.1'	; bp+3
BPB_BytesPerSec: dw	512		; bp+11
BPB_SecPerClus:	db	32		; bp+13
BPB_RsvdSecCnt:	dw	34		; bp+14
BPB_NumFATs:	db	2		; bp+16
BPB_RootEntCnt: dw	0		; bp+17
BPB_TotSec16:	dw	0		; bp+19
BPB_Media:	db	0F8h		; bp+21
BPB_FATSz16:	dw	0		; bp+22
BPB_SecPerTrk:	dw	63		; bp+24
BPB_NumHeads:	dw	255		; bp+26
BPB_HiddSec:	dd	63		; bp+28
BPB_TotSec32:	dd	61432497	; bp+32
BPB_FATSz32:	dd	14991		; bp+36
BPB_ExtFlags:	dw	0		; bp+40
BPB_FSVer:	dw	0		; bp+42
BPB_RootClus:	dd	2		; bp+44
BPB_FSInfo:	dw	1		; bp+48
BPB_BkBootSec:	dw	6		; bp+50
BPB_Reserved:	db	12 dup (0)	; bp+52
BS_DrvNum:	db	80h		; bp+64
BS_Reserved1:	db	0		; bp+65
BS_BootSig:	db	29h		; bp+66
BS_VolID:	dd	1A3319E7h	; bp+67
BS_VolLab:	db	'NO NAME    '	; bp+71
BS_FilSysType:	db	'FAT32   '	; bp+82

; ---------------------------------------------------------------------------

loc_5A:		
		xor	cx, cx
		mov	ss, cx
		mov	sp, 7BF4h
		mov	es, cx
		mov	ds, cx	
		mov	bp, 7C00h
		mov	[bp+2],	cl ; 0	; [BS_jmpBoot+2] 	
		mov	dl, [bp+40h]	; [BS_DrvNum]
		mov	ah, 8
		int	13h	; DISK - GET CURRENT DRIVE PARAMETERS
				; DL = drive number
				; Return: CF set on error, 
				; AH = status code, BL = drive type
				; DL = number of consecutive drives
				; DH = maximum value for head number
				; ES:DI -> drive parameter
		jnb	short loc_79
		mov	cx, 0FFFFh
		mov	dh, cl
loc_79:	
		; calculate CHS read (sector) limit
		movzx	eax, dh ; head
		inc	ax	; number of heads
		movzx	edx, cl
		and	dl, 3Fh
		mul	dx	; heads * sectors (per track)
		; AX = sectors per cylinder 
		xchg	cl, ch
		shr	ch, 6
		inc	cx
		; CX = number of cylinders
		movzx	ecx, cx
		mul	ecx
		mov	[bp-8],	eax	; CHS limit
					; (Sector address 
					; must be less than this limit
					; value for CHS read mode).

		; Check FAT32 boot sector (BPB) validiation
		cmp	word ptr [bp+16h], 0 ; [BPB_FATSz16]
		jnz	short loc_D6 ; invalid system disk error
		cmp	word ptr [bp+2Ah], 0 ; [BPB_FSVer]
		ja	short loc_D6 ; invalid system disk error
		;
		; Read boot sector 2 (the 2nd half of FAT32 boot record)
		mov	eax, [bp+1Ch]	; [BPB_HiddSec]
		add	eax, 0Ch ; 12	; Sector 12 in FAT32 partition		
		mov	bx, 8000h	; Buffer addr for boot sector 2	
		mov	cx, 1		; read 1 sector
		call	disk_read	; call loc_E0
		jmp	near ptr 400h	; boot sector 2
; ---------------------------------------------------------------------------

loc_B8:		; Disk I/O (read) error
		mov	al, ds:7DFAh 	; low byte of
					; 'disk error' msg address
loc_BB:	
		mov	ah, 7Dh		; High byte of error msg address 
		mov	si, ax
loc_BF:	
		lodsb
		test	al, al
		jz	short loc_DB
		cmp	al, 0FFh
		jz	short loc_D1	; next row: 'press any to restart'
		mov	ah, 0Eh
		mov	bx, 7
		int	10h	; VIDEO - WRITE CHARACTER & ADVANCE CURSOR
				; AL = character, BH = display page
				; BL = foreground color (graphics modes)
		jmp	short loc_BF
; ---------------------------------------------------------------------------

loc_D1:		; write 'press any key to restart' message	
		mov	al, ds:7DFBh	; low byte of
		jmp	short loc_BB	; 'press any key to restart' msg addr
; ---------------------------------------------------------------------------

loc_D6:		; invalid system disk ('NTLDR is missing') error
		mov	al, ds:7DF9h	; low byte of
		jmp	short loc_BB	; 'NTLDR is missing' msg address 
; ---------------------------------------------------------------------------

loc_DB:		; wait for a keystoke and then reboot
		; AL = 0
		cbw
		int	16h		; KEYBOARD -
		int	19h		; DISK BOOT
					; causes reboot	of disk	system
; ---------------------------------------------------------------------------

disk_read:
loc_E0:		pushad
		cmp	eax, [bp-8]	; CHS limit in 7BF8h
		jb	chs_read ; loc_134
		push	large 0
		push	eax
		push	es
		push	bx
		push	large 10010h
		cmp	byte ptr [bp+2], 0 ; [BS_jmpBoot+2] > 0 
					   ; LBA read is available
		jnz	lba_read ; loc_11F
		; Check INT 13h extensions (for LBA read function) 
		mov	ah, 41h	; 'A'
		mov	bx, 55AAh
		mov	dl, [bp+40h]
		int	13h		; DISK -
		jb	near ptr loc_128+1 ; 0F9h = stc instruction
		cmp	bx, 0AA55h
		jnz	near ptr loc_128+1 ; 0F9h = stc instruction
		test	cl, 1
		jz	near ptr loc_128+1 ; 0F9h = stc instruction
		inc	byte ptr [bp+2]	   ; = 1 ([BS_jmpBoot+2] > 0)	
lba_read:
loc_11F:	
		mov	ah, 42h ; LBA read
		mov	dl, [bp+40h]
		mov	si, sp
		int	13h		; DISK -
loc_128:	
		mov	al, 0F9h ; loc_129: stc (9F9h)
;loc_130: 
		pop	eax
		pop	eax
		pop	eax
		pop	eax
		jmp	short loc_15E
; ---------------------------------------------------------------------------

chs_read:
loc_134:	; CHS read
		; EAX = LBA (absolute) sector address
		; CX = sector count to read
		xor	edx, edx
		movzx	ecx, word ptr [bp+18h] ; [BPB_SecPerTrk]
		div	ecx
		inc	dl
		mov	cl, dl
		mov	edx, eax
		shr	edx, 10h
		div	word ptr [bp+1Ah] ; [BPB_NumHeads]
		xchg	dl, dh
		mov	dl, [bp+40h] ; [BS_DrvNum]
		mov	ch, al
		shl	ah, 6
		or	cl, ah
		mov	ax, 201h
		int	13h	; DISK - READ SECTORS INTO MEMORY
				; AL = number of sectors to read
				; CH = track, CL = sector
				; DH = head, DL	= drive 
				; ES:BX -> buffer to fill
				; Return: CF set on error, 
				; AH = status, AL = num of sectors read
loc_15E:	
		popad
		jb	loc_B8	; write 'Disk error' message 
		add	bx, 512 ; 200h ; [BPB_BytesPerSec] !?
		inc	eax
		dec	cx
		jnz	disk_read ; loc_E0
		retn
; ---------------------------------------------------------------------------
startup_file_name:
loc_170:
		db	'NTLDR      '
		db	loc_1AC-$ dup(0)
		;org	7DACh
ntldr_missing_msg:
loc_1AC:
		db	0Dh, 0Ah
		db	'NTLDR is missing'
		db	0FFh
disk_error_msg:
loc_1BF:
		db	0Dh, 0Ah
		db	'Disk error'
		db	0FFh
press_key_start_msg:
loc_1CC:	
		db	0Dh, 0Ah
		db	'Press any key to restart'
		db	0Dh, 0Ah, 0
loc_1E9:		
		;db	505-$ dup(0)
		db	0, 0, 0, 0, 0, 0, 0, 0
		db	0, 0, 0, 0, 0, 0, 0, 0

		;org 	7DF9h
loc_1F9:			; 7DF9h
		db	0ACh
loc_1FA:			; 7DFAh
		db	0BFh
loc_1FB:			; 7DFBh
		db	0CCh
loc_1FC:
		;db	7DFEh-$ dup(0)
		db	0, 0
		;org 	7DFEh
loc_1FE:
boot_sector_sign:
		db	55h, 0AAh

seg000		ends

		end