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