mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +00:00
c44d02099d
Now the FAT12/16 boot sector properly works on all FAT12/16 partition types (1, 4, 6, 0xe) Fixed a few small bugs svn path=/trunk/; revision=2852
249 lines
11 KiB
NASM
249 lines
11 KiB
NASM
|
|
;
|
|
; The BP register is initialized to 0x7c00, the start of
|
|
; the boot sector. The SP register is initialized to
|
|
; 0x7bf0, leaving 16 bytes of data storage space above
|
|
; the stack.
|
|
;
|
|
; The DWORD that gets stored at 0x7bfc is the logical
|
|
; sector number of the start of the data area.
|
|
;
|
|
; The DWORD that gets stored at 0x7bf8 is ????????
|
|
;
|
|
; The DWORD that gets stored at 0x7bf4 is ????????
|
|
;
|
|
; The DWORD that gets stored at 0x7bf0 is ????????
|
|
;
|
|
|
|
|
|
org 7c00h
|
|
|
|
segment .text
|
|
|
|
bits 16
|
|
|
|
start:
|
|
jmp short main
|
|
nop
|
|
|
|
OEMName db 'MSWIN4.0'
|
|
BytesPerSector dw 512
|
|
SectsPerCluster db 1
|
|
ReservedSectors dw 1
|
|
NumberOfFats db 2
|
|
MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
|
|
TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
|
|
MediaDescriptor db 0f8h
|
|
SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
|
|
SectorsPerTrack dw 18
|
|
NumberOfHeads dw 2
|
|
HiddenSectors dd 0
|
|
TotalSectorsBig dd 0
|
|
BootDrive db 80h
|
|
Reserved db 0
|
|
ExtendSig db 29h
|
|
SerialNumber dd 00000000h
|
|
VolumeLabel db 'NO NAME '
|
|
FileSystem db 'FAT16 '
|
|
|
|
main:
|
|
00007C3E 33C9 xor cx,cx
|
|
00007C40 8ED1 mov ss,cx ; Setup stack
|
|
00007C42 BCF07B mov sp,0x7bf0 ; Give us 16 bytes (4 dwords) of space above stack
|
|
00007C45 8ED9 mov ds,cx
|
|
00007C47 B80020 mov ax,0x2000
|
|
00007C4A 8EC0 mov es,ax ; Setup ES:0000 == 2000:0000
|
|
00007C4C FC cld
|
|
00007C4D BD007C mov bp,0x7c00
|
|
00007C50 384E24 cmp [bp+BootDrive],cl ; Compare the boot drive to zero (I think they are testing for a hard disk drive number)
|
|
00007C53 7D24 jnl floppy_boot ; Nope, it's a floppy, skip partition table tests
|
|
00007C55 8BC1 mov ax,cx ; Move zero to AX
|
|
00007C57 99 cwd ; DX:AX now contains zero
|
|
00007C58 E83C01 call read_one_sector ; Try to read in the MBR sector
|
|
00007C5B 721C jc floppy_boot ; Read failed, continue
|
|
00007C5D 83EB3A sub bx,byte +0x3a ; BX comes back with 512, make it equal to 454 (offset of partition table in MBR)
|
|
00007C60 66A11C7C mov eax,[HiddenSectors] ; Put HiddenSectors in EAX
|
|
find_our_partition:
|
|
00007C64 26663B07 cmp eax,[es:bx] ; Compare partition table entry's start sector to HiddenSectors
|
|
00007C68 268A57FC mov dl,[es:bx-0x4] ; Get partition type byte for this entry
|
|
00007C6C 7506 jnz next_partition_entry ; If partition start sector != HiddenSectors then skip this entry
|
|
00007C6E 80CA02 or dl,0x2 ; Set the second bit in partition type?? I guess this makes types 4 & 6 identical
|
|
00007C71 885602 mov [bp+0x2],dl ; Save it on top of nop instruction (3rd byte of boot sector)
|
|
next_partition_entry:
|
|
00007C74 80C310 add bl,0x10 ; Add 16 to bl (offset of next entry in partition table)
|
|
00007C77 73EB jnc find_our_partition ; Jump back until we hit the end of the partition table
|
|
|
|
; We now have our partition type at 0000:7C02
|
|
; If the type was 4 or 6 then that byte is 6
|
|
; I can't imagine why the boot sector needs to store
|
|
; this information, but hopefully I will uncover it
|
|
; as I further disassemble this boot sector.
|
|
|
|
|
|
floppy_boot:
|
|
00007C79 33C9 xor cx,cx ; Zero out CX
|
|
00007C7B 8A4610 mov al,[bp+NumberOfFats] ; Get the number of FATs in AL (usually 2)
|
|
00007C7E 98 cbw ; Sign extend it into AX (AX == 2)
|
|
00007C7F F76616 mul word [bp+NumberOfFats] ; Multiply it with NumberOfFats PLUS the low byte of MaxRootEntries!!??
|
|
00007C82 03461C add ax,[bp+HiddenSectors] ; Result is in DX:AX
|
|
00007C85 13561E adc dx,[bp+HiddenSectors+2] ; Add HiddenSectors to DX:AX
|
|
00007C88 03460E add ax,[bp+ReservedSectors] ; Add ReservedSectors to DX:AX
|
|
00007C8B 13D1 adc dx,cx ; CX still contains zero
|
|
00007C8D 8B7611 mov si,[bp+MaxRootEntries] ; Get MaxRootEntries in SI
|
|
00007C90 60 pusha ; Save all registers (right now DX:AX has starting sector of root dir)
|
|
00007C91 8946FC mov [bp-0x4],ax ; Save the starting sector of the root directory
|
|
00007C94 8956FE mov [bp-0x2],dx ; Save it in the first 4 bytes before the boot sector
|
|
00007C97 B82000 mov ax,0x20 ; AX == 32 (size of a directory entry)
|
|
00007C9A F7E6 mul si ; Multiply it with MaxRootEntries (DX:AX == length in bytes of root directory)
|
|
00007C9C 8B5E0B mov bx,[bp+BytesPerSector] ; Get the BytesPerSector in BX
|
|
00007C9F 03C3 add ax,bx ; Add it to AX (what if this addition carries? MS should 'adc dx,0' shouldn't they?)
|
|
00007CA1 48 dec ax ; Subtract one (basically rounding up)
|
|
00007CA2 F7F3 div bx ; Divide DX:AX (length of root dir in bytes) by the size of a sector
|
|
00007CA4 0146FC add [bp-0x4],ax ; Add the number of sectors of the root directory to our other value
|
|
00007CA7 114EFE adc [bp-0x2],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
|
|
00007CAA 61 popa ; Restore all registers (DX:AX has start sector of root dir)
|
|
load_root_dir_sector:
|
|
00007CAB BF0000 mov di,0x0 ; Zero out di
|
|
00007CAE E8E600 call read_one_sector ; Read the first sector of the root directory
|
|
00007CB1 7239 jc print_disk_error_message ; Read failed, print disk error and reboot
|
|
search_directory:
|
|
00007CB3 26382D cmp [es:di],ch ; If the first byte of the directory entry is zero then we have reached the end
|
|
00007CB6 7417 jz print_ntldr_error_message; of the directory and NTLDR is not here so reboot
|
|
00007CB8 60 pusha ; Save all registers
|
|
00007CB9 B10B mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
|
|
00007CBB BEA17D mov si,NTLDR ; Put offset of filename string in DS:SI
|
|
00007CBE F3A6 repe cmpsb ; Compare this directory entry against 'NTLDR '
|
|
00007CC0 61 popa ; Restore all the registers
|
|
00007CC1 7432 jz found_ntldr ; If we found NTLDR then jump
|
|
00007CC3 4E dec si ; SI holds MaxRootEntries, subtract one
|
|
00007CC4 7409 jz print_ntldr_error_message; If we are out of root dir entries then reboot
|
|
00007CC6 83C720 add di,byte +0x20 ; Increment DI by the size of a directory entry
|
|
00007CC9 3BFB cmp di,bx ; Compare DI to BX (DI has offset to next dir entry, BX has address of end of directory sector in memory)
|
|
00007CCB 72E6 jc search_directory ; If DI is less than BX loop again
|
|
00007CCD EBDC jmp short load_root_dir_sector ; Didn't find NTLDR in this directory sector, try again
|
|
print_ntldr_error_message:
|
|
00007CCF A0FB7D mov al,[NTLDR_ERR_offset_from_0x7d00]
|
|
putchars:
|
|
00007CD2 B47D mov ah,0x7d
|
|
00007CD4 8BF0 mov si,ax
|
|
get_another_char:
|
|
00007CD6 AC lodsb
|
|
00007CD7 98 cbw
|
|
00007CD8 40 inc ax
|
|
00007CD9 740C jz print_reboot_message
|
|
00007CDB 48 dec ax
|
|
00007CDC 7413 jz reboot
|
|
00007CDE B40E mov ah,0xe
|
|
00007CE0 BB0700 mov bx,0x7
|
|
00007CE3 CD10 int 0x10
|
|
00007CE5 EBEF jmp short get_another_char
|
|
print_reboot_message:
|
|
00007CE7 A0FD7D mov al,[RESTART_ERR_offset_from_0x7d00]
|
|
00007CEA EBE6 jmp short putchars
|
|
print_disk_error_message:
|
|
00007CEC A0FC7D mov al,[DISK_ERR_offset_from_0x7d00]
|
|
00007CEF EBE1 jmp short putchars
|
|
reboot:
|
|
00007CF1 CD16 int 0x16
|
|
00007CF3 CD19 int 0x19
|
|
found_ntldr:
|
|
00007CF5 268B551A mov dx,[es:di+0x1a] ; Get NTLDR start cluster in DX
|
|
00007CF9 52 push dx ; Save it on the stack
|
|
00007CFA B001 mov al,0x1 ; Read 1 cluster? Or is this one sector?
|
|
00007CFC BB0000 mov bx,0x0 ; ES:BX is the load address (2000:0000)
|
|
00007CFF E83B00 call read_cluster ; Do the read
|
|
00007D02 72E8 jc print_disk_error_message ; If it failed then reboot
|
|
00007D04 5B pop bx ; Get the start cluster of NTLDR in BX
|
|
00007D05 8A5624 mov dl,[bp+BootDrive] ; Get boot drive in DL
|
|
00007D08 BE0B7C mov si,0x7c0b
|
|
00007D0B 8BFC mov di,sp
|
|
00007D0D C746F03D7D mov word [bp-0x10],read_cluster
|
|
00007D12 C746F4297D mov word [bp-0xc],0x7d29
|
|
00007D17 8CD9 mov cx,ds
|
|
00007D19 894EF2 mov [bp-0xe],cx
|
|
00007D1C 894EF6 mov [bp-0xa],cx
|
|
00007D1F C606967DCB mov byte [0x7d96],0xcb
|
|
00007D24 EA03000020 jmp 0x2000:0x3
|
|
00007D29 0FB6C8 movzx cx,al
|
|
00007D2C 668B46F8 mov eax,[bp-0x8]
|
|
00007D30 6603461C add eax,[bp+HiddenSectors]
|
|
00007D34 668BD0 mov edx,eax
|
|
00007D37 66C1EA10 shr edx,0x10
|
|
00007D3B EB5E jmp short 0x7d9b
|
|
read_cluster:
|
|
00007D3D 0FB6C8 movzx cx,al
|
|
00007D40 4A dec dx
|
|
00007D41 4A dec dx
|
|
00007D42 8A460D mov al,[bp+SectsPerCluster]
|
|
00007D45 32E4 xor ah,ah
|
|
00007D47 F7E2 mul dx
|
|
00007D49 0346FC add ax,[bp-0x4]
|
|
00007D4C 1356FE adc dx,[bp-0x2]
|
|
00007D4F EB4A jmp short 0x7d9b
|
|
|
|
read_sectors:
|
|
00007D51 52 push dx
|
|
00007D52 50 push ax
|
|
00007D53 06 push es
|
|
00007D54 53 push bx
|
|
00007D55 6A01 push byte +0x1
|
|
00007D57 6A10 push byte +0x10
|
|
00007D59 91 xchg ax,cx
|
|
00007D5A 8B4618 mov ax,[bp+SectorsPerTrack]
|
|
00007D5D 96 xchg ax,si
|
|
00007D5E 92 xchg ax,dx
|
|
00007D5F 33D2 xor dx,dx
|
|
00007D61 F7F6 div si
|
|
00007D63 91 xchg ax,cx
|
|
00007D64 F7F6 div si
|
|
00007D66 42 inc dx
|
|
00007D67 87CA xchg cx,dx
|
|
00007D69 F7761A div word [bp+NumberOfHeads]
|
|
00007D6C 8AF2 mov dh,dl
|
|
00007D6E 8AE8 mov ch,al
|
|
00007D70 C0CC02 ror ah,0x2
|
|
00007D73 0ACC or cl,ah
|
|
00007D75 B80102 mov ax,0x201
|
|
00007D78 807E020E cmp byte [bp+0x2],0xe
|
|
00007D7C 7504 jnz 0x7d82
|
|
00007D7E B442 mov ah,0x42
|
|
00007D80 8BF4 mov si,sp
|
|
00007D82 8A5624 mov dl,[bp+BootDrive]
|
|
00007D85 CD13 int 0x13
|
|
00007D87 61 popa
|
|
00007D88 61 popa
|
|
00007D89 720B jc 0x7d96
|
|
00007D8B 40 inc ax
|
|
00007D8C 7501 jnz 0x7d8f
|
|
00007D8E 42 inc dx
|
|
00007D8F 035E0B add bx,[bp+BytesPerSector]
|
|
00007D92 49 dec cx
|
|
00007D93 7506 jnz 0x7d9b
|
|
00007D95 F8 clc
|
|
00007D96 C3 ret
|
|
|
|
read_one_sector:
|
|
00007D97 41 inc cx
|
|
00007D98 BB0000 mov bx,0x0
|
|
00007D9B 60 pusha
|
|
00007D9C 666A00 o32 push byte +0x0
|
|
00007D9F EBB0 jmp short 0x7d51
|
|
|
|
|
|
NTLDR db 'NTLDR '
|
|
|
|
|
|
NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
|
|
DISK_ERR db 0dh,0ah,'Disk error',0ffh
|
|
RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
|
|
|
|
filler times 18 db 0
|
|
|
|
|
|
NTLDR_offset_from_0x7d00 db 0
|
|
NTLDR_ERR_offset_from_0x7d00 db 0ach
|
|
DISK_ERR_offset_from_0x7d00 db 0bfh
|
|
RESTART_ERR_offset_from_0x7d00 db 0cch
|
|
|
|
dw 0
|
|
dw 0aa55h
|