📄 bbu_fat.s
字号:
;*******************************************************************************
;
; COPYRIGHT (C) 2007 Marvell International Ltd. All Rights Reserved.
;
; The information in this file is furnished for informational use only,
; is subject to change without notice, and should not be construed as
; a commitment by Marvell. Marvell assumes no responsibility or liability
; for any errors or inaccuracies that may appear in this software or any
; documenation that may be provided in association with this software.
;
;*******************************************************************************
;
; bbu_FAT.s
; Subroutines to support File Allocation Tables and DOS-like directories
; Only 8.3 format file names are supported since support for long file
; names would require licensing from Microsoft.
;
;
BBU_FAT_BUFSZ EQU 6 ; Should be a multiple of 3 - (Sector count) 3K
BBU_DIR_BUFSZ EQU 8 ; Directory buffer size in sectors (4KB)
;
; NOTE FAT Buffer size should be a multiple of 3 so FAT12 entries never span
; a buffer boundry.
;
GLOBAL BBU_FAT_BOOT_SEC ; Boot sector validate / decode routine
GLOBAL BBU_DISP_DIR ; List the contents of the cur directory
GLOBAL BBU_FIND_FILE ; Locate a file in the directory
GLOBAL BBU_FAT_NEXT_CLUS ; Get the next cluster # in the file
GLOBAL BBU_READ_FILE ; Read file (given cluster number)
GLOBAL BBU_SET_DIR ; Set default directory
GLOBAL BBU_NAME_83 ; Format file/dir names in 8.3 format
;
; Global variables
;
GLOBAL BBU_FAT_TYPE ; FAT type saved here
GLOBAL BBU_SEC_CLUS ; Sectors per cluster count
EXTERN BBU_MMC_Read ; Read from the MMC
EXTERN BBU_putchr ; Output a character to the UART
EXTERN BBU_putstr ; Output an ASCII string to the UART
EXTERN BBU_crlf ; New line
EXTERN BBU_UDecToAscii ; Output a number in decimal format
EXTERN BBU_MMC_Read ; Read from MMC device
EXTERN BBU_U32Divide ; Unsigned 32-bit divide routine
EXTERN BBU_CMD_ASCII ; Command ASCII string
AREA |text|,CODE,READONLY
;
;*******************************************************************************
;
; ********************
; * *
; * BBU_FAT_BOOT_SEC * BBU FAT Boot Sector decode
; * *
; ********************
;
; Checks to make sure a valid boot sector was read in and if so, saves
; off various bits of information that will be referenced by other
; subroutines in this file.
;
; PARAMETER PASSING:
;
; INPUT:
;
; r0 - Address where boot sector data starts in memory
;
; OUTPUT:
;
; r0 = 0xFF if an invalid boot sector was detected
; r0 = size of device in bytes if no error
;
;
BBU_FAT_BOOT_SEC FUNCTION
stmfd sp!, {r1-r5, lr} ; Save registers and link on the stack
;
; First- zero out a few things
;
mov r1, #0 ; Zero out a work register
ldr r2, =BBU_VOL_SLBA ; Starting Logical Block Address
str r1, [r2] ; Zero out this value
ldr r2, =BBU_FAT_TYPE ; Address of FAT type
str r1, [r2] ; Zero out this value
;
; Read the boot block (sector) from a MMC device
;
mov r0, #0 ; Specify sector #0
2 ldr r1, =BBU_FAT_1 ; Buffer address
bl BBU_MMC_Read ; Read the boot sector
mov r5, r0 ; Copy return code to r5
cmp r0, #0xFF ; was an error detected?
beq %F9 ; Yes - take the exit path
;
; Check the code at the end of the sector for a valid boot sector ID
;
ldr r0, =BBU_FAT_1 ; Specify the buffer address
ldr r2, =0x1FE ; Offset to boot sector ID code
ldrh r1, [r0, r2] ; Fetch end of boot sector code
ldr r2, =0xAA55 ; End of boot sector ID code
cmp r1, r2 ; Do they match?
movne r5, #0xFF ; No - load error code into r5
bne %F9 ; ...and take the exit path
;
; Valid ID found - Next see if this sector contains boot code or just a
; partition table. BBU check the doubleword at offset 0x1B8 (just before
; the partition table). If this is zero, a partition table is assumed.
; If not, It's assumed all the volume information is in sector zero.
;
ldr r1, [r0, #0x1B8] ; Fetch the doubleword at offset 0x1B8
cmp r1, #0 ; Is there any code here?
beq %F7 ; No - search for a partition table
;
; If the first doubleword is not zero, BBU assumes it's boot code and that
; this sector contains information about the volume. In that case, the
; code continues below.
;
ldrb r1, [r0, #0xB] ; Get bytes/sector (low byte)
ldrb r2, [r0, #0xC] ; Get bytes/sector (high byte)
mov r2, r2, LSL #8 ; Shift left 1 byte
orr r2, r2, r1 ; r2 = bytes per sector
ldr r1, =BBU_BYTE_SEC ; Load address where this will be saved
strh r2, [r1] ; Save bytes/sector
ldrb r3, [r0, #0xD] ; Sectors per cluster
ldr r1, =BBU_SEC_CLUS ; Load address where this will be saved
strb r3, [r1] ; Save sectors/cluster
ldrh r3, [r0, #0xE] ; Reserved Sector Count
ldr r1, =BBU_RES_SEC ; Load address where this will be saved
strh r3, [r1] ; Save Reserved Sector Count
ldrb r3, [r0, #0x11] ; Max # root dir entries (low byte)
ldrb r4, [r0, #0x12] ; Max # root dir entries (high byte)
mov r4, r4, LSL #8 ; Shift left 1 byte
orr r3, r3, r4 ; Maximum # of root directory entries
ldr r1, =BBU_ROOT_DIRE ; Load address where this will be saved
strh r3, [r1] ; Save root directory entry count
mov r3, r3, LSR #4 ; LSR #4 to get # of root dir sectors
ldr r1, =BBU_ROOT_SIZE ; Number of root sectors is saved here
strh r3, [r1] ; Save the number of root sectors
ldrh r1, [r0, #0x16] ; Sectors per FAT (FAT12/FAT16)
cmp r1, #0 ; Is this zero?
ldreq r1, [r0, #0x24] ; If zero, load from here (FAT32)
ldr r4, =BBU_SEC_FAT ; Load address where this will be saved
str r1, [r4] ; Save sectors per FAT
ldrb r3, [r0, #0x13] ; Total sectors (low byte)
ldrb r4, [r0, #0x14] ; Total sectors (high byte)
mov r4, r4, LSL #8 ; Shift left 1 byte
orr r3, r3, r4 ; Total sector count
cmp r3, #0 ; Is this value zero?
ldreq r3, [r0, #0x20] ; If zero, get sector count from here
ldr r4, =BBU_TOT_SEC ; Load address where this will be saved
str r3, [r4] ; Save total sector count here
;
; Figure out if this is a FAT12, FAT16 or a FAT32 volume. This is
; determined by the count of clusters on the volume and NOTHING ELSE.
; The formulas are:
;
; CountofClusters = Data_sector_count / sectorsPerCluster
;
; where
;
; Data_sector_count = total sectors - (res_sec + FATsz*NumOfFATs + RtSEC)
;
; Currently:
;
; R0 = pointer to base of MBR
; R1 = sectors per FAT
; r2 = bytes per sector (leave this alone - it is used later)
; R3 = total sector count
;
ldrb r4, [r0, #0x10] ; Get number of FAT tables (usually 2)
mul r1, r1, r4 ; R1 = sectors taken up by FATs
ldrh r4, [r0, #0xE] ; Get reserved sector count
add r1, r1, r4 ; ...and add this to r1
ldr r5, =BBU_ROOT_SIZE ; Number of root sectors was saved here
ldrh r4, [r5] ; Fetch this value
add r5, r1, r4 ; r5 = total of non-data sectors
ldrb r1, [r0, #0xD] ; Fetch Sectors per cluster
sub r0, r3, r5 ; r0 = total # of data sectors
mul r5, r2, r3 ; r5 = total bytes on this volume/device
;
; divide total data sector count (in r0) by sectors per cluster (in r1)
; Count of clusters is then in r2
;
bl BBU_U32Divide ; Divide. R2 = Count of Clusters
;
; Volume = FAT12 if count of clusters is less than 4085
; Volume = FAT16 if count of clusters 4085 to 65524
; Volume - FAT32 if count of clusters is over 65524
;
ldr r1, =4085 ; Xover point for FAT12/FAT16
cmp r2, r1 ; Compare to count of clusters
movlt r0, #12 ; If .LT. 4085, it's FAT12
blt %F5 ; ...and exit
ldr r1, =65524 ; Xover point for FAT16/FAT32
cmp r2, r1 ; Compare count of clusters
movle r0, #16 ; 65524 orless= FAT16
movgt r0, #32 ; Over 65524 = FAT32
5 ldr r1, =BBU_FAT_TYPE ; Address of FAT type
strb r0, [r1] ; Save the FAT type here
;
; Figure out sector offset to root directory and save this for later
; reference & use.
;
ldr r4, =BBU_RES_SEC ; Address of reserved sector count
ldrh r0, [r4] ; Get reserved sector count
ldr r4, =BBU_SEC_FAT ; Sectors per FAT count
ldr r1, [r4] ; Get sectors per FAT count
mov r1, r1, LSL #1 ; Multiply by 2
add r0, r0, r1 ; r0 =sector offset to root directory
ldr r4, =BBU_VOL_SLBA ; Starting Logical Block Address
ldr r1, [r4] ; Get this value
add r0, r0, r1 ; Add to the root directory offset
ldr r1, =BBU_ROOT_SECT ; Location of root directory sector
str r0, [r1] ; Save this data
mov r0, #0 ; Set default to root dir (cluster #0)
bl BBU_SET_DIR ; Set it up
;
; Load the 1st segment of the FAT into BBU's internal buffer
;
mov r0, #0 ; Start at FAT offset zero
bl BBU_LOAD_FAT ; Load the first part of the table
;
; Calculate what the starting sector number for "cluster #0" would be
; for this volume. This value will be used to with the FAT to figure
; out what sectors to acess with reading/writing files. The data area
; really starts at cluster #2 so cluster #0 is a "virtual cluster" to
; take into account that the fist two cluster entries in the FAT are
; ignored.
;
; Currently this code only supports FAT12 and FAT16.
;
ldr r2, =BBU_RES_SEC ; Address of reserved sector count
ldrh r1, [r2] ; Get reserved sector count
ldr r2, =BBU_SEC_FAT ; Address of sectors/FAT count
ldr r3, [r2] ; Get sectors per FAT
mov r3, r3, LSL #1 ; Multiply by 2
add r1, r1, r3 ; R1 = reserved sectors + FAT sectors
ldr r2, =BBU_ROOT_SIZE ; Number of root sectors is saved here
ldrh r3, [r2] ; r1 = Size of root dir in sectors
add r1, r1, r3 ; r1 points to sector that starts data
ldr r2, =BBU_SEC_CLUS ; Address where sectors/cluster is kept
ldrb r3, [r2] ; Fetch this value
mov r3, r3, LSL #1 ; Multiply by 2
sub r1, r1, r3 ; r1 = sector offset of cluster zero
b %F9 ; ...and exit
;
; BBU branches here if the first doubleword of master boot record is zero.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -