merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / boot / freeldr / bootsect / wxpfat16.asm
1
2 ;
3 ; The BP register is initialized to 0x7c00, the start of
4 ; the boot sector. The SP register is initialized to
5 ; 0x7bf0, leaving 16 bytes of data storage space above
6 ; the stack.
7 ;
8 ; The DWORD that gets stored at 0x7bfc is the logical
9 ; sector number of the start of the data area.
10 ;
11 ; The DWORD that gets stored at 0x7bf8 is ????????
12 ;
13 ; The DWORD that gets stored at 0x7bf4 is ????????
14 ;
15 ; The DWORD that gets stored at 0x7bf0 is ????????
16 ;
17
18
19 org 7c00h
20
21 segment .text
22
23 bits 16
24
25 start:
26 jmp short main
27 nop
28
29 OEMName db 'MSWIN4.0'
30 BytesPerSector dw 512
31 SectsPerCluster db 1
32 ReservedSectors dw 1
33 NumberOfFats db 2
34 MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
35 TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
36 MediaDescriptor db 0f8h
37 SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
38 SectorsPerTrack dw 18
39 NumberOfHeads dw 2
40 HiddenSectors dd 0
41 TotalSectorsBig dd 0
42 BootDrive db 80h
43 Reserved db 0
44 ExtendSig db 29h
45 SerialNumber dd 00000000h
46 VolumeLabel db 'NO NAME '
47 FileSystem db 'FAT16 '
48
49 main:
50 00007C3E 33C9 xor cx,cx
51 00007C40 8ED1 mov ss,cx ; Setup stack
52 00007C42 BCF07B mov sp,0x7bf0 ; Give us 16 bytes (4 dwords) of space above stack
53 00007C45 8ED9 mov ds,cx
54 00007C47 B80020 mov ax,0x2000
55 00007C4A 8EC0 mov es,ax ; Setup ES:0000 == 2000:0000
56 00007C4C FC cld
57 00007C4D BD007C mov bp,0x7c00
58 00007C50 384E24 cmp [bp+BootDrive],cl ; Compare the boot drive to zero (I think they are testing for a hard disk drive number)
59 00007C53 7D24 jnl floppy_boot ; Nope, it's a floppy, skip partition table tests
60 00007C55 8BC1 mov ax,cx ; Move zero to AX
61 00007C57 99 cwd ; DX:AX now contains zero
62 00007C58 E83C01 call read_one_sector ; Try to read in the MBR sector
63 00007C5B 721C jc floppy_boot ; Read failed, continue
64 00007C5D 83EB3A sub bx,byte +0x3a ; BX comes back with 512, make it equal to 454 (offset of partition table in MBR)
65 00007C60 66A11C7C mov eax,[HiddenSectors] ; Put HiddenSectors in EAX
66 find_our_partition:
67 00007C64 26663B07 cmp eax,[es:bx] ; Compare partition table entry's start sector to HiddenSectors
68 00007C68 268A57FC mov dl,[es:bx-0x4] ; Get partition type byte for this entry
69 00007C6C 7506 jnz next_partition_entry ; If partition start sector != HiddenSectors then skip this entry
70 00007C6E 80CA02 or dl,0x2 ; Set the second bit in partition type?? I guess this makes types 4 & 6 identical
71 00007C71 885602 mov [bp+0x2],dl ; Save it on top of nop instruction (3rd byte of boot sector)
72 next_partition_entry:
73 00007C74 80C310 add bl,0x10 ; Add 16 to bl (offset of next entry in partition table)
74 00007C77 73EB jnc find_our_partition ; Jump back until we hit the end of the partition table
75
76 ; We now have our partition type at 0000:7C02
77 ; If the type was 4 or 6 then that byte is 6
78 ; I can't imagine why the boot sector needs to store
79 ; this information, but hopefully I will uncover it
80 ; as I further disassemble this boot sector.
81
82
83 floppy_boot:
84 00007C79 33C9 xor cx,cx ; Zero out CX
85 00007C7B 8A4610 mov al,[bp+NumberOfFats] ; Get the number of FATs in AL (usually 2)
86 00007C7E 98 cbw ; Sign extend it into AX (AX == 2)
87 00007C7F F76616 mul word [bp+NumberOfFats] ; Multiply it with NumberOfFats PLUS the low byte of MaxRootEntries!!??
88 00007C82 03461C add ax,[bp+HiddenSectors] ; Result is in DX:AX
89 00007C85 13561E adc dx,[bp+HiddenSectors+2] ; Add HiddenSectors to DX:AX
90 00007C88 03460E add ax,[bp+ReservedSectors] ; Add ReservedSectors to DX:AX
91 00007C8B 13D1 adc dx,cx ; CX still contains zero
92 00007C8D 8B7611 mov si,[bp+MaxRootEntries] ; Get MaxRootEntries in SI
93 00007C90 60 pusha ; Save all registers (right now DX:AX has starting sector of root dir)
94 00007C91 8946FC mov [bp-0x4],ax ; Save the starting sector of the root directory
95 00007C94 8956FE mov [bp-0x2],dx ; Save it in the first 4 bytes before the boot sector
96 00007C97 B82000 mov ax,0x20 ; AX == 32 (size of a directory entry)
97 00007C9A F7E6 mul si ; Multiply it with MaxRootEntries (DX:AX == length in bytes of root directory)
98 00007C9C 8B5E0B mov bx,[bp+BytesPerSector] ; Get the BytesPerSector in BX
99 00007C9F 03C3 add ax,bx ; Add it to AX (what if this addition carries? MS should 'adc dx,0' shouldn't they?)
100 00007CA1 48 dec ax ; Subtract one (basically rounding up)
101 00007CA2 F7F3 div bx ; Divide DX:AX (length of root dir in bytes) by the size of a sector
102 00007CA4 0146FC add [bp-0x4],ax ; Add the number of sectors of the root directory to our other value
103 00007CA7 114EFE adc [bp-0x2],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
104 00007CAA 61 popa ; Restore all registers (DX:AX has start sector of root dir)
105 load_root_dir_sector:
106 00007CAB BF0000 mov di,0x0 ; Zero out di
107 00007CAE E8E600 call read_one_sector ; Read the first sector of the root directory
108 00007CB1 7239 jc print_disk_error_message ; Read failed, print disk error and reboot
109 search_directory:
110 00007CB3 26382D cmp [es:di],ch ; If the first byte of the directory entry is zero then we have reached the end
111 00007CB6 7417 jz print_ntldr_error_message; of the directory and NTLDR is not here so reboot
112 00007CB8 60 pusha ; Save all registers
113 00007CB9 B10B mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
114 00007CBB BEA17D mov si,NTLDR ; Put offset of filename string in DS:SI
115 00007CBE F3A6 repe cmpsb ; Compare this directory entry against 'NTLDR '
116 00007CC0 61 popa ; Restore all the registers
117 00007CC1 7432 jz found_ntldr ; If we found NTLDR then jump
118 00007CC3 4E dec si ; SI holds MaxRootEntries, subtract one
119 00007CC4 7409 jz print_ntldr_error_message; If we are out of root dir entries then reboot
120 00007CC6 83C720 add di,byte +0x20 ; Increment DI by the size of a directory entry
121 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)
122 00007CCB 72E6 jc search_directory ; If DI is less than BX loop again
123 00007CCD EBDC jmp short load_root_dir_sector ; Didn't find NTLDR in this directory sector, try again
124 print_ntldr_error_message:
125 00007CCF A0FB7D mov al,[NTLDR_ERR_offset_from_0x7d00]
126 putchars:
127 00007CD2 B47D mov ah,0x7d
128 00007CD4 8BF0 mov si,ax
129 get_another_char:
130 00007CD6 AC lodsb
131 00007CD7 98 cbw
132 00007CD8 40 inc ax
133 00007CD9 740C jz print_reboot_message
134 00007CDB 48 dec ax
135 00007CDC 7413 jz reboot
136 00007CDE B40E mov ah,0xe
137 00007CE0 BB0700 mov bx,0x7
138 00007CE3 CD10 int 0x10
139 00007CE5 EBEF jmp short get_another_char
140 print_reboot_message:
141 00007CE7 A0FD7D mov al,[RESTART_ERR_offset_from_0x7d00]
142 00007CEA EBE6 jmp short putchars
143 print_disk_error_message:
144 00007CEC A0FC7D mov al,[DISK_ERR_offset_from_0x7d00]
145 00007CEF EBE1 jmp short putchars
146 reboot:
147 00007CF1 CD16 int 0x16
148 00007CF3 CD19 int 0x19
149 found_ntldr:
150 00007CF5 268B551A mov dx,[es:di+0x1a] ; Get NTLDR start cluster in DX
151 00007CF9 52 push dx ; Save it on the stack
152 00007CFA B001 mov al,0x1 ; Read 1 cluster? Or is this one sector?
153 00007CFC BB0000 mov bx,0x0 ; ES:BX is the load address (2000:0000)
154 00007CFF E83B00 call read_cluster ; Do the read
155 00007D02 72E8 jc print_disk_error_message ; If it failed then reboot
156 00007D04 5B pop bx ; Get the start cluster of NTLDR in BX
157 00007D05 8A5624 mov dl,[bp+BootDrive] ; Get boot drive in DL
158 00007D08 BE0B7C mov si,0x7c0b
159 00007D0B 8BFC mov di,sp
160 00007D0D C746F03D7D mov word [bp-0x10],read_cluster
161 00007D12 C746F4297D mov word [bp-0xc],0x7d29
162 00007D17 8CD9 mov cx,ds
163 00007D19 894EF2 mov [bp-0xe],cx
164 00007D1C 894EF6 mov [bp-0xa],cx
165 00007D1F C606967DCB mov byte [0x7d96],0xcb
166 00007D24 EA03000020 jmp 0x2000:0x3
167 00007D29 0FB6C8 movzx cx,al
168 00007D2C 668B46F8 mov eax,[bp-0x8]
169 00007D30 6603461C add eax,[bp+HiddenSectors]
170 00007D34 668BD0 mov edx,eax
171 00007D37 66C1EA10 shr edx,0x10
172 00007D3B EB5E jmp short 0x7d9b
173 read_cluster:
174 00007D3D 0FB6C8 movzx cx,al
175 00007D40 4A dec dx
176 00007D41 4A dec dx
177 00007D42 8A460D mov al,[bp+SectsPerCluster]
178 00007D45 32E4 xor ah,ah
179 00007D47 F7E2 mul dx
180 00007D49 0346FC add ax,[bp-0x4]
181 00007D4C 1356FE adc dx,[bp-0x2]
182 00007D4F EB4A jmp short 0x7d9b
183
184 read_sectors:
185 00007D51 52 push dx
186 00007D52 50 push ax
187 00007D53 06 push es
188 00007D54 53 push bx
189 00007D55 6A01 push byte +0x1
190 00007D57 6A10 push byte +0x10
191 00007D59 91 xchg ax,cx
192 00007D5A 8B4618 mov ax,[bp+SectorsPerTrack]
193 00007D5D 96 xchg ax,si
194 00007D5E 92 xchg ax,dx
195 00007D5F 33D2 xor dx,dx
196 00007D61 F7F6 div si
197 00007D63 91 xchg ax,cx
198 00007D64 F7F6 div si
199 00007D66 42 inc dx
200 00007D67 87CA xchg cx,dx
201 00007D69 F7761A div word [bp+NumberOfHeads]
202 00007D6C 8AF2 mov dh,dl
203 00007D6E 8AE8 mov ch,al
204 00007D70 C0CC02 ror ah,0x2
205 00007D73 0ACC or cl,ah
206 00007D75 B80102 mov ax,0x201
207 00007D78 807E020E cmp byte [bp+0x2],0xe
208 00007D7C 7504 jnz 0x7d82
209 00007D7E B442 mov ah,0x42
210 00007D80 8BF4 mov si,sp
211 00007D82 8A5624 mov dl,[bp+BootDrive]
212 00007D85 CD13 int 0x13
213 00007D87 61 popa
214 00007D88 61 popa
215 00007D89 720B jc 0x7d96
216 00007D8B 40 inc ax
217 00007D8C 7501 jnz 0x7d8f
218 00007D8E 42 inc dx
219 00007D8F 035E0B add bx,[bp+BytesPerSector]
220 00007D92 49 dec cx
221 00007D93 7506 jnz 0x7d9b
222 00007D95 F8 clc
223 00007D96 C3 ret
224
225 read_one_sector:
226 00007D97 41 inc cx
227 00007D98 BB0000 mov bx,0x0
228 00007D9B 60 pusha
229 00007D9C 666A00 o32 push byte +0x0
230 00007D9F EBB0 jmp short 0x7d51
231
232
233 NTLDR db 'NTLDR '
234
235
236 NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
237 DISK_ERR db 0dh,0ah,'Disk error',0ffh
238 RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
239
240 filler times 18 db 0
241
242
243 NTLDR_offset_from_0x7d00 db 0
244 NTLDR_ERR_offset_from_0x7d00 db 0ach
245 DISK_ERR_offset_from_0x7d00 db 0bfh
246 RESTART_ERR_offset_from_0x7d00 db 0cch
247
248 dw 0
249 dw 0aa55h