biosint13.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,444 行 · 第 1/4 页

C
1,444
字号
/*++

Copyright (c)  1999 - 2003 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

    BiosInt13.c
    
Abstract:

     Routines that use BIOS to support INT 13 devices.


Revision History

--*/
#include "BiosDriver.h"                                

INTN
PrintBlkIO (
    BIOS_BLK_IO_DEV     *Dev
    );

EFI_STATUS 
BiosBlkIoReset (
    IN  EFI_BLOCK_IO        *This,
    IN  BOOLEAN             ExtendedVerification
    ); 
    
EFI_STATUS 
BiosBlkIoReadBlocks (
    IN  EFI_BLOCK_IO        *This,
    IN  UINT32              MediaId,
    IN  EFI_LBA             LBA,
    IN  UINTN               BufferSize,
    OUT VOID                *Buffer
    );   
    
EFI_STATUS
BiosBlkIoWriteBlocks (
    IN  EFI_BLOCK_IO        *This,
    IN  UINT32              MediaId,
    IN  EFI_LBA             LBA,
    IN  UINTN               BufferSize,
    OUT VOID                *Buffer
    );
    
EFI_STATUS 
BiosBlkIoFlushBlocks (
    IN  EFI_BLOCK_IO  *This
    ); 
    
STATIC UINTN
Int13GetDeviceParameters (
    IN BIOS_LEGACY_DRIVE    *Drive
    );  

STATIC UINTN
Int13Extensions(
    IN BIOS_LEGACY_DRIVE    *Drive
    );
    
STATIC UINTN                           
GetDriveParameters(
    IN  BIOS_LEGACY_DRIVE   *Drive
    );    

VOID
PrintOnDriveAccess (
    IN  EFI_BLOCK_IO        *This,
    IN  UINT32              MediaId,
    IN  EFI_LBA             LBA,
    IN  UINTN               BufferSize,
    OUT VOID                *Buffer,
    IN  CHAR16              *TypeString
    );

//
// Address packet is a buffer under 1 MB for all version EDD calls
//
extern EDD_DEVICE_ADDRESS_PACKET   *GlobalEDDBufferUnder1MB;

//
// This is a buffer for INT 13h func 48 information
//
extern BIOS_LEGACY_DRIVE           *GlobalLegacyDriverUnder1MB;

//
// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
//  0xFE00 bytes is the max transfer size supported.
//
extern VOID                        *GlobalEDD11Buffer;

//
// Global Io Functions 
//
extern EFI_DEVICE_IO_INTERFACE   *GlobalIoFncs; 

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

UINTN
BiosGetNumberOfDiskettes (
    VOID
    )
{
    UINT8   NumberOfDrives;

#ifdef SOFT_SDV
    NumberOfDrives = 0;
    return NumberOfDrives;
#endif
    //
    // Read BIOS Data Area for Info
    //
    NumberOfDrives = *(UINT8 *)0x410;
    return (UINTN)(((NumberOfDrives >> 6) & 0x03) + 1);
}

UINTN
BiosGetNumberOfHardDrives (
    VOID
    )
{
    UINTN   NumberOfDrives;
    //
    // Return the number of drives from the BIOS data area
    //
    NumberOfDrives = (*(UINT8 *)0x0475);    
    return NumberOfDrives;
}


BOOLEAN
BiosInitBlkIo (
    IN  BIOS_BLK_IO_DEV         *Dev
    )
{
    EFI_BLOCK_IO                *BlkIo;
    EFI_BLOCK_IO_MEDIA          *BlkMedia;
    BIOS_LEGACY_DRIVE           *Bios;

    BlkIo = &Dev->BlkIo;
    BlkIo->Media = &Dev->BlkMedia;
    BlkMedia = BlkIo->Media;
    Bios = &Dev->Bios;
    if (Int13GetDeviceParameters (Bios)) {
        if (Int13Extensions (Bios)) {
            BlkMedia->LastBlock = (EFI_LBA)Bios->Parameters.PhysicalSectors - 1;
            BlkMedia->BlockSize = (UINT32)Bios->Parameters.BytesPerSector;

            if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) {
              BlkMedia->RemovableMedia = TRUE;
            }

        } else {
            //
            // Legacy Interfaces
            //
            BlkMedia->BlockSize = 512;
            BlkMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
        }

        DEBUG ((D_INIT, "BlockSize = %d  LastBlock = %d\n",BlkMedia->BlockSize,BlkMedia->LastBlock));    

        BlkMedia->LogicalPartition = FALSE;
        BlkMedia->WriteCaching = FALSE;

        //
        // BugBug: Need to set this for removable media devices if they do not
        //  have media present
        //
        BlkMedia->ReadOnly = FALSE;
        BlkMedia->MediaPresent = TRUE; 
    
        BlkIo->Reset = BiosBlkIoReset;
        BlkIo->FlushBlocks = BiosBlkIoFlushBlocks;
        if (!Bios->ExtendedInt13) {
            //
            // Legacy interfaces
            //
            BlkIo->ReadBlocks = BiosReadLegacyDrive;    
            BlkIo->WriteBlocks = BiosWriteLegacyDrive;
        } else if ((Bios->EDDVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) {   
            //
            // EDD 3.0 Required for Device path, but extended reads are not required.
            //

            BlkIo->ReadBlocks = EDD30BiosReadBlocks;
            BlkIo->WriteBlocks = EDD30BiosWriteBlocks;
        } else {
            //
            // Assume EDD 1.1 - Read and Write functions. 
            //  This could be EDD 3.0 without Extensions64Bit being set.
            // If it's EDD 1.1 this will work, but the device path will not
            //  be correct. This will cause confusion to EFI OS installation.
            //  
            //  ASSERT (Bios->EDD);
            BlkIo->ReadBlocks = EDD11BiosReadBlocks;
            BlkIo->WriteBlocks = EDD11BiosWriteBlocks;
        }
    
        BlkMedia->LogicalPartition = FALSE;
        BlkMedia->WriteCaching = FALSE;

        return TRUE;
    } 
    return FALSE;
}

#if EFI_DEBUG
INTN
PrintBlkIO (
    BIOS_BLK_IO_DEV     *Dev
    )
{   
    BIOS_LEGACY_DRIVE   *Bios; 
    BOOLEAN             Valid = FALSE;
    
    Bios = &Dev->Bios;   

    Print (L"\n\n Letter %c Number %x EDD Version %x\n", Bios->Letter, Bios->Number, Bios->EDDVersion);
    Print (L" Block Size = %X\n", Dev->BlkIo.Media->BlockSize);
    if (Bios->ExtendedInt13) {
        Print (L"XINT13 ");
    }
    if (Bios->DriveLockingAndEjecting) { 
        Print (L"EJECT ");
    }
    if (Bios->EDD) {
        Print (L"EDD ");
    }
    if (Bios->Floppy) {
        Print (L"Floppy ");
    } 
    if (Bios->ParametersValid) {      
        Print (L"Valid ");            
        Valid = TRUE;
    }                     
    
    Print (L"\n");
    
    if (Valid) {
        Print (L" Sector Size %x", Bios->Parameters.BytesPerSector);
        Print (L" Size %lx", Bios->Parameters.PhysicalSectors);
        Print (L" Struct Size %x \n", Bios->Parameters.StructureSize);
    }
    return 0;
}
#endif

VOID
PrintOnDriveAccess (
    IN  EFI_BLOCK_IO        *This,
    IN  UINT32              MediaId,
    IN  EFI_LBA             LBA,
    IN  UINTN               BufferSize,
    OUT VOID                *Buffer,
    IN  CHAR16              *TypeString
    )
{
    Print (L"BlkIo %s LBA %lx MediaID %x Size %x", TypeString, LBA, MediaId, BufferSize);
}

STATIC UINTN
Int13GetDeviceParameters (
    IN BIOS_LEGACY_DRIVE    *Drive
    )      
{
    UINTN               CarryFlag;
    UINT16              Cylinder;
    IA32_RegisterSet_t  Regs;
    
    Regs.h.AH = 0x08;
    Regs.h.DL = Drive->Number;
    CarryFlag = Int86(0x13, &Regs);
    DEBUG ((D_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n",Drive->Number,CarryFlag,Regs.h.AH));    
    if (CarryFlag || Regs.h.AH != 0x00) {
        Drive->ErrorCode = Regs.h.AH;
        return FALSE;   
    }                         
    
    if (Drive->Floppy) {
        if (Regs.h.BL == 0x10) {
            Drive->ATAPI_Floppy = TRUE;
        } else {
            Drive->MaxHead = Regs.h.DH;
            Drive->MaxSector = Regs.h.CL;
            Drive->MaxCylinder = Regs.h.CH;
            if (Drive->MaxSector == 0) {
                //
                // BugBug: You can not trust the Carry flag. 
                //
                return FALSE;
            }
        }
    } else {
        Drive->MaxHead = Regs.h.DH & 0x3f;
        Cylinder = ((UINT16)Regs.h.DH & 0xc0) << 4;
        Cylinder |= ((UINT16)Regs.h.CL & 0xc0) << 2;
        Drive->MaxCylinder =  Cylinder + Regs.h.CH; 
        Drive->MaxSector = Regs.h.CL & 0x3f;
    }
    return TRUE;
}

STATIC UINTN
Int13Extensions(
    IN BIOS_LEGACY_DRIVE    *Drive
    )
{
    INTN CarryFlag;
    IA32_RegisterSet_t Regs;
    
    Regs.h.AH = 0x41;
    Regs.x.BX = 0x55aa;
    Regs.h.DL = Drive->Number;
    CarryFlag = Int86(0x13, &Regs);
    DEBUG ((D_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n",Drive->Number,CarryFlag,Regs.x.BX));    
    if (CarryFlag || Regs.x.BX != 0xaa55) {
        Drive->ExtendedInt13 = FALSE;
        Drive->DriveLockingAndEjecting = FALSE;
        Drive->EDD = FALSE;
        return(FALSE);  
    }
    Drive->EDDVersion = Regs.h.AH;
    Drive->ExtendedInt13 = (BOOLEAN)((Regs.x.CX & 0x01) == 0x01);
    Drive->DriveLockingAndEjecting = (BOOLEAN)((Regs.x.CX & 0x02) == 0x02);
    Drive->EDD = (BOOLEAN)((Regs.x.CX & 0x04) == 0x04);  
    Drive->Extensions64Bit = (BOOLEAN)(Regs.x.CX & 0x08);

    Drive->ParametersValid = (UINT8)GetDriveParameters(Drive);
    return Drive->ParametersValid;
}

STATIC UINTN                            
GetDriveParameters(
    IN  BIOS_LEGACY_DRIVE   *Drive
    )
{
    INTN CarryFlag;
    IA32_RegisterSet_t  Regs; 
    UINTN               PointerMath;
    
    Regs.h.AH = 0x48;
    Regs.h.DL = Drive->Number;

    //
    // EDD Buffer must be passed in with max buffer size as first entry in the buffer
    //
    GlobalLegacyDriverUnder1MB->Parameters.StructureSize = sizeof(EDD_DRIVE_PARAMETERS);
    Regs.x.DS = _FP_SEG (&GlobalLegacyDriverUnder1MB->Parameters);
    Regs.x.SI = _FP_OFF (&GlobalLegacyDriverUnder1MB->Parameters);
    CarryFlag = Int86(0x13, &Regs);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?