biosint13.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,444 行 · 第 1/4 页
C
1,444 行
BIOS_BLK_IO_DEV *BiosBlkIoDev;
IA32_RegisterSet_t Regs;
UINTN UpperCylinder, Temp;
UINTN Cylinder, Head, Sector;
UINTN NumberOfBlocks, TransferByteSize;
UINTN ShortLba, CheckLba;
UINTN BlockSize;
BIOS_LEGACY_DRIVE *Bios;
UINTN CarryFlag;
UINTN Retry;
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);
ShortLba = (UINTN) LBA;
while (BufferSize) {
//
// Compute I/O location in Sector, Head, Cylinder format
//
Sector = (ShortLba % BiosBlkIoDev->Bios.MaxSector) + 1;
Temp = ShortLba / BiosBlkIoDev->Bios.MaxSector;
Head = Temp % (BiosBlkIoDev->Bios.MaxHead + 1);
Cylinder = Temp / (BiosBlkIoDev->Bios.MaxHead + 1);
//
// Limit transfer to this Head & Cylinder
//
NumberOfBlocks = BufferSize/BlockSize;
Temp = BiosBlkIoDev->Bios.MaxSector - Sector + 1;
NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
Retry = 3;
do {
//
// Perform the IO
//
Regs.h.AH = 2;
Regs.h.AL = (UINT8) NumberOfBlocks;
Regs.h.DL = BiosBlkIoDev->Bios.Number;
UpperCylinder = (Cylinder & 0x0f00) >> 2;
CheckLba = Cylinder*(BiosBlkIoDev->Bios.MaxHead + 1) + Head;
CheckLba = CheckLba*BiosBlkIoDev->Bios.MaxSector + Sector - 1;
DEBUG ((D_BLKIO_ULTRA, "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
ShortLba, CheckLba,
Sector, BiosBlkIoDev->Bios.MaxSector,
Head, BiosBlkIoDev->Bios.MaxHead,
Cylinder,
UpperCylinder
));
ASSERT(CheckLba == ShortLba);
Regs.h.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
Regs.h.DH = (UINT8) (Head & 0x3f);
Regs.h.CH = (UINT8) (Cylinder & 0xff);
Regs.x.BX = _FP_OFF (GlobalEDD11Buffer);
Regs.x.ES = _FP_SEG (GlobalEDD11Buffer);
DEBUG ((D_BLKIO_ULTRA, "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
Regs.h.AL,
(UINT8) (Head & 0x3f),
Regs.h.DL,
(UINT8) (Cylinder & 0xff),
(UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
_FP_OFF (GlobalEDD11Buffer),
_FP_SEG (GlobalEDD11Buffer)
));
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_BLKIO_ULTRA, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
Retry--;
} while (CarryFlag && Retry !=0 && Regs.h.AH != BIOS_DISK_CHANGED);
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 the size of the media changed we need to reset the disk geometry
//
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, GlobalEDD11Buffer, TransferByteSize);
ShortLba = ShortLba + NumberOfBlocks;
BufferSize = BufferSize - TransferByteSize;
Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
}
return EFI_SUCCESS;
}
EFI_STATUS
BiosWriteLegacyDrive (
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;
IA32_RegisterSet_t Regs;
UINTN UpperCylinder, Temp;
UINTN Cylinder, Head, Sector;
UINTN NumberOfBlocks, TransferByteSize;
UINTN ShortLba, CheckLba;
UINTN BlockSize;
BIOS_LEGACY_DRIVE *Bios;
UINTN CarryFlag;
UINTN Retry;
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);
ShortLba = (UINTN) LBA;
while(BufferSize) {
//
// Compute I/O location in Sector, Head, Cylinder format
//
Sector = (ShortLba % BiosBlkIoDev->Bios.MaxSector) + 1;
Temp = ShortLba / BiosBlkIoDev->Bios.MaxSector;
Head = Temp % (BiosBlkIoDev->Bios.MaxHead + 1);
Cylinder = Temp / (BiosBlkIoDev->Bios.MaxHead + 1);
//
// Limit transfer to this Head & Cylinder
//
NumberOfBlocks = BufferSize/BlockSize;
Temp = BiosBlkIoDev->Bios.MaxSector - Sector + 1;
NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
Retry = 3;
do {
//
// Perform the IO
//
Regs.h.AH = 3;
Regs.h.AL = (UINT8) NumberOfBlocks;
Regs.h.DL = BiosBlkIoDev->Bios.Number;
UpperCylinder = (Cylinder & 0x0f00) >> 2;
CheckLba = Cylinder*(BiosBlkIoDev->Bios.MaxHead + 1) + Head;
CheckLba = CheckLba*BiosBlkIoDev->Bios.MaxSector + Sector - 1;
DEBUG ((D_BLKIO_ULTRA, "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
ShortLba, CheckLba,
Sector, BiosBlkIoDev->Bios.MaxSector,
Head, BiosBlkIoDev->Bios.MaxHead,
Cylinder,
UpperCylinder
));
ASSERT(CheckLba == ShortLba);
Regs.h.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
Regs.h.DH = (UINT8) (Head & 0x3f);
Regs.h.CH = (UINT8) (Cylinder & 0xff);
Regs.x.BX = _FP_OFF (GlobalEDD11Buffer);
Regs.x.ES = _FP_SEG (GlobalEDD11Buffer);
TransferByteSize = NumberOfBlocks * BlockSize;
CopyMem (GlobalEDD11Buffer, Buffer, TransferByteSize);
DEBUG ((D_BLKIO_ULTRA, "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
Regs.h.AL,
(UINT8) (Head & 0x3f),
Regs.h.DL,
(UINT8) (Cylinder & 0xff),
(UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
_FP_OFF (GlobalEDD11Buffer),
_FP_SEG (GlobalEDD11Buffer)
));
CarryFlag = Int86 (0x13, &Regs);
DEBUG ((D_BLKIO_ULTRA, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n",BiosBlkIoDev->Bios.Number,CarryFlag,Regs.h.AH));
Retry--;
} while (CarryFlag && Retry !=0 && Regs.h.AH != BIOS_DISK_CHANGED);
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;
}
//
// If the size of the media changed we need to reset the disk geometry
//
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;
ShortLba = ShortLba + NumberOfBlocks;
BufferSize = BufferSize - TransferByteSize;
Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
}
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?