Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
26 KiB

  1. Page ,132
  2. TITLE BOOT SECTOR 1 OF TRACK 0 - BOOT LOADER
  3. ;/*
  4. ; * Microsoft Confidential
  5. ; * Copyright (C) Microsoft Corporation 1991
  6. ; * All Rights Reserved.
  7. ; */
  8. ; Rev 1.0 ChrisP, AaronR and others. 2.0 format boot
  9. ;
  10. ; Rev 3.0 MarkZ PC/AT enhancements
  11. ; 2.50 in label
  12. ; Rev 3.1 MarkZ 3.1 in label due to vagaries of SYSing to IBM drive D's
  13. ; This resulted in the BPB being off by 1. So we now trust
  14. ; 2.0 and 3.1 boot sectors and disbelieve 3.0.
  15. ;
  16. ; Rev 3.2 LeeAc Modify layout of extended BPB for >32M support
  17. ; Move PHYDRV to 3rd byte from end of sector
  18. ; so that it won't have to be moved again
  19. ; FORMAT and SYS count on PHYDRV being in a known location
  20. ;
  21. ; Rev 3.3 D.C.L. Changed Sec 9 EOT field from 15 to 18. May 29, 1986.
  22. ;
  23. ; Rev 3.31 MarkT The COUNT value has a bogus check (JBE????) to determine
  24. ; if we've loaded in all the sectors of IBMBIO. This will
  25. ; cause too big of a load if the sectors per track is high
  26. ; enough, causing either a stack overflow or the boot code
  27. ; to be overwritten.
  28. ;
  29. ; Rev 4.00 J. K. For DOS 4.00 Modified to handle the extended BPB, and
  30. ; 32 bit sector number calculation to enable the primary
  31. ; partition be started beyond 32 MB boundary.
  32. ;
  33. ; Rev 7.0 JeffPar Loads WINBOOT.SYS from anywhere in the root of the boot
  34. ; drive. WINBOOT.SYS must be an EXE with exactly 1 sector
  35. ; of header information, followed by a series of binary
  36. ; images imbedded in the EXE, as follows:
  37. ;
  38. ; 1. WINLOAD module (ORGed at 200h, loaded at 70:200h)
  39. ; 2. IO.SYS module
  40. ; 3. MSDOS.SYS module
  41. ;
  42. ; The WINLOAD module should fit within WINLOAD_SIZE sectors,
  43. ; which includes 1 sector for the EXE header, so the code
  44. ; and data for the WINLOAD bootstrap should fit in 3 sectors.
  45. ;
  46. ; Rev 7.1 ARR Multi sector version of boot record for booting off 32-bit
  47. ; BigFAT media.
  48. ;
  49. ; The ROM in the IBM PC starts the boot process by performing a hardware
  50. ; initialization and a verification of all external devices. If all goes
  51. ; well, it will then load from the boot drive the sector from track 0, head 0,
  52. ; sector 1. This sector is placed at physical address 07C00h. The initial
  53. ; registers are presumably set up as follows: CS=DS=ES=SS=0, IP=7C00h, and
  54. ; SP=0400h. But all we rely on is the BIOS being loaded at linear 07C00h.
  55. ;
  56. ; If WINBOOT.SYS is not found, an error message is displayed and the user is
  57. ; prompted to insert another disk. If there is a disk error during the
  58. ; process, a message is displayed and things are halted.
  59. ;
  60. ; At the beginning of the boot sector, there is a table which describes the
  61. ; MSDOS structure of the media. This is equivalent to the BPB with some
  62. ; additional information describing the physical layout of the driver (heads,
  63. ; tracks, sectors)
  64. ;
  65. ;==============================================================================
  66. ;REVISION HISTORY:
  67. ;AN000 - New for DOS Version 4.00 - J.K.
  68. ;AC000 - Changed for DOS Version 4.00 - J.K.
  69. ;AN00x - PTM number for DOS Version 4.00 - J.K.
  70. ;==============================================================================
  71. ;AN001; d52 Make the fixed positioned variable "CURHD" to be local. 7/6/87 J.K.
  72. ;AN002; d48 Change head settle at boot time. 7/7/87 J.K.
  73. ;AN003; P1820 New message SKL file 10/20/87 J.K.
  74. ;AN004; D304 New structrue of Boot record for OS2. 11/09/87 J.K.
  75. ;AN005; Changed version to 5.0 03/08/90 E.A.
  76. ;AN006; Changed to remove MSLOAD in first cluster restriction 04/23/90 J.H.
  77. ;==============================================================================
  78. .xlist
  79. include bpb.inc
  80. include bootsec.inc
  81. include dirent.inc
  82. ;include version.inc
  83. .list
  84. ; ==========================================================================
  85. ORIGIN EQU 7C00H ; Origin of bootstrap LOADER
  86. BIO_SEG EQU 2000H ; Destination segment of BIOS
  87. BIO_OFFSET EQU 0000H ; Offset of bios
  88. SECTOR_SIZE EQU 512 ; Sector size in bytes
  89. DIR_ENTRY_SIZE EQU SIZE DIR_ENTRY ; Size of directory entry in bytes
  90. ROM_DISKRD EQU 2
  91. SIZEBIGBOOTINSEC EQU 3
  92. ; ==========================================================================
  93. SEGBIOS SEGMENT AT BIO_SEG
  94. ; Define the destination segment of the BIOS, including the
  95. ; initialization label
  96. ORG BIO_OFFSET
  97. WINLOAD LABEL BYTE
  98. SEGBIOS ENDS
  99. ; ==========================================================================
  100. ; Local (on stack) Data storage between temp stack and start of
  101. ; boot sector
  102. CurrBuffFatSecL EQU -12
  103. CurrBuffFatSecH EQU -10
  104. Int13Sectors EQU -8
  105. DataSecL EQU -4
  106. DataSecH EQU -2
  107. ; ==========================================================================
  108. CODE SEGMENT
  109. ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
  110. ORG ORIGIN
  111. Public $START
  112. $START Label byte
  113. jmp short Main
  114. GotXint13:
  115. nop ; used to store xint13 flag
  116. GotXint13Offset = (offset GotXint13 - offset $START)
  117. ; ==========================================================================
  118. ; Start of BPB area of the boot record
  119. OsName DB "MSWIN"
  120. OsVersion DB "4.1" ; Windows version number
  121. BytesPerSector DW SECTOR_SIZE ; Size of a physical sector
  122. SecsPerClust DB 2 ; Sectors per allocation unit
  123. ReservedSecs DW 8 ; Number of reserved sectors
  124. NumFats DB 1 ; Number of fats
  125. NumDirEntries DW 1024 ; Number of direc entries
  126. TotalSectors DW 0 ; Number of sectors - number of hidden
  127. ; sectors (0 when 32 bit sector number)
  128. MediaByte DB 0F8H ; MediaByte byte
  129. NumFatSecs DW 0 ; Number of fat sectors (0 when 32 bit)
  130. SecPerTrack DW 17 ; Sectors per track
  131. NumHeads DW 4 ; Number of drive heads
  132. HiddenSecs DD 1 ; Number of hidden sectors
  133. BigTotalSecs DD 00200000h ; 32 bit version of number of sectors
  134. BigNumFatSecs DD 00001FE0h ; 32 bit version of number of FAT sectors
  135. ExtFlags DW 0
  136. BPBReserved1 DW 0
  137. RootStrtClus DD 0
  138. FSInfoSec dw ((FSInfoSecSig - $START) / SECTOR_SIZE)
  139. BkUpBootSec dw MBR_BOOTFAILBACKUP
  140. BPBReserved2 DD 3 DUP (0)
  141. .errnz ($-BytesPerSector) NE SIZE BIGFATBPB
  142. BootDrv DB 80h
  143. CurrentHead DB 0h ; Current Head
  144. ExtBootSig DB 41
  145. SerialNum DD 0
  146. VolumeLabel DB 'NO NAME '
  147. FatId DB 'FAT32 '
  148. .errnz ($-$START) NE SIZE BIGFATBOOTSEC
  149. ; =========================================================================
  150. ;
  151. ; First thing is to reset the stack to a better and more known
  152. ; place. The ROM may change, but we'd like to get the stack
  153. ; in the correct place.
  154. ;
  155. Main:
  156. xor CX,CX
  157. mov SS,CX ;Work in stack just below this routine
  158. mov SP,ORIGIN+CurrBuffFatSecL
  159. mov es,cx
  160. mov ds,cx ; DS = ES = SS = 0
  161. ASSUME DS:CODE,ES:CODE,SS:CODE
  162. mov BP,ORIGIN
  163. ;
  164. ; Determine the number of sectors addressable via
  165. ; conventional int13. If we can't get drive params for some reason
  166. ; then something is very wrong -- we'll try to force the caller
  167. ; to use conventional int13 by maxing out the sector count.
  168. ;
  169. mov [bp].GotXint13Offset,cl ; no xint13 yet
  170. mov dl,[bp].bgbsDriveNumber ; int13 unit number
  171. mov ah,8 ; get drive params
  172. int 13h ; call BIOS
  173. jnc @f ; no error, procede
  174. mov cx,-1 ; strange case, fake registers to force
  175. mov dh,cl ; use of standard int13 (set all vals to max)
  176. @@:
  177. .386
  178. movzx eax,dh ; eax = max head # (0-255)
  179. inc ax ; eax = heads (1-256)
  180. movzx edx,cl ; edx = sectors per track + cyl bits
  181. and dl,3fh ; edx = sectors per track (1-63)
  182. mul dx ; eax = sectors per cylinder, edx = 0
  183. xchg cl,ch
  184. shr ch,6 ; cx = max cylinder # (0-1023)
  185. inc cx ; cx = cylinders (1-1024)
  186. movzx ecx,cx ; ecx = cylinders (1-1024)
  187. mul ecx ; eax = sectors visible via int13, edx = 0
  188. mov [bp].Int13Sectors,eax ; save # sectors addressable via int13
  189. .8086
  190. ;
  191. ; The MBR (or boot ROM) only reads one boot sector. Thus the first order
  192. ; of business is to read the rest of ourself in by reading the second
  193. ; boot sector of the 2-sector boot record.
  194. ;
  195. ; The second sector in the NT case is at sector 12. This preserves
  196. ; the bootsect.dos logic and eliminates a special case for fat32.
  197. ;
  198. ReadBoot:
  199. cmp [BP].bgbsBPB.oldBPB.BPB_SectorsPerFAT,0 ; FAT32 BPB?
  200. jne short NoSysMsg ; No, invalid, messed up
  201. cmp [BP].bgbsBPB.BGBPB_FS_Version,FAT32_Curr_FS_Version
  202. ja short NoSysMsg ; boot code too old for this volume
  203. .386
  204. mov eax,dword ptr [BP].bgbsBPB.oldBPB.BPB_HiddenSectors
  205. add eax,12 ; read in the second boot sector
  206. .8086
  207. mov BX,ORIGIN + (SECTOR_SIZE * 2)
  208. mov cx,1
  209. call DoRead ; doesn't return if err
  210. jmp DirRead ; no error, continue boot in sector 2
  211. DiskError:
  212. mov al,byte ptr [MSGOFF_IOERROR]
  213. ;
  214. ; Al is the offset - 256 of the message within the boot sector.
  215. ; So we first calculate the real segment-based offset to the message
  216. ; and stick it in si so lodsb will work later.
  217. ;
  218. DisplayError:
  219. .ERRNZ ORIGIN MOD 256
  220. mov ah,(ORIGIN / 256) + 1
  221. mov si,ax
  222. DisplayError1:
  223. lodsb ; get next character
  224. test AL,AL ; end of message?
  225. jz WaitForKey ; yes
  226. cmp AL,0FFh ; end of sub-message?
  227. je DisplayWait ; yes, switch to final message now
  228. mov AH,14 ; write character & attribute
  229. mov BX,7 ; attribute (white char on black)
  230. int 10h ; print the character
  231. jmp short DisplayError1
  232. DisplayWait:
  233. mov al,byte ptr [MSGOFF_COMMON]
  234. jmp short DisplayError
  235. NoSysMsg:
  236. mov al,byte ptr [MSGOFF_NOSYS] ; point to no system file message
  237. jmp short DisplayError
  238. WaitForKey:
  239. cbw ;warning assumes al is zero!
  240. int 16h ; get character from keyboard
  241. int 19h ; Continue in loop till good disk
  242. ; =========================================================================
  243. ;
  244. ; Read disk sector(s). This routine cannot transfer more than 64K!
  245. ;
  246. ; Inputs: EAX == physical sector #
  247. ; CL == # sectors (CH == 0)
  248. ; ES:BX == transfer address
  249. ;
  250. ; Outputs: EAX next physical sector #
  251. ; CX == 0
  252. ; ES:BX -> byte after last byte of read
  253. ; Does not return if error
  254. ;
  255. ; Reads sectors, switching to extended int13 if necessary and
  256. ; available. The note below is for the conventional int13 case.
  257. ;
  258. ; Notes: Reads sectors one at a time in case they straddle a
  259. ; track boundary. Performs full 32-bit division on the
  260. ; first decomposition (of logical sector into track+sector)
  261. ; but not on the second (of track into cylinder+head),
  262. ; since (A) we don't have room for it, and (B) the results
  263. ; of that division must yield a quotient < 1024 anyway, because
  264. ; the CHS-style INT 13h interface can't deal with cylinders
  265. ; larger than that.
  266. ;
  267. ; =========================================================================
  268. DoRead:
  269. .386
  270. pushad
  271. ;
  272. ; Determine if the sector we're about to read is available via
  273. ; conventional int13.
  274. ;
  275. cmp eax,[bp].Int13Sectors ; determine if standard int13 is ok
  276. jb stdint13
  277. ;
  278. ; Need extended int13. First set up parameter packet on stack.
  279. ; Then, if we don't know whether xint13 is available for the drive yet,
  280. ; find out. If not, error out since we know we can't read the sector
  281. ; we need.
  282. ;
  283. db 66h ; hand-coded 32-bit push of 8-bit immediate
  284. push 0 ; high 32 bits of sector #
  285. push eax ; low 32 bits of sector #
  286. push es
  287. push bx ; transfer address
  288. push dword ptr 10010h ; transfer 1 sector, packet size = 16
  289. cmp byte ptr [bp].GotXint13Offset,0 ; have xint13?
  290. jnz xint13ok ; yes, do the read
  291. mov ah,41h
  292. mov bx,055aah
  293. mov dl,[bp].bgbsDriveNumber
  294. int 13h ; check availability
  295. jc xint13err ; error from int13 means no xint13
  296. cmp bx,0aa55h ; absence of sig means no xint13
  297. jne xint13err
  298. test cl,1 ; bit 0 off means no xint13
  299. jz xint13err
  300. inc byte ptr [bp].GotXint13Offset ; have xint13, remember for next time
  301. xint13ok:
  302. mov ah,42h ; extended read
  303. mov dl,[bp].bgbsDriveNumber ; dl = int13 unit #
  304. mov si,sp ; ds:si -> param packet
  305. int 13h ; perform the read
  306. db 0b0h ; HACK: avoid stc by making next
  307. ; byte part of mov al,xx instruction
  308. xint13err:
  309. stc ; this instruction MUST follow previous byte!
  310. pop eax ; throw away param packet without
  311. pop eax ; clobbering carry flag
  312. pop eax
  313. pop eax
  314. jmp short did_read
  315. stdint13:
  316. ;
  317. ; Read via conventional int13
  318. ;
  319. xor edx,edx ; edx:eax = absolute sector number
  320. movzx ecx,[bp].bgbsBPB.oldBPB.BPB_SectorsPerTrack ; ecx = sectors per track
  321. div ecx ; eax = track, edx = sector within track (0-62)
  322. inc dl ; dl = sector within track (1-63)
  323. mov cl,dl ; cl = sector within track
  324. mov edx,eax
  325. shr edx,16 ; dx:ax = track
  326. div [bp].bgbsBPB.oldBPB.BPB_Heads ; ax = cylinder (0-1023), dx = head (0-255)
  327. xchg dl,dh ; dh = head
  328. mov dl,[bp].bgbsDriveNumber ; dl = int13 unit #
  329. mov ch,al ; ch = bits 0-7 of cylinder
  330. shl ah,6
  331. or cl,ah ; bits 6-7 of cl = bits 8-9 of cylinder
  332. mov ax,201h ; read 1 sector
  333. int 13h
  334. did_read:
  335. popad
  336. jc DiskError
  337. add bx,SECTOR_SIZE ; advance transfer address
  338. inc eax ; next sector number
  339. dec cx ; loop instruction is out of range,
  340. jnz DoRead ; have to do it manually
  341. ret
  342. .8086
  343. Public WinBoot ; System boot file (11 bytes)
  344. WinBoot DB "NTLDR "
  345. ;
  346. ; Message table.
  347. ;
  348. ; We put English messages here as a placeholder only, so that in case
  349. ; anyone uses bootf32.h without patching new messages in, things will
  350. ; still be correct (in English, but at least functional).
  351. ;
  352. .errnz ($-$START) GT 1ACH
  353. ORG ORIGIN + 01ACH ; shift message to coincide with that in FAT
  354. ; this will help driver to think the MBR
  355. ; is empty when dealing with FAT32 superfloppy
  356. include msgstub.inc
  357. ;
  358. ; Now build a table with the low byte of the offset to each message.
  359. ; Code that patches the boot sector messages updates this table.
  360. ;
  361. .errnz ($-$START) GT (SECTOR_SIZE-7)
  362. ORG ORIGIN + SECTOR_SIZE - 7
  363. MSGOFF_NOSYS:
  364. db OFFSET (MSG_NOSYS - ORIGIN) - 256
  365. MSGOFF_IOERROR:
  366. db OFFSET (MSG_IOERROR - ORIGIN) - 256
  367. MSGOFF_COMMON:
  368. db OFFSET (MSG_COMMON - ORIGIN) - 256
  369. ORG ORIGIN + (SECTOR_SIZE - 4)
  370. DD BOOTSECTRAILSIG ; Boot sector signature (4 bytes)
  371. .errnz ($-$START) NE SECTOR_SIZE
  372. SecndSecStart label byte
  373. ;
  374. ; The second boot sector contains nothing but data. This sector is re-written
  375. ; by MS-DOS with a fairly high frequency due to changes made to the fsinfo
  376. ; structure. We don't want the actual boot code to get accidentally corrupted.
  377. ;
  378. FSInfoSecSig label byte
  379. .errnz ($-SecndSecStart) NE 0
  380. DD SECONDBOOTSECSIG
  381. db (SECTOR_SIZE - ($-FSInfoSecSig) - 4 - (SIZE BIGFATBOOTFSINFO)) DUP (0)
  382. .errnz ($-SecndSecStart) NE (OFFSETFSINFOFRMSECSTRT)
  383. fsinfo BIGFATBOOTFSINFO <FSINFOSIG,0FFFFFFFFh,000000002h>
  384. .errnz ($-FSInfoSecSig) NE OFFSETTRLSIG
  385. DD BOOTSECTRAILSIG ; Boot sector signature (4 bytes)
  386. .errnz ($-$START) NE (SECTOR_SIZE * 2)
  387. StrtThirdBootSector LABEL BYTE
  388. DirRead:
  389. .386
  390. movzx eax,[BP].bgbsBPB.oldBPB.BPB_NumberOfFATs ; Determine sector dir starts on (NumFats)
  391. mov ecx,dword ptr [BP].bgbsBPB.BGBPB_BigSectorsPerFat
  392. mul ecx ; EAX = (NumFatSecs)
  393. add EAX,dword ptr [BP].bgbsBPB.oldBPB.BPB_HiddenSectors ; (HiddenSecs)
  394. movzx edx,[BP].bgbsBPB.oldBPB.BPB_ReservedSectors ;(ReservedSecs)
  395. add EAX,EDX
  396. ;
  397. ; EAX = NumFats * NumFatSecs + ReservedSecs + cSecHid
  398. ; (first physical sector of cluster area)
  399. ;
  400. mov dword ptr [BP].DataSecL,EAX
  401. mov dword ptr [BP].CurrBuffFatSecL,0FFFFFFFFh
  402. DirReRead:
  403. mov eax,dword ptr [BP].bgbsBPB.BGBPB_RootDirStrtClus
  404. cmp eax,2
  405. jb NoSysMsg
  406. cmp eax,00FFFFFF8h
  407. jae NoSysMsg
  408. ; EAX is starting cluster of root directory
  409. DirCluster:
  410. push eax ; save starting cluster number
  411. sub eax,2 ; Convert to 0 based cluster #
  412. movzx EBX,[BP].bgbsBPB.oldBPB.BPB_SectorsPerCluster
  413. mov si,bx ; Sector count to SI for sector loop
  414. mul EBX ; compute logical sector in EAX
  415. add EAX,dword ptr [BP].DataSecL ; Add data start bias
  416. DirSector:
  417. mov BX,ORIGIN+(SIZEBIGBOOTINSEC*SECTOR_SIZE)
  418. mov DI,BX ; save address in DI for comparisons
  419. mov CX,1
  420. call DoRead ; doesn't return if error
  421. ; relies on return cx=0
  422. DirEntry:
  423. cmp byte ptr [di],ch ; empty, NUL directory entry?
  424. je short MissingFile ; yes, that's the end
  425. mov CL,11
  426. push SI
  427. mov si,offset WinBoot
  428. repz cmpsb ; see if the same
  429. pop SI
  430. jz short DoLoad ; if so, continue booting
  431. add DI,CX ; Finish advance to end of name field
  432. add DI,DIR_ENTRY_SIZE-11 ; Next dir entry
  433. cmp DI,BX ; exhausted this root dir sector yet?
  434. jb DirEntry ; no, check next entry
  435. dec SI ; decrement # dir sectors
  436. jnz DirSector ; More dir sectors in this cluster
  437. pop eax ; recover current root dir cluster
  438. call GetNextFatEntry
  439. jc DirCluster ; Do next Root dir cluster
  440. MissingFile:
  441. add sp,4 ; Discard EAX saved on stack
  442. jmp NoSysMsg
  443. CurrentSegment dw BIO_SEG
  444. ;
  445. ; We now load NTLDR
  446. ;
  447. ; All we have to do is multiply the file's starting cluster
  448. ; (whose directory entry is at DS:DI-11) by sectors per cluster and
  449. ; add that to the disk's starting data sector. We read ntldr into
  450. ; 2000:0, and begin execution there.
  451. ;
  452. DoLoad:
  453. add sp,4 ; Discard DX:AX saved on stack above
  454. mov si,[DI-11].DIR_FIRSTHIGH
  455. mov di,[DI-11].DIR_FIRST ; SI:DI = NTLDR starting cluster
  456. mov ax,si
  457. shl eax,16
  458. mov ax,di ; EAX = NTLDR starting cluster
  459. cmp eax,2 ; valid cluster #?
  460. jb NoSysMsg ; NO!
  461. cmp eax,00FFFFFF8h
  462. jae NoSysMsg ; NO!
  463. ReadAcluster:
  464. push eax ; save cluster number
  465. sub eax,2 ; Subtract first 2 reserved clusters
  466. movzx ecx,[BP].bgbsBPB.oldBPB.BPB_SectorsPerCluster ; ECX = Sectors per cluster (SecsPerClust)
  467. mul ecx ; EAX = logical sector #
  468. add eax,dword ptr [BP].DataSecL ; EAX = physical sector #
  469. mov bx,BIO_OFFSET
  470. push es
  471. mov es,CurrentSegment ; ES:BX = destination for read
  472. call DoRead ; read all sectors in cluster, doesn't return if error
  473. pop es
  474. pop eax ; recover current 0-based cluster#
  475. shr bx,4 ; updated offset -> paragraphs
  476. add CurrentSegment,bx ; update segment for next read
  477. call GetNextFatEntry ; get 2-based successor cluster in EAX
  478. jnc StartItUp ; if end of cluster chain reached
  479. jc ReadACluster ; keep sucking up clusters
  480. .8086
  481. ;
  482. ; NTLDR requires the following input conditions:
  483. ;
  484. ; DL = boot drive #
  485. ;
  486. StartItUp:
  487. mov DL,[BP].bgbsDriveNumber
  488. jmp FAR PTR WINLOAD ; CRANK UP THE WINDOWS NT BOOT LOADER
  489. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  490. ;
  491. ; GetNextFatEntry
  492. ;
  493. ; Given the last cluster found, this will return the next cluster
  494. ; of a chain of clusters. If the last cluster is (ffff)(f)ff8 - (ffff)(f)fff,
  495. ; then the final cluster has been loaded.
  496. ;
  497. ; INPUTS:
  498. ; EAX = CurrentCluster (0 based cluster #)
  499. ;
  500. ; OUTPUTS:
  501. ; EAX = Next cluster (2 based cluster #)
  502. ; Carry CLEAR if all done, SET if not
  503. ;
  504. ; USES:
  505. ; EAX,EBX,ECX,EDX,ESI,DI es
  506. ;
  507. GetNextFatEntry PROC NEAR
  508. ; NOTE For following... FAT32 cluster numbers are 28 bits not 32,
  509. ; so we know the following multiply (shl DX:AX by 2) will never
  510. ; overflow into carry.
  511. .386
  512. shl eax,2
  513. call GetFatSector
  514. mov EAX,dword ptr ES:[DI+BX]
  515. and EAX,0FFFFFFFh ; Mask to valid FAT32 cluster # bits
  516. cmp EAX,00FFFFFF8h ; carry CLEAR if all done, SET if not
  517. .8086
  518. ret
  519. GetNextFatEntry ENDP
  520. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  521. ;
  522. ; GetFatSector
  523. ;
  524. ; Read the corresponding FAT sector into the second boot sector
  525. ;
  526. ; INPUTS:
  527. ; EAX == offset (from FAT entry 0) of entry to find
  528. ;
  529. ; OUTPUTS:
  530. ; ES:DI+BX -> corresponding FAT entry in the FAT sector
  531. ;
  532. ; USES:
  533. ; BX,EAX,ECX,EDX,DI
  534. ;
  535. GetFatSector PROC NEAR
  536. .386
  537. mov DI,ORIGIN + SECTOR_SIZE
  538. movzx ECX,[BP].bgbsBPB.oldBPB.BPB_BytesPerSector
  539. xor edx,edx
  540. div ECX ; EAX = Sector number, (E)DX = Offset
  541. cmp EAX,dword ptr [BP].CurrBuffFatSecL ; The same fat sector?
  542. je short SetRet ; Don't need to read it again
  543. mov dword ptr [BP].CurrBuffFatSecL,EAX
  544. add EAX,dword ptr [BP].bgbsBPB.oldBPB.BPB_HiddenSectors
  545. movzx ecx,[BP].bgbsBPB.oldBPB.BPB_ReservedSectors
  546. add eax,ecx ; Point at 1st (0th) FAT
  547. movzx ebx,[BP].bgbsBPB.BGBPB_ExtFlags
  548. and bx,BGBPB_F_ACTIVEFATMSK
  549. jz short GotFatSec
  550. cmp bl,[BP].bgbsBPB.oldBPB.BPB_NumberOfFATs
  551. jae NoSysMsg
  552. push dx ; Save offset of cluster in the FAT sec
  553. mov ecx,eax ; Save FAT sector # in 0th FAT
  554. mov eax,dword ptr [BP].bgbsBPB.BGBPB_BigSectorsPerFat
  555. mul ebx ; EAX = Sector offset to active FAT
  556. ; from 0th FAT
  557. add eax,ecx
  558. pop dx
  559. GotFatSec:
  560. push dx ; Save offset of cluster in the FAT sec
  561. mov BX,DI
  562. mov CX,1
  563. call DoRead ; do the disk read, doesn't return if error
  564. pop dx
  565. SetRet:
  566. mov BX,DX ; set BX to the offset of the cluster
  567. .8086
  568. ret
  569. GetFatSector ENDP
  570. db ((SECTOR_SIZE - ($-StrtThirdBootSector)) - 4) DUP (0)
  571. .errnz ($-StrtThirdBootSector) NE OFFSETTRLSIG
  572. DD BOOTSECTRAILSIG ; Boot sector signature (4 bytes)
  573. .errnz ($-$START) NE (SECTOR_SIZE * 3)
  574. .errnz SIZEBIGBOOTINSEC NE 3
  575. $BigEnd label byte
  576. CODE ENDS
  577. END