📄 usbmass.asm
字号:
mov eax, DWORD PTR [di+4]
xchg ah, al
rol eax, 16
xchg ah, al
mov (MassDeviceInfo PTR [bx]).dMaxLBA, eax
; Check for 1.44MB floppy drive
cmp eax, USB_144MB_FDD_MAX_LBA
jne UMRFC_Cont
; Return parameters for 144MB floppy
mov (MassDeviceInfo PTR [bx]).bHeads, USB_144MB_FDD_MAX_HEADS
mov (MassDeviceInfo PTR [bx]).bNonLBAHeads, USB_144MB_FDD_MAX_HEADS
mov (MassDeviceInfo PTR [bx]).bSectors, USB_144MB_FDD_MAX_SECTORS
mov (MassDeviceInfo PTR [bx]).bNonLBASectors, USB_144MB_FDD_MAX_SECTORS
mov (MassDeviceInfo PTR [bx]).wCylinders, USB_144MB_FDD_MAX_CYLINDERS
mov (MassDeviceInfo PTR [bx]).wNonLBACylinders, USB_144MB_FDD_MAX_CYLINDERS
mov (MassDeviceInfo PTR [bx]).bMediaType, USB_144MB_FDD_MEDIA_TYPE
UMRFC_Cont:
pop di
; Clear zero flag indicating success
or sp, sp
UMRFC_FreeExit:
pushf
; Check and free command buffer
mov bx, di
call USBMem_FreeOne
popf
UMRFC_Exit:
pop di
pop bx
pop eax
ret
USBMassReadFormatCapacity ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBMassReadSector
;
; Description: This function a sector at the LBA specified
;
; Input: SI Pointer to DeviceInfo structure
; EAX LBA to read
; DS:DI Data buffer
;
; Output: ZR If read failed
; NZ If read is successful
;
; Modified: Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBMassReadSector PROC NEAR SYSCALL
push eax
push bx
push edx
mov edx, eax
; Allocate memory for the command buffer
call USBMem_AllocOne
jz UMRS_Exit
mov bx, ax
; Set opcode to read command
mov (CommonRWVCommand PTR [bx]).OpCode, COMMON_READ_10_OPCODE
; Number of blocks (sectors to read)
mov ax, 1
xchg ah, al ; Big endian to little endian
mov (CommonRWVCommand PTR [bx]).TransferLength, ax
mov eax, edx
xchg ah, al ; Big endian to little endian
rol eax, 16
xchg ah, al
mov (CommonRWVCommand PTR [bx]).Lba, eax
xor dx, dx ; DX = 0
UMRS_RetryCommand:
; Fill the common bulk transaction structure
; Fill Command buffer address & size
mov stMassXactStruc.pCmdBuffer, bx
mov stMassXactStruc.bCmdSize, SIZE CommonRWVCommand
mov stMassXactStruc.bXferDir, BIT7 ; IN
push ds
push di
pop eax
mov stMassXactStruc.fpBuffer, eax
mov stMassXactStruc.dwLength, 200h ; 512 bytes
xor ax, ax
mov stMassXactStruc.wPreSkip, ax
mov stMassXactStruc.wPostSkip, ax
call USBMassIssueMassTransaction
or eax, eax
jnz UMRS_SuccessfulRead
; May be drive error. Try to correct from it !
; Check whether the drive is ready for read/write/verify command
; SI DeviceInfo
call USBMassCheckDeviceReady
or eax, eax
jnz UMRS_SkipNotSuccess
; Retry the command
or dl, dl
jnz UMRS_SkipNotSuccess
inc dl
jmp UMRS_RetryCommand
UMRS_SkipNotSuccess:
; Set zero flag
cmp sp, sp
jmp UMRS_FreeExit
UMRS_SuccessfulRead:
or sp, sp ; Clear zero flag
UMRS_FreeExit:
pushf
; Check and free command buffer (in BX)
call USBMem_FreeOne
popf
UMRS_Exit:
pop edx
pop bx
pop eax
ret
USBMassReadSector ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBMassUpdateCHSFromBootRecord
;
; Description: This function parses the boot record and extract the CHS
; information of the formatted media from the boot record.
; This routine checks for DOS & NTFS formats only
;
; Input: SI Pointer to DeviceInfo structure
; ECX Maximum LBA in the device
; DS:DI Boot record of the device
;
; Output: ZR If the boot record is un-recognizable and CHS info
; is not extracted
; NZ If the boot record is recognizable and CHS info
; is extracted. CHS information is updated in the
; mass device info structure
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBMassUpdateCHSFromBootRecord PROC NEAR SYSCALL
push eax
push ecx
push dx
push si
; Check for valid MSDOS/MSWIN/NTFS boot record
mov eax, DWORD PTR [di+3]
cmp eax, 'ODSM' ; MSDO..
je UMGFT_GetCHSFromBootRecord
cmp eax, 'IWSM' ; MSWI..
je UMGFT_GetCHSFromBootRecord
cmp eax, 'SFTN' ; NTFS
je UMGFT_GetCHSFromBootRecord
; Check for valid FAT,FAT16 boot records
mov BYTE PTR [di+39h], 20h
cmp DWORD PTR [di+36h], ' TAF' ; FAT
je UMGFT_GetCHSFromBootRecord
; It may be FAT32, check that too
cmp DWORD PTR [di+52h], '3TAF' ; FAT3
je UMGFT_GetCHSFromBootRecord
; Invalid boot record. Return with error.
cmp sp, sp
jmp SHORT UMUCFBR_Exit
UMGFT_GetCHSFromBootRecord:
mov si, (DeviceInfo PTR [si]).pMassInfoPtr
xor ax, ax
mov al, BYTE PTR [di+18h] ; Sectors/track
mov (MassDeviceInfo PTR [si]).bSectors, al
mov (MassDeviceInfo PTR [si]).bNonLBASectors, al
mov al, BYTE PTR [di+1Ah] ; heads
mov (MassDeviceInfo PTR [si]).bHeads, al
mov (MassDeviceInfo PTR [si]).bNonLBAHeads, al
mul (MassDeviceInfo PTR [si]).bSectors
xchg eax, ecx
push eax
pop ax
pop dx
div cx
mov (MassDeviceInfo PTR [si]).wCylinders, ax
mov (MassDeviceInfo PTR [si]).wNonLBACylinders, ax
or sp, sp
UMUCFBR_Exit:
pop si
pop dx
pop ecx
pop eax
ret
USBMassUpdateCHSFromBootRecord ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBMassGetFormatType
;
; Description: This function reads the first sector from the mass storage
; device and identifies the formatted type.
;
; Input: SI Pointer to DeviceInfo structure
; EAX Maximum LBA in the device
;
; Output: ZR If could not identify the formatted type
; NZ If formatted type is identified
; CH Emulation type
; CL Device type (Floppy, Harddisk or CDROM)
;
; Modified: ECX
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBMassGetFormatType PROC NEAR SYSCALL PUBLIC
push eax
push bx
push dx
push di
; Save CX in DX
mov dx, cx
mov ecx, eax
;; #1. Read the first sector of the device
; Set the LBA number to 0
xor eax, eax
mov di, pUSBMassConsumeBuffer
call USBMassReadSector
jz UMGFT_Exit
; Check for validity of the partition table/boot record
cmp WORD PTR [di+1FEh], 0AA55h
jne UMGFT_SkipNotSuccess
;; #2. Check whether it has valid partition table
add di, 1BEh ; Start offset of partition table
xor ax, ax
mov dx, ax
; DX Contains first valid partition table entry
UMGFT_VerifyPartitionTable:
cmp DWORD PTR [di+8], 0
jz UMGFT_CheckNextEntry
cmp DWORD PTR [di+8], ecx
ja UMGFT_InvalidPartitionTable ; FDD
inc ah
or dx, dx
jnz UMGFT_CheckNextEntry
mov dx, di
UMGFT_CheckNextEntry:
add di, 10h ; Point to next partition table entry
inc al
cmp al, 4
jb UMGFT_VerifyPartitionTable
; Valid partition table found.
;; #3. If it has valid partition table then
;; #4. Check number of entries in the partition table
;; #10. If the number of entries is not equal to 1 then assume HDD and leave
cmp ah, 1
ja UMGFT_HDDEmulation
jb UMGFT_InvalidPartitionTable
; Only one partition present, check the device size,
cmp ecx, MAX_LBA_FOR_FLOPPY_EMULATION
; if the device size is less than 530 MB assume FDD or else assume the
; emulation as HDD
ja UMGFT_HDDEmulation
mov ax, dx
;; #5. If the number of entries is 1 then
;; #6. Assume emulation as Forced FDD
; Assume emulation as Forced FDD.
mov dx, (USB_EMU_FORCED_FDD SHL 8) + USB_MASS_DEV_ARMD
;;; Assume emulation as HDD
;; mov dx, (USB_EMU_HDD_ONLY SHL 8) + USB_MASS_DEV_HDD
; Read boot sector
; Set the LBA number to boot record LBA number
mov di, pUSBMassConsumeBuffer
push di
mov di, ax
mov eax, DWORD PTR [di+8]
pop di
; Save hidden sector value
push si
mov si, (DeviceInfo PTR [si]).pMassInfoPtr
mov (MassDeviceInfo PTR [si]).bHiddenSectors, al
pop si
call USBMassReadSector
jz UMGFT_Exit
;; #7. If boot record is a valid FAT/NTFS file system
;; #8. Get CHS value from the boot record and leave
;; #9. Else Assume emulation type as HDD and leave
; DS:DI Boot record
call USBMassUpdateCHSFromBootRecord
jnz UMGFT_EmulationFound
jmp SHORT UMGFT_HDDEmulation
UMGFT_InvalidPartitionTable:
;; #11. Else
;; #12. Assume emulation type as FDD
; Assume the emulation as floppy
mov dx, (USB_EMU_FLOPPY_ONLY SHL 8) + USB_MASS_DEV_ARMD
;(USB001+)>
;Check whether UFI class device
push si
mov si, (DeviceInfo PTR [si]).pMassInfoPtr
cmp (MassDeviceInfo PTR [si]).bSubClass, SUB_CLASS_UFI
pop si
jz UMGFT_SkipPatchForUFI
;Assume force FDD emulation for non-UFI class device
mov dx, (USB_EMU_FORCED_FDD SHL 8) + USB_MASS_DEV_ARMD
UMGFT_SkipPatchForUFI:
;<(USB001+)
;; #13. If boot record is a valid FAT/NTFS file system
;; #14. Get CHS value from the boot record and leave
mov di, pUSBMassConsumeBuffer
call USBMassUpdateCHSFromBootRecord
jnz UMGFT_EmulationFound
;; #15. Else
;; #16. Check the device size
cmp ecx, MAX_LBA_FOR_FLOPPY_EMULATION
;; #17. If the device size is less than 530 MB assume FDD and leave
jb UMGFT_EmulationFound
;; #18. ELSE assume as HDD and leave
UMGFT_HDDEmulation:
; Reset hidden sector value
mov (MassDeviceInfo PTR [si]).bHiddenSectors, 0
; Assume the emulation as HDD
mov dx, (USB_EMU_HDD_ONLY SHL 8) + USB_MASS_DEV_HDD
UMGFT_EmulationFound:
mov cx, dx
; Clear the carry flag indicating success
or sp, sp ;
jmp SHORT UMGFT_Exit
UMGFT_SkipNotSuccess:
mov cx, dx ; Restore CX
; Set zero flag
cmp sp, sp
UMGFT_Exit:
pop di
pop dx
pop bx
pop eax
ret
USBMassGetFormatType ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBMassIdentifyDeviceType
;
; Description: This function identifies the type of the USB mass storage
; device attached from the INQUIRY data obtained from the drive
;
; Input: SI Pointer to DeviceInfo structure
; DI Pointer to the inquiry data (read from device)
;
; Output: Nothing
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBMassEmulationTypeTable LABEL WORD
WORD (USB_EMU_FLOPPY_ONLY SHL 8) + USB_MASS_DEV_ARMD
WORD (USB_EMU_FORCED_FDD SHL 8) + USB_MASS_DEV_ARMD
WORD (USB_EMU_HDD_ONLY SHL 8) + USB_MASS_DEV_HDD
WORD (USB_EMU_HDD_OR_FDD SHL 8) + USB_MASS_DEV_CDROM
USBMassIdentifyDeviceType PROC NEAR SYSCALL PUBLIC
push eax
push ecx
push bx
; Get MassDeviceInfo structure pointer into BX
mov bx, (DeviceInfo PTR [si]).pMassInfoPtr
; Get the emulation type setup option
mov ax, (MassDeviceInfo PTR [bx]).wEmulationOption
call check_cmos_data_far
or al, al
jz UMIDT_EmuTypeAuto
dec ax
shl ax, 1 ; Multiply by 2
add ax, OFFSET USBMassEmulationTypeTable
push bx
mov bx, ax
mov cx, WORD PTR CS:[bx]
pop bx
jmp SHORT UMIDT_DeviceTypeOver
UMIDT_EmuTypeAuto:
; Get the device type from the inquiry data
mov al, BYTE PTR [di]
; Get the sub-class type of the mass device
mov ah, (MassDeviceInfo PTR [bx]).bSubClass
; It is a removable device. Check for CDROM drive type
cmp al, 05h
jne UMIDT_CheckWithGeometry
UMIDT_SetCDROMType:
; Set the type as CDROM and emulation as HDD or FDD
mov cx, (USB_EMU_HDD_OR_FDD SHL 8) + USB_MASS_DEV_CDROM
jmp UMIDT_DeviceTypeOver
UMIDT_CheckWithGeometry:
; Assume as floppy
mov cx, (USB_EMU_FLOPPY_ONLY SHL 8) + USB_MASS_DEV_ARMD
; Device is coming up give some delay
push ax ; Sense code
mov ax, ((500 * 1000) / 15) ; 500ms delay
call USBMisc_FixedDelay
pop ax ; Sense code
; Get the block size & last LBA number
; SI Pointer to the device info structure
call USBMassCheckDeviceReady
; Check for media presence status
cmp eax, 003A02h
jne UMIDT_ProceedNormalChecking
; Check the compatibility flag for format capacity command not supported
test (DeviceInfo PTR [si]).wIncompatFlags, USB_INCMPT_FORMAT_CAPACITY_NOT_SUPPORTED
jnz UMIDT_ProceedNormalChecking
; Media not present. Try to get disk geometry from Format capacity command
call USBMassReadFormatCapacity
jmp SHORT UMIDT_DeviceTypeOver
UMIDT_ProceedNormalChecking:
or eax, eax
jnz UMIDT_DeviceTypeOver ; Assume as floppy
; Get the max LBA & block size
mov ax, (MassDeviceInfo PTR [bx]).wBlockSize
; If block size is other than 512 bytes assume emulation as CDROM
cmp ax, 200h
ja UMIDT_SetCDROMType
; Read the first sector and verify the emulation type
mov eax, (MassDeviceInfo PTR [bx]).dMaxLBA
call USBMassGetFormatType ; EAX - dMaxLBA
jnz UMIDT_DeviceTypeOver ; Device type identified
; Find the device type by size
push cx
mov cl, (20 - 9) ; 512 / (1024 * 1024)
shr eax, cl
pop cx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -