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 + -
显示快捷键?