biosint13.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,444 行 · 第 1/4 页
C
1,444 行
DEBUG ((D_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n",Drive->Number,CarryFlag,Regs.h.AH));
if (CarryFlag || Regs.h.AH != 0x00) {
Drive->ErrorCode = Regs.h.AH;
SetMem(&Drive->Parameters, sizeof(Drive->Parameters), 0xaf);
return FALSE;
}
//
// We only have one buffer < 1MB, so copy into our instance data
//
CopyMem (
&Drive->Parameters,
&GlobalLegacyDriverUnder1MB->Parameters,
sizeof(Drive->Parameters)
);
if (Drive->ATAPI_Floppy) {
//
// Sense Media Type
//
Regs.h.AH = 0x20;
Regs.h.DL = Drive->Number;
CarryFlag = Int86(0x13, &Regs);
DEBUG ((D_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n",Drive->Number,CarryFlag,Regs.h.AL));
if (CarryFlag) {
//
// Media not present or unknown media present
//
if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1);
Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack;
ASSERT(Drive->MaxSector != 0);
Drive->MaxCylinder = (UINT16)Drive->Parameters.MaxCylinders - 1;
} else {
Drive->MaxHead = 0;
Drive->MaxSector = 1;
Drive->MaxCylinder = 0;
}
} else {
//
// Media Present
//
switch(Regs.h.AL) {
case 0x03 : // 720 KB
Drive->MaxHead = 1;
Drive->MaxSector = 9;
Drive->MaxCylinder = 79;
break;
case 0x04 : // 1.44MB
Drive->MaxHead = 1;
Drive->MaxSector = 18;
Drive->MaxCylinder = 79;
break;
case 0x06 : // 2.88MB
Drive->MaxHead = 1;
Drive->MaxSector = 36;
Drive->MaxCylinder = 79;
break;
case 0x0C : // 360 KB
Drive->MaxHead = 1;
Drive->MaxSector = 9;
Drive->MaxCylinder = 39;
break;
case 0x0D : // 1.2 MB
Drive->MaxHead = 1;
Drive->MaxSector = 15;
Drive->MaxCylinder = 79;
break;
case 0x0E : // Toshiba 3 mode
case 0x0F : // NEC 3 mode
case 0x10 : // Default Media
if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1);
Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack;
ASSERT(Drive->MaxSector != 0);
Drive->MaxCylinder = (UINT16)Drive->Parameters.MaxCylinders - 1;
} else {
Drive->MaxHead = 0;
Drive->MaxSector = 1;
Drive->MaxCylinder = 0;
}
break;
default : // Unknown media type.
Drive->MaxHead = 0;
Drive->MaxSector = 1;
Drive->MaxCylinder = 0;
break;
}
}
Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1);
Drive->Parameters.BytesPerSector = 512;
}
//
// This data comes from the BIOS so it may not allways be valid
// since the BIOS may reuse this buffer for future accesses
//
PointerMath = _FP_SEG(Drive->Parameters.FDPT) << 4;
PointerMath += _FP_OFF(Drive->Parameters.FDPT);
Drive->FDPTPointer = (VOID *)PointerMath;
return TRUE;
}
//
// Block IO Routines
//
EFI_STATUS
EDD30BiosReadBlocks (
IN EFI_BLOCK_IO *This,
IN UINT32 MediaId,
IN EFI_LBA LBA,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
EFI_BLOCK_IO_MEDIA *Media;
BIOS_BLK_IO_DEV *BiosBlkIoDev;
EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability
IA32_RegisterSet_t Regs;
UINT64 TransferBuffer;
UINTN NumberOfBlocks;
UINTN TransferByteSize;
UINTN BlockSize;
BIOS_LEGACY_DRIVE *Bios;
UINTN CarryFlag;
UINTN MaxTransferBlocks;
EFI_BLOCK_IO *BlkIo;
Media = This->Media;
BlockSize = Media->BlockSize;
//
//Check buffer alignment
//
if((Media->IoAlign > 1) && ((UINTN)Buffer & (UINTN)(Media->IoAlign -1 ))){
return EFI_INVALID_PARAMETER;
}
if (MediaId != Media->MediaId) {
return EFI_MEDIA_CHANGED;
}
if (LBA > Media->LastBlock) {
return EFI_INVALID_PARAMETER;
}
if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize % BlockSize != 0) {
return EFI_BAD_BUFFER_SIZE;
}
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0 ) {
return EFI_SUCCESS;
}
BiosBlkIoDev = BIOS_BLK_IO_FROM_THIS (This);
AddressPacket = GlobalEDDBufferUnder1MB;
MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
TransferBuffer = (UINT64)Buffer;
for (;BufferSize > 0;) {
NumberOfBlocks = BufferSize/BlockSize;
NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
AddressPacket->Zero = 0;
AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
AddressPacket->Zero2 = 0;
AddressPacket->SegOffset = 0xffffffff;
AddressPacket->LBA = (UINT64)LBA;
AddressPacket->TransferBuffer = TransferBuffer;
Regs.h.AH = 0x42;
Regs.h.DL = BiosBlkIoDev->Bios.Number;
Regs.x.SI = _FP_OFF (AddressPacket);
Regs.x.DS = _FP_SEG (AddressPacket);
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_BLKIO_ULTRA, "EDD30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
Media->MediaPresent = TRUE;
if (CarryFlag) {
//
// Return Error Status
//
BiosBlkIoDev->Bios.ErrorCode = Regs.h.AH;
if (BiosBlkIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
Media->MediaId++;
Bios = &BiosBlkIoDev->Bios;
if (Int13GetDeviceParameters(Bios)) {
if (Int13Extensions (Bios)) {
Media->LastBlock = (EFI_LBA)Bios->Parameters.PhysicalSectors - 1;
Media->BlockSize = (UINT32)Bios->Parameters.BytesPerSector;
} else {
//
// Legacy Interfaces
//
Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
Media->BlockSize = 512;
}
Media->ReadOnly = FALSE;
BS->HandleProtocol (BiosBlkIoDev->Handle, &BlockIoProtocol, (VOID **)&BlkIo);
BS->ReinstallProtocolInterface (BiosBlkIoDev->Handle, &BlockIoProtocol, BlkIo, BlkIo);
return EFI_MEDIA_CHANGED;
}
} else if (BiosBlkIoDev->Bios.ErrorCode == BIOS_DRIVE_TIMEOUT &&
Media->RemovableMedia) {
//
// Treat this case as NO_MEDIA
//
Media->MediaPresent = FALSE;
BS->HandleProtocol (BiosBlkIoDev->Handle, &BlockIoProtocol, (VOID **)&BlkIo);
BS->ReinstallProtocolInterface (BiosBlkIoDev->Handle, &BlockIoProtocol, BlkIo, BlkIo);
return EFI_NO_MEDIA;
}
if (Media->RemovableMedia) {
Media->MediaPresent = FALSE;
}
return EFI_DEVICE_ERROR;
}
TransferByteSize = NumberOfBlocks * BlockSize;
BufferSize = BufferSize - TransferByteSize;
TransferBuffer += TransferByteSize;
LBA += NumberOfBlocks;
}
return EFI_SUCCESS;
}
EFI_STATUS
EDD30BiosWriteBlocks (
IN EFI_BLOCK_IO *This,
IN UINT32 MediaId,
IN EFI_LBA LBA,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
EFI_BLOCK_IO_MEDIA *Media;
BIOS_BLK_IO_DEV *BiosBlkIoDev;
EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability
IA32_RegisterSet_t Regs;
UINT64 TransferBuffer;
UINTN NumberOfBlocks;
UINTN TransferByteSize;
UINTN BlockSize;
BIOS_LEGACY_DRIVE *Bios;
UINTN CarryFlag;
UINTN MaxTransferBlocks;
EFI_BLOCK_IO *BlkIo;
Media = This->Media;
BlockSize = Media->BlockSize;
//
//Check buffer alignment
//
if((Media->IoAlign > 1) && ((UINTN)Buffer & (UINTN)(Media->IoAlign -1 ))){
return EFI_INVALID_PARAMETER;
}
if (MediaId != Media->MediaId) {
return EFI_MEDIA_CHANGED;
}
if (LBA > Media->LastBlock) {
return EFI_DEVICE_ERROR;
}
if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize % BlockSize != 0) {
return EFI_BAD_BUFFER_SIZE;
}
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0 ) {
return EFI_SUCCESS;
}
BiosBlkIoDev = BIOS_BLK_IO_FROM_THIS (This);
AddressPacket = GlobalEDDBufferUnder1MB;
MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
TransferBuffer = (UINT64)Buffer;
for (;BufferSize > 0;) {
NumberOfBlocks = BufferSize/BlockSize;
NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
AddressPacket->Zero = 0;
AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
AddressPacket->Zero2 = 0;
AddressPacket->SegOffset = 0xffffffff;
AddressPacket->LBA = (UINT64)LBA;
AddressPacket->TransferBuffer = TransferBuffer;
Regs.h.AH = 0x43;
Regs.h.AL = 0x00; // Write Verify Off
Regs.h.DL = BiosBlkIoDev->Bios.Number;
Regs.x.SI = _FP_OFF (AddressPacket);
Regs.x.DS = _FP_SEG (AddressPacket);
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_BLKIO_ULTRA, "EDD30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
Media->MediaPresent = TRUE;
if (CarryFlag) {
//
// Return Error Status
//
BiosBlkIoDev->Bios.ErrorCode = Regs.h.AH;
if (BiosBlkIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
Media->MediaId++;
Bios = &BiosBlkIoDev->Bios;
if (Int13GetDeviceParameters(Bios)) {
if (Int13Extensions (Bios)) {
Media->LastBlock = (EFI_LBA)Bios->Parameters.PhysicalSectors - 1;
Media->BlockSize = (UINT32)Bios->Parameters.BytesPerSector;
} else {
//
// Legacy Interfaces
//
Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
Media->BlockSize = 512;
}
Media->ReadOnly = FALSE;
BS->HandleProtocol (BiosBlkIoDev->Handle, &BlockIoProtocol, (VOID **)&BlkIo);
BS->ReinstallProtocolInterface (BiosBlkIoDev->Handle, &BlockIoProtocol, BlkIo, BlkIo);
return EFI_MEDIA_CHANGED;
}
} else if (BiosBlkIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
Media->ReadOnly = TRUE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?