2 ; BOOT_DRIVE, si and bp must be set up by the code using this driver.
3 ; (Specifically, si must be a pointer to the partition's partition
4 ; table entry and bp must be a pointer to the BPB.)
5 ; Before reading any cluster chains, callers must call get_1st_data_sec
6 ; and must be careful not to trash ecx after calling it.
8 ; eax - start cluster number
9 ; es:di - where to load the cluster chain
10 ; NOTE: Cluster chain might be the root directory or a file.
19 ; get the first sector of the cluster to read
23 mov bl, BPB_SecPerClus
31 movzx cx, BPB_SecPerClus
35 ; increment the load offset (and segment if needed)
38 movzx ax, BPB_SecPerClus
39 mul word BPB_BytsPerSec
48 ; get FAT sector number and offset containing the next cluster number
50 mov bl, 4 ; put 4 in EBX, doing this instead of "mov ebx, 4" saves us an entire byte
52 movzx ebx, word BPB_BytsPerSec
54 movzx ebx, word BPB_RsvdSecCnt
58 ; reminder for myself: EAX is FAT sector number, (E)BX is offset into FAT sector
60 ; load the FAT sector we're looking for
65 push es ; we want to read at 0:1000, not STAGE3_SEGMENT:1000
66 push eax ; desired LBA
69 pop ebx ; pop LBA into EBX
74 ; find the cluster we're looking for
75 pop es ; restore STAGE3_SEGMENT
76 pop ebx ; pop FAT offset back into EBX for cmp
81 jl .loop ; if cluster number is lower than the defective cluster value, we're not done
82 ; TODO: perhaps check is it equal defective and error out in that case?
93 ; es:di - where to load the sector(s)
94 ; ebx - start LBA address
95 ; cx - how many sectors to read
118 ; ds:si - pointer to partition table entry
119 ; RETURN: ecx - first data sector
123 movzx ax, BPB_NumFats
124 mul dword BPB_FatSz32 ; space occupied by all FATs
125 movzx ebx, word BPB_RsvdSecCnt
126 add eax, ebx ; space occupied by the reserved area
127 add eax, [si] ; space before the partition
133 read_error: db "Read error", 0