biosint13.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,444 行 · 第 1/4 页
C
1,444 行
return EFI_WRITE_PROTECTED;
} 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;
}
Media->ReadOnly = FALSE;
TransferByteSize = NumberOfBlocks * BlockSize;
BufferSize = BufferSize - TransferByteSize;
TransferBuffer += TransferByteSize;
LBA += NumberOfBlocks;
}
return EFI_SUCCESS;
}
EFI_STATUS
BiosBlkIoFlushBlocks (
IN EFI_BLOCK_IO *This
)
{
return EFI_SUCCESS;
}
EFI_STATUS
BiosBlkIoReset (
IN EFI_BLOCK_IO *This,
IN BOOLEAN ExtendedVerification
)
{
BIOS_BLK_IO_DEV *BiosBlkIoDev;
IA32_RegisterSet_t Regs;
UINTN CarryFlag;
BiosBlkIoDev = BIOS_BLK_IO_FROM_THIS (This);
Regs.h.AH = 0x00;
Regs.h.DL = BiosBlkIoDev->Bios.Number;
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_INIT, "BiosBlkIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
if (CarryFlag) {
if (Regs.h.AL == BIOS_RESET_FAILED) {
Regs.h.AH = 0x00;
Regs.h.DL = BiosBlkIoDev->Bios.Number;
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_INIT, "BiosBlkIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
if (CarryFlag) {
BiosBlkIoDev->Bios.ErrorCode = Regs.h.AH;
return EFI_DEVICE_ERROR;
}
}
}
return EFI_SUCCESS;
}
//
//
// These functions need to double buffer all data under 1MB!
//
//
EFI_STATUS
EDD11BiosReadBlocks (
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)GlobalEDD11Buffer;
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 = _FP_SEG (TransferBuffer) << 16;
AddressPacket->SegOffset |= _FP_OFF (TransferBuffer);
AddressPacket->LBA = (UINT64)LBA;
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, "EDD11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n",BiosBlkIoDev->Bios.Number, CarryFlag, Regs.h.AH, LBA, NumberOfBlocks));
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;
CopyMem (Buffer, (VOID *)TransferBuffer, TransferByteSize);
BufferSize = BufferSize - TransferByteSize;
Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
LBA += NumberOfBlocks;
}
return EFI_SUCCESS;
}
EFI_STATUS
EDD11BiosWriteBlocks (
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)GlobalEDD11Buffer;
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 = _FP_SEG (TransferBuffer) << 16;
AddressPacket->SegOffset |= _FP_OFF (TransferBuffer);
AddressPacket->LBA = (UINT64)LBA;
Regs.h.AH = 0x43;
Regs.h.AL = 0x00; // Write Verify disable
Regs.h.DL = BiosBlkIoDev->Bios.Number;
Regs.x.SI = _FP_OFF (AddressPacket);
Regs.x.DS = _FP_SEG (AddressPacket);
TransferByteSize = NumberOfBlocks * BlockSize;
CopyMem ((VOID *)TransferBuffer, Buffer, TransferByteSize);
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_BLKIO_ULTRA, "EDD11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n",BiosBlkIoDev->Bios.Number, CarryFlag, Regs.h.AH, LBA, NumberOfBlocks));
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;
return EFI_WRITE_PROTECTED;
} 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;
}
Media->ReadOnly = FALSE;
BufferSize = BufferSize - TransferByteSize;
Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
LBA += NumberOfBlocks;
}
return EFI_SUCCESS;
}
EFI_STATUS
BiosReadLegacyDrive (
IN EFI_BLOCK_IO *This,
IN UINT32 MediaId,
IN EFI_LBA LBA,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
EFI_BLOCK_IO_MEDIA *Media;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?