📄 bbu_fat.s
字号:
; In that case BBU assumes this sector only contains partition information
; and will attempt to read in the boot record for the first partition
; on this volume.
;
; The quick and easy way to get to the boot record for the first partition
; is to simply get the starting Logical Block Address (LBA) for the first
; partition which is the 4 bytes starting at offset 0x1C6 and read in that
; sector from the volume.
;
7 add r0, r0, #0x100 ; Add an offset into the sector
ldrh r1, [r0, #0xC6] ; Get bottom 2 bytes of starting LBA
ldrh r2, [r0, #0xC8] ; Get top 2 bytes of starting LBA
mov r2, r2, LSL #16 ; Move to the top 16 bits
orr r0, r1, r2 ; Generate the boot sector number in r0
cmp r0, #0 ; Is this sector zero?
moveq r0, #0xFF ; Yes - load error code into r0
beq %F9 ; ...and take the exit path
ldr r2, =BBU_VOL_SLBA ; Starting Logical Block Address
str r0, [r2] ; Save this value
b %B2 ; Otherwise read this sector & try again
;
; Exit path - do final calculation for cluster zero sector number
;
9 ldr r2, =BBU_VOL_SLBA ; Starting Logical Block Address
ldr r3, [r2] ; Get this value
add r1, r1, r3 ; r1 now equals sector # of cluster zero
ldr r2, =BBU_CLUSZ_SEC ; Address of Cluster Zero Sector #
str r1, [r2] ; Save this sector data
mov r0, r5 ; Return total byte count in r0
ldmfd sp!, {r1-r5, pc} ; Restore registers, return to caller
ENDFUNC
;
;*******************************************************************************
;
; *********************
; * *
; * BBU_FAT_NEXT_CLUS *
; * *
; *********************
;
; Given a cluster number, this subroutine returns the next cluster to be
; read for the current file.
;
; PARAMETER PASSING:
;
; INPUT:
;
; r0 - The current cluster number
;
; OUTPUT:
;
; r0 = The next cluster to read from.
;
;
BBU_FAT_NEXT_CLUS FUNCTION
stmfd sp!, {r1-r6, lr} ; Save registers and link on the stack
;
; First calculate the offset into the FAT where the next cluster data
; is saved. NOTE: this offset is calculated in NIBBLES.
;
ldr r1, =BBU_FAT_TYPE ; Address where FAT type is saved
ldrb r5, [r1] ; Get the FAT type
mov r1, #0 ; Set default nibble multiplier to zero
cmp r5, #32 ; FAT32?
moveq r1, #8 ; Yes - multiply by 8
cmp r5, #16 ; FAT16?
moveq r1, #4 ; Yes - multiply by 4
cmp r5, #12 ; FAT12?
moveq r1, #3 ; Yes - multiply by 3
mul r3, r0, r1 ; Calculate the NIBBLE offset into FAT
;
; Check to see if this offset is within the range of FAT data already in
; memory. If not, a new area of the FAT will have to be read in.
;
ldr r0, =BBU_FAT_OFFSET ; Buffer offset base is saved here
ldr r4, [r0] ; Get FAT offset base for current buffer
mov r0, r3, LSR #1 ; Load desired byte offset into r0
cmp r0, r4 ; Compare desired offset to base offset
bmi %F63 ; Desired offset .LT. base - update FAT
mov r2, #BBU_FAT_BUFSZ ; # of sectors used for FAT BUFFER
mov r2, r2, LSL #9 ; Multiply by 512 (sector size)
add r2, r2, r4 ; r2 = End of FAT table (by offset)
cmp r0, r2 ; Is the desired offset in memory?
bmi %F64 ; Yes - skip over the following
;
; The desired FAT entry is not in BBU's internal buffer. Read a new
; segment of the FAT into BBU's buffer.
;
63 bl BBU_LOAD_FAT ; Load the desired FAT segment
ldr r6, =BBU_FAT_OFFSET ; New FAT offset is saved here
ldr r4, [r6] ; Get a copy of it
64 ldr r2, =BBU_FAT_1 ; Start of the FAT in BBU's buffer
mov r4, r4, LSL #1 ; Generate the nibble offset into FAT
sub r3, r3, r4 ; Subtract out any offset into this FAT
cmp r5, #12 ; Is this a FAT12 structure?
bne %F65 ; No - assume FAT16 or FAT32
;
; Code continues here if the file structure is FAT12
;
mov r1, r3, LSR #1 ; Generate byte offset into FAT
ldrb r4, [r2, r1] ; Load this byte into r4
add r1, r1, #1 ; point to the next byte
ldrb r5, [r2, r1] ; Load the next byte into r5
ands r3, r3, #1 ; Check for a nibble offset
movne r4, r4, LSR #4 ; If nibble offset valid, LSR low byte
movne r5, r5, LSL #4 ; ...and LSL high byte 4 bits left
moveq r5, r5, LSL #8 ; If nibble byte not set, LSL 8 bits
andeq r5, r5, #0xF00 ; ...and only save bits 11:8
orr r0, r4, r5 ; Generate next cluster offset to use
b %F69 ; and take the exit path
;
; Code continues here if the file structure is FAT16 or FAT32
;
65 mov r1, r3, LSR #1 ; Generate byte offset into FAT
cmp r5, #16 ; Is this a FAT16 structure?
ldreqh r0, [r2, r1] ; Load the 16 bit cluster number into r0
ldrne r0, [r2, r1] ; Load the 32 bit cluster number into r0
bic r0, r0, #0xF0000000 ; Insure upper 4 bits are clear
;
69 ldmfd sp!, {r1-r6, pc} ; Restore registers, return to caller
ENDFUNC
;
;*******************************************************************************
;
; ****************
; * *
; * BBU_LOAD_FAT * Load a section of the FAT into memory
; * *
; ****************
;
;
; PARAMETER PASSING:
;
; INPUT:
;
; r0 - Byte OFFSET into FAT table to be used as the starting point for
; the load. A value of 0x0 starts the load at the first sector of
; the FAT. As currently written 4 sectors (2kB) are of the FAT are
; loaded into memory. NOTE: the code always reads in 2kB which
; means that is is possible to read past the end of the FAT if a
; high offset value is entered.
;
; OUTPUT:
;
; r0 = 0xFF If the read failed, otherwise non-useful data is returned
;
; NOTE ABOUT BBU'S FAT TABLE BUFFER:
;
; FAT tables should start on a 3 sector boundry and be a multiple of 3
; sectors in length. The reason for this is to make it easier to deal
; with FAT12 file structures which pack 2-1/3 cluster entries per 32-bit
; doubleword or 341.33 per 512 BYTE sector; hence reading in 3 sectors
; results in 1024 complete FAT12 clusters and avoids having to deal with
; buffer boundry issues. If the volume is using FAT16 or FAT32 the code
; does not have to be concerned about the buffer starting with a sector
; that is evenly divisable by 3.
;
;
BBU_LOAD_FAT FUNCTION
stmfd sp!, {r1-r5, lr} ; Save registers and link on the stack
;
; Figure out where the FAT starts by examining the data the has been saved
; from decoding the volume's boot block.
;
mov r3, r0 ; Save a copy of r0
ldr r1, =BBU_RES_SEC ; Address of reserved sector count
ldrh r2, [r1] ; FAT starts at sector offset in r2
ldr r1, =BBU_VOL_SLBA ; Address of Starting Logical Blk Addrs
ldr r5, [r1] ; Fetch this value
add r2, r2, r5 ; Sector where FAT starts is in r2
mov r1, r0, LSR #9 ; r1 = requested sector offset
ldr r5, =BBU_FAT_TYPE ; Where the FAT type is saved
ldrb r4, [r5] ; Get the FAT type
cmp r4, #12 ; is it FAT12?
bne %F9 ; No (thank goodness!) - skip some code
;
; The sector offset value in r1 should be evenly divisible by 3 in order
; to make it easier to deal with FAT12 tables. If the value is not
; divisible by 3, decrement the value until it is. This number shouldn't
; be very large so it's faster to use repetitive subtraction than to use
; BBU's divide routine.
;
cmp r1, #0 ; Is r1 =0?
beq %F9 ; Yes - skip over the following
6 mov r5, r1 ; Copy starting sector to r5
7 subs r5, r5, #3 ; Subtract 3
beq %F9 ; If result was 0, r1 is divisable by 3
bgt %B7 ; If the result was .GT. 0 sub 3 again
subs r1, r1, #1 ; Negative result, decrement r1
beq %F9 ; If result was 0, r1 is divisable by 3
b %B6 ; ...otherwise see if this divides by 3
;
; FAT16, FAT32 and FAT12 (sector offset divisable by 3) continues here
;
9 mov r4, r1, LSL #9 ; Offset (in bytes) where FAT starts
ldr r5, =BBU_FAT_OFFSET ; We will want to save a copy of this
str r4, [r5] ; Save the data here for future use.
add r4, r1, r2 ; Calculate starting sector number
ldr r5, =BBU_FAT_1 ; Address where data goes
mov r3, #BBU_FAT_BUFSZ ; Number of sectors to read
10 mov r0, r4 ; Copy sector # to r0
mov r1, r5 ; Address to be written to
bl BBU_MMC_Read ; Read from MMC
cmp r0, #0xFF ; Did the read fail?
beq %F12 ; Oooops! It did, Inform the user
subs r3, r3, #1 ; Read another sector?
beq %F14 ; No - take the exit path
add r4, r4, #1 ; Request the next sector
add r5, r5, #0x200 ; Update the address
b %B10 ; Read another sector
;
; Read failure
;
12 ldr r0, =BBU_GEN_DRF ; Read failed message
bl BBU_putstr ; Output the message
mov r0, #0xFF ; Set error return value
14 ldmfd sp!, {r1-r5, pc} ; Restore registers, return to caller
ENDFUNC
;
;*******************************************************************************
;
; ****************
; * *
; * BBU_LOAD_DIR * Load directory segment into memory
; * *
; ****************
;
;
; PARAMETER PASSING:
;
; INPUT:
;
; r0 - Starting offset into sector table generated by the BBU_SET_DIR
; subroutine. Zero means loads the start of the directory. Each
; succeding sector is an index of 4 bytes into the table.
; Typically sucessive calls to this routine would be offsets of
; four times the value of BBU_DIR_BUFSZ to work through the
; directory entries.
;
; OUTPUT:
;
; r0 = 0xFF If theree was a read failure.
; r0 = 0x00 If the end of the directory sector table was reached.
; otherwise r0 = offset to the next entry into the sector table.
;
;
BBU_LOAD_DIR FUNCTION
stmfd sp!, {r1-r5, lr} ; Save registers and link on the stack
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -