Newer
Older
AMI-Aptio-BIOS-Reversed / CsmBlockIo / CsmBlockIo.c
@Ajax Dong Ajax Dong 2 days ago 62 KB Init
/*++

CsmBlockIo.c -- UEFI CSM Legacy Block I/O Driver
AMD64 / X64 UEFI DXE Driver
Source: HR650X BIOS (AmiModulePkg/CSM/CsmBlockIo/)

This is the CSM Compatibility Support Module's Block I/O driver. It
provides the bridge between UEFI Block I/O protocols and legacy INT 13h
disk services used by CSM booting (e.g., booting legacy OS from UEFI).

Source files referenced:
  e:\hs\AmiModulePkg\CSM\CsmBlockIo\CsmBlockIo.c
  e:\hs\AmiModulePkg\CSM\CsmBlockIo\CsmInt13.c

--*/

#include <Uefi.h>
#include <Protocol/BlockIo.h>
#include <Protocol/DiskIo.h>
#include <Protocol/LegacyBios.h>
#include <Protocol/LegacyBiosPlatform.h>
#include <Protocol/LegacyInterrupt.h>
#include <Protocol/Legacy8259.h>
#include <Protocol/LegacyRegion.h>
#include <Protocol/LegacyMbr.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DxeHobLib.h>
#include "CsmBlockIo.h"

//
// ============================================================================
// Global Data
// ============================================================================
//

//
// Protocol GUID definitions (.rdata section)
//
EFI_GUID gEfiLegacyInterruptProtocolGuid   = EFI_LEGACY_INTERRUPT_PROTOCOL_GUID;    // 0x3270
EFI_GUID gEfiLegacy8259ProtocolGuid        = EFI_LEGACY_8259_PROTOCOL_GUID;         // 0x3250
EFI_GUID gCsmBlockIoInternalGuid           = EFI_CSM_BLOCK_IO_INTERNAL_GUID;        // 0x3260
EFI_GUID gEfiBlockIoProtocolGuid           = EFI_BLOCK_IO_PROTOCOL_GUID;            // 0x3280
EFI_GUID gEfiLegacyRegionProtocolGuid      = EFI_LEGACY_REGION_PROTOCOL_GUID;       // 0x3290
EFI_GUID gEfiDiskIoProtocolGuid            = EFI_DISK_IO_PROTOCOL_GUID;             // 0x32F0
EFI_GUID gEfiLegacyBiosPlatformProtocolGuid = EFI_LEGACY_BIOS_PLATFORM_PROTOCOL_GUID; // 0x3300
EFI_GUID gEfiLegacyBiosPlatform2ProtocolGuid = EFI_LEGACY_BIOS_PLATFORM_PROTOCOL2_GUID; // 0x3310
EFI_GUID gEfiLegacyMbrProtocolGuid         = EFI_LEGACY_MBR_PROTOCOL_GUID;          // 0x32D0

//
// Protocol GUIDs installed by this driver
//
EFI_GUID gEfiDiskInfoProtocolGuid          = EFI_DISK_INFO_PROTOCOL_GUID;           // 0x32B0
EFI_GUID gEfiLegacyBiosExtProtocolGuid     = EFI_LEGACY_BIOS_EXT_PROTOCOL_GUID;    // 0x32E0
EFI_GUID gEfiLegacyBiosProtocolGuid        = EFI_LEGACY_BIOS_PROTOCOL_GUID;        // 0x32C0

//
// HOB list pointer (cached, from DxeHobLib)
//
VOID  *mHobList = NULL;     // 0x33B8

//
// Debug output driver handle (from sub_275C)
//
VOID  *mDebugOutputHandle = NULL;  // 0x33B0

//
// Run-time CMOS scratch register state (sub_2864)
//
UINT8  mCmosScratchRegister = 0;   // 0x33D8

//
// INT13 handler state save/restore
//
UINT32 mInt13SavedEflags = 0;      // 0x33DC

//
// Temporary buffer for INT13 data transfer
//
VOID   *mInt13TransferBuffer = NULL;  // 0x33E0

//
// Segment for INT13 data transfer
//
UINT16 mInt13TransferSegment = 0;     // 0x33E8
UINT16 mInt13TransferSegment2 = 0;    // 0x33F0

//
// Driver-defined table at 0x3320:
// Contains a CRC/checksum and function pointers for internal dispatch
//
typedef struct {
  UINT64    Checksum;         // +0x00: 0x46b7bfc6c8bca618
  UINT64    Reserved;         // +0x08: 0xc16ee5e21483198d
  UINT64    EntryPoint1;      // +0x10: sub_4C8 (DiskInfo handler)
  UINT64    EntryPoint2;      // +0x18: sub_6D4 (main INT13 handler entry)
  UINT64    EntryPoint3;      // +0x20: sub_FA8 (INT13 cleanup/BCV)
  UINT64    EntryPoint4;      // +0x28: 0x10 (size?)
} CSM_BLOCK_IO_DISPATCH_TABLE;

CSM_BLOCK_IO_DISPATCH_TABLE mDispatchTable = {
  0x46b7bfc6c8bca618,
  0xc16ee5e21483198d,
  (UINT64)sub_4C8,
  (UINT64)sub_6D4,
  (UINT64)sub_FA8,
  0x10
};

//
// Driver-defined table at 0x3360:
// Describes the legacy BIOS extension protocol interface
//
typedef struct {
  UINT64    DiskInfoInquiry;  // +0x00: sub_1554 (DiskInfo->Inquiry)
  UINT64    DiskInfoIdentify; // +0x08: sub_1564 (DiskInfo->Identify)
  CHAR8     LanguageCode[4];  // +0x10: "eng"
} CSM_BLOCK_IO_LEGACY_BIOS_TABLE;

CSM_BLOCK_IO_LEGACY_BIOS_TABLE mLegacyBiosExtTable = {
  (UINT64)sub_1554,
  (UINT64)sub_1564,
  "eng"
};

//
// Default BBS type value
//
UINT32 mDefaultBbsType = 0x4FF7F;   // 0x3378

//
// IPLDT handle allocation counter
//
UINT64 mIplDtHandleCounter = 0;      // 0x3380

//
// Reference count for the IPLDT allocation (sub_FA8)
//
UINT64 mIplDtRefCount = 0;           // 0x3388

//
// Dispatch table pointer (off_3330 = &mDispatchTable)
// LegacyBiosExt pointer (off_3360 = &mLegacyBiosExtTable)
//

//
// ============================================================================
// Library Helpers
// ============================================================================
//

//
// sub_2824 -- Debug assert helper
// Calls gDebugOutput->DebugAssert(FileName, LineNumber, Description)
//
VOID
EFIAPI
CsmAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  if (mDebugOutputHandle != NULL) {
    DEBUG_OUTPUT_PROTOCOL *Debug = (DEBUG_OUTPUT_PROTOCOL *)mDebugOutputHandle;
    Debug->DebugAssert (FileName, LineNumber, Description);
  }
}

//
// sub_27DC -- Debug print helper (log with format)
//
EFI_STATUS
EFIAPI
CsmDebugPrint (
  IN UINTN          ErrorLevel,
  IN CONST CHAR8    *Format,
  ...
  )
{
  VA_LIST     Marker;
  EFI_STATUS  Status;

  if (mDebugOutputHandle == NULL) {
    return EFI_NOT_FOUND;
  }

  Status = CsmCheckDebugLevel (ErrorLevel);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  VA_START (Marker, Format);
  Status = ((DEBUG_OUTPUT_PROTOCOL *)mDebugOutputHandle)->VDebugPrint (
             ErrorLevel, Format, Marker
             );
  VA_END (Marker);
  return Status;
}

//
// sub_275C -- Get debug output protocol handle
// Locates the EFI_DEBUG_OUTPUT_PROTOCOL (at 0x3240) from the HOB list
//
VOID *
GetDebugOutputHandle (
  VOID
  )
{
  UINTN   HobSize;
  VOID    *DebugHandle;

  if (mDebugOutputHandle != NULL) {
    return mDebugOutputHandle;
  }

  HobSize = gBS->CalculateHobSize (31);
  gBS->AllocateHob (HobSize);

  if (HobSize <= 16) {
    //
    // Locate debug protocol from HOB
    //
    if (EFI_ERROR (gBS->LocateProtocol (
                       &gCsmBlockIoInternalGuid,  // 0x3240
                       NULL,
                       &DebugHandle
                       ))) {
      DebugHandle = NULL;
    }
    mDebugOutputHandle = DebugHandle;
    return DebugHandle;
  }

  return NULL;
}

//
// sub_2864 -- Check CMOS scratch register for debug level
// Reads CMOS offset 0x4B, checks debug enable bit
//
UINT32
CsmCheckDebugLevel (
  IN UINTN  ErrorLevel
  )
{
  UINT8   CmosValue;

  CmosValue = IoRead8 (0x70);
  IoWrite8 (0x70, (CmosValue & 0x80) | 0x4B);
  CmosValue = IoRead8 (0x71);

  if (CmosValue > 3) {
    if (CmosValue == 0) {
      CmosValue = (MmioRead8 (0xFDAF0490) & 2) | 1;
    }
  }

  if ((UINT8)(CmosValue - 1) > 0xFD) {
    return 0;
  }

  return (CmosValue == 1) ? 0x80000004 : 0x80000006;
}

//
// sub_28B4 -- Get HOB list pointer (DxeHobLib)
//
VOID *
GetHobList (
  VOID
  )
{
  EFI_STATUS  Status;
  UINTN       Index;
  UINT8       *HobList;

  if (mHobList != NULL) {
    return mHobList;
  }

  mHobList = NULL;
  if (gST->HobList == NULL) {
    CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND);
    CsmAssert (
      "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
      54,
      "!EFI_ERROR (Status)"
      );
    return mHobList;
  }

  HobList = (UINT8 *)gST->HobList;
  for (Index = 0; Index < *(UINTN *)&gST->HobList; Index++) {
    if (CsmMatchGuid (Index, (EFI_GUID *)(HobList + 12))) {
      mHobList = *(VOID **)(HobList + 24 * Index + 16);
      break;
    }
  }

  if (mHobList == NULL) {
    CsmAssert (
      "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
      55,
      "mHobList != ((void *) 0)"
      );
  }

  return mHobList;
}

//
// sub_2B2C -- Compare GUID at HOB entry with target guid
//
BOOLEAN
CsmMatchGuid (
  IN UINTN     HobEntry,
  IN EFI_GUID  *TargetGuid
  )
{
  UINT64  V1, V2;

  V1 = CsmReverseQword ((UINT64 *)&Guid1);   // 0x32A0
  V2 = CsmReverseQword ((UINT64 *)TargetGuid);
  if (V1 != V2) {
    return FALSE;
  }
  V1 = CsmReverseQword ((UINT64 *)&Guid2);   // 0x32A8
  V2 = CsmReverseQword ((UINT64 *)((UINT8 *)TargetGuid + 8));
  return (V1 == V2);
}

//
// sub_2B9C -- Reverse 8 bytes for GUID comparison
//
UINT64
CsmReverseQword (
  IN UINT64  *Value
  )
{
  UINT64  Result;
  UINT8   *Src, *Dst;
  INTN    i;

  Src = (UINT8 *)Value;
  Dst = (UINT8 *)&Result;
  for (i = 7; i >= 0; i--) {
    Dst[7 - i] = Src[i];
  }
  return Result;
}

//
// sub_2C20 -- ZeroMemory
//
VOID
CsmZeroMem (
  IN VOID   *Buffer,
  IN UINTN  Size
  )
{
  UINT8  *Ptr;
  UINTN  i;

  Ptr = (UINT8 *)Buffer;
  for (i = 0; i < Size; i++) {
    Ptr[i] = 0;
  }
}

//
// sub_2C80 -- Memory copy (overlap-safe)
//
VOID *
CsmMemCopy (
  OUT VOID       *Destination,
  IN CONST VOID  *Source,
  IN UINTN       Length
  )
{
  BOOLEAN       OverlapReversed;
  UINTN         Count;
  UINTN         AlignDelta;
  UINTN         AlignCheck;
  UINT8         *D;
  CONST UINT8   *S;
  UINTN         i;

  D = (UINT8 *)Destination;
  S = (UINT8 *)Source;

  //
  // Handle overlapping buffers
  //
  OverlapReversed = FALSE;
  if ((UINTN)S < (UINTN)D) {
    if ((UINTN)S + Length >= (UINTN)D) {
      S = (UINT8 *)((UINTN)S + Length);
      D = (UINT8 *)((UINTN)D + Length);
      OverlapReversed = TRUE;
    }
  }

  if (Length < 8 || (UINTN)(S - D) < 8) {
    goto ByteCopy;
  }

  //
  // Aligned copy (8-byte aligned)
  //
  AlignCheck = (UINTN)S & 7;
  AlignDelta = (UINTN)D & 7;

  if (OverlapReversed) {
    S--;
    D--;
  }

  if ((AlignCheck == AlignDelta) && AlignCheck) {
    if (!OverlapReversed) {
      AlignCheck = 8 - AlignCheck;
    }
    CopyMem (D, S, AlignCheck);
    S += AlignCheck;
    D += AlignCheck;
    Length -= AlignCheck;
  }

  if (OverlapReversed) {
    D -= 7;
    S -= 7;
  }

  Count = Length >> 3;
  CopyMem (D, S, Count * 8);
  D += Count * 8;
  S += Count * 8;

  if (Length & 7) {
    if (OverlapReversed) {
      S += 2;
      D += 8;
    }
    Length = Length & 7;
    CopyMem (D, S, Length);
  }

  return Destination;

ByteCopy:
  if (OverlapReversed) {
    S--;
    D--;
  }
  CopyMem (D, S, Length);
  return Destination;
}

//
// sub_29B8 -- Get current allocation position from legacy region
// Walks a header-terminated chain of blocks starting at the
// legacy region memory buffer. Each block has 4-byte header:
//   byte0 = type (0xFF = end, 0x00 = unused)
//   byte1 = 0x7F marker
//   byte2-3 = block size (little-endian 16-bit)
// Returns the total payload size allocated so far (skip 4-byte header).
//
UINT64
CsmGetCurrentAllocation (
  IN UINT8  *Buffer
  )
{
  UINT8   *Ptr;
  UINT64  Total;
  UINTN   BlockSize;

  if (Buffer == NULL) {
    return 0;
  }

  Ptr = Buffer;
  Total = 0;

  while (TRUE) {
    //
    // Check for end-of-table or unused entry marker
    //
    if (Ptr[0] == 0x7F && Ptr[1] == 0xFF) {
      //
      // End marker found -- return total + 4 (skip header)
      //
      return Total + 4;
    }

    BlockSize = (UINTN)Ptr[2] + ((UINTN)Ptr[3] << 8);

    if (Ptr[0] == 0 || BlockSize == 0) {
      break;
    }

    Total += BlockSize;
    Ptr += 256 * (UINT64)Ptr[3] + Ptr[2];
  }

  return Total;
}

//
// sub_298C -- Allocate boot services data pool
// Wrapper for gBS->AllocatePool (EfiBootServicesData, Size, &Buffer)
//
UINT64
CsmLegacyRegionAllocate (
  IN UINTN  Size
  )
{
  UINT64  Buffer;

  Buffer = 0;
  gBS->AllocatePool (EfiBootServicesData, Size, (VOID **)&Buffer);
  return Buffer;
}

//
// sub_2AE4 -- Allocate and copy a BBS type table to boot services data pool
//
UINT64
CsmBbsTableCopy (
  IN UINT32  *BbsType
  )
{
  UINT64  Allocation;
  UINT64  TableSize;

  TableSize = CsmGetCurrentAllocation (BbsType);
  Allocation = CsmLegacyRegionAllocate (TableSize);
  CsmMemCopy ((VOID *)Allocation, BbsType, TableSize);
  return Allocation;
}

//
// sub_2A0C -- Legacy region allocation wrapper
// If pBbsType is provided, allocate and copy the BBS type table.
// If NULL, free the allocation.
//
UINT64
CsmBbsTableAllocate (
  IN UINT32  *BbsType,
  IN VOID    *OptionalCopySource
  )
{
  UINT64    Allocation;
  UINT64    Offset;
  UINT64    TableSize;

  if (BbsType == NULL) {
    if (OptionalCopySource == NULL) {
      BbsType = &mDefaultBbsType;
    }
    CsmLegacyRegionFree ((UINT64)BbsType);
    return 0;
  }

  if (OptionalCopySource != NULL) {
    Allocation = CsmGetCurrentAllocation () - 4;
  } else {
    Allocation = 0;
  }

  TableSize = (UINT64)((UINT8 *)BbsType)[2] + ((UINT64)((UINT8 *)BbsType)[3] << 8) + 4;
  Allocation = CsmLegacyRegionAllocate (Allocation + TableSize);

  Offset = Allocation;
  if ((UINT64)OptionalCopySource) {
    CsmMemCopy ((VOID *)Offset, OptionalCopySource, (UINT64)OptionalCopySource);
    Offset += (UINT64)OptionalCopySource;
  }

  CsmMemCopy (
    (VOID *)Offset,
    BbsType,
    ((UINT8 *)BbsType)[2] + ((UINT64)((UINT8 *)BbsType)[3] << 8)
    );

  *(UINT32 *)(Offset + ((UINT8 *)BbsType)[2] + ((UINT64)((UINT8 *)BbsType)[3] << 8)) = mDefaultBbsType;

  return Allocation;
}

//
// ============================================================================
// INT13 Subsystem: State Save/Restore
// ============================================================================
//

//
// sub_26F4 -- Save current interrupt state for a device
// Saves global INT13 eflags into the per-device saved-flags array,
// then replaces it with the device's current flags value.
// The saved-flags array is indexed by the device number stored at
// Private->Int13SavedFlagsIndex (context+0xF8).
//
UINT8
Int13SaveState (
  IN CSM_BLOCK_IO_PRIVATE  *Private
  )
{
  UINT8   FlagsIndex;

  FlagsIndex = Private->Int13SavedFlagsIndex;  // +0xF8
  if (FlagsIndex != 0) {
    //
    // Save current global eflags into the per-device slot
    //
    mInt13SavedEflags = Private->Int13SavedFlags[FlagsIndex];
    //
    // Replace with device's current flags
    //
    Private->Int13SavedFlags[Private->Int13SavedFlagsIndex] = Private->Int13Flags;
  }

  return FlagsIndex;
}

//
// sub_2734 -- Restore previous interrupt state for a device
// Restores the global INT13 eflags value from the per-device saved array.
//
UINT8
Int13RestoreState (
  IN CSM_BLOCK_IO_PRIVATE  *Private
  )
{
  UINT8   FlagsIndex;

  FlagsIndex = Private->Int13SavedFlagsIndex;  // +0xF8
  if (FlagsIndex != 0) {
    //
    // Restore saved eflags from the per-device slot
    //
    Private->Int13SavedFlags[FlagsIndex] = mInt13SavedEflags;
  }

  return FlagsIndex;
}

//
// ============================================================================
// INT13 Handler Functions
// ============================================================================
//

//
// sub_1AB0 -- INT13h disk I/O status check (function 0x01)
//
EFI_STATUS
Int13GetStatus (
  IN CSM_BLOCK_IO_PRIVATE  *Private
  )
{
  UINT8   Status;

  Int13SaveState (Private);
  Status = Private->DeviceStatus;  // context+0x89

  Private->Int13Function = 0;
  (*Private->Int13HandlerEntry) (Private, 0x13, &Status);

  if ((Private->Int13Flags & 1) != 0 && Status == 5) {
    Private->DeviceStatus = Private->DeviceStatus;  // reload context+0x89
    Private->Int13Function = 0;
    (*Private->Int13HandlerEntry) (Private, 0x13, &Status);
    if ((Private->Int13Flags & 1) != 0) {
      *Private->Int13ExtendedError = Status;
      return EFI_UNSUPPORTED;
    }
  }

  Int13RestoreState (Private);
  return EFI_SUCCESS;
}

//
// sub_1AAC -- INT13h error handler (stub)
//
VOID
Int13ErrorStub (
  VOID
  )
{
  // empty -- placeholder for Int13Error function pointer
}

//
// sub_1B48 -- INT13h Read Sectors (CHS mode, function 0x02)
// Used when device has CHS geometry (original IDE/ATA)
//
EFI_STATUS
Int13ReadWriteChs (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN UINT8                 Command,      // 0x02=read, 0x03=write
  IN UINT64                StartLba,
  IN UINT64                BlockCount,
  IN UINT64                BufferAddress
  )
{
  INT13_EXT_PACKET  Packet;
  UINT64            BlockSize;
  UINT64            BlocksPerTransfer;
  UINT64            RemainingBlocks;
  UINT64            Lba;
  UINT64            TransferBlocks;
  UINT64            TransferBytes;
  UINT64            CurrentBuf;

  BlockSize = Private->BlockSize;
  if (Command != Private->MediaId) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount == 0) {
    return EFI_SUCCESS;
  }
  if (StartLba > Private->MaxSector ||
      (BlockCount / BlockSize + StartLba - 1) > Private->MaxSector) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount % BlockSize != 0) {
    return EFI_BAD_BUFFER_SIZE;
  }
  if (BufferAddress == 0 ||
      (Private->Alignment > 1 && BufferAddress % Private->Alignment != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  BlocksPerTransfer = 0xFE00 / (UINT32)BlockSize;

  Int13SaveState (Private);

  Lba = StartLba;
  CurrentBuf = BufferAddress;
  RemainingBlocks = BlockCount;

  while (RemainingBlocks > 0) {
    //
    // Build INT13 CHS packet
    //
    Packet.PacketSize = 0x20;
    Packet.Reserved = 0;
    TransferBlocks = RemainingBlocks;
    if (TransferBlocks > BlocksPerTransfer) {
      TransferBlocks = BlocksPerTransfer;
    }
    Packet.BlockCount = (UINT16)TransferBlocks;
    Packet.Lba = Lba;
    Packet.BufferOffset = (UINT16)(mInt13TransferSegment & 0xF000);
    Packet.BufferSegment = (UINT16)(
      (mInt13TransferSegment2 >> 4) + Packet.BufferOffset
      );

    Private->DeviceStatus = Private->DeviceStatus;
    Private->Int13Command = 0x42;  // extended read
    Private->Int13TransferBuffer = (VOID *)(UINTN)Lba;

    (*Private->Int13HandlerEntry) (Private, 0x13, &Packet);

    if ((Private->Int13Flags & 1) != 0) {
      *Private->Int13ExtendedError = Private->Int13Command;
      if (Private->Int13Command != 6) {
        if (Private->RemovableMedia) {
          Private->MediaChanged = 0;
        }
        return EFI_UNSUPPORTED;
      }

      //
      // Disk changed -- re-detect geometry
      //
      Private->MediaId++;
      if (Int13IdentifyDevice (Private, (UINT8 *)&Private->DeviceInfo)) {
        if (Int13GetDriveParameters (Private, (UINT8 *)&Private->DeviceInfo)) {
          Private->MaxSector = Private->DeviceInfo.MaxSector;
          Private->BlockSize = Private->DeviceInfo.BytesPerSector;
        } else {
          CsmAssert ("", 804, "("")");
        }
        gBS->ReinstallProtocolInterface (
               Private->BlockIo,
               &gEfiDiskIoProtocolGuid,
               Private->DiskIo,
               Private->DiskIo
               );
        return EFI_INVALID_PARAMETER;
      }
      continue;
    }

    //
    // Copy data from transfer buffer
    //
    if (mCommand == 0x02)  // read
      CsmMemCopy ((VOID *)CuCurrentBuf, (VOID *)mmInt13TransferBuffer, TrransferBytes);
    }

    Lba += TrransferBlocks;
    CuurrentBuf += TransferBytes;
    RemainingBlocks -= TransferBytes;

    if ((Private->Int13Flags & 1) != 0) {
      break;
    }
  }

  Int13RestoreState (Private);
  return EFI_SUCCESS;
}

//
// sub_1E18 -- INT13h Extended Read (function 0x42)
// For LBA mode with extended INT13 support (EDD-1.1+)
//
EFI_STATUS
Int13ExtendedRead (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN UINT8                 Command,
  IN UINT64                StartLba,
  IN UINT64                BlockCount,
  IN UINT64                BufferAddress
  )
{
  INT13_EXT_PACKET  Packet;
  UINT64            BlockSize;
  UINT64            BlocksPerTransfer;
  UINT64            RemainingBlocks;
  UINT64            Lba;
  UINT64            TransferBlocks;
  UINT64            TransferBytes;
  UINT64            CurrentBuf;

  BlockSize = Private->BlockSize;
  if (Command != Private->MediaId) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount == 0) {
    return EFI_SUCCESS;
  }
  if (StartLba > Private->MaxSector ||
      BlockCount / BlockSize + StartLba - 1 > Private->MaxSector) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount % BlockSize != 0) {
    return EFI_BAD_BUFFER_SIZE;
  }
  if (BufferAddress == 0 ||
      (Private->Alignment > 1 && BufferAddress % Private->Alignment != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  BlocksPerTransfer = 0xFE00 / (UINT32)BlockSize;

  Int13SaveState (Private);

  Lba = StartLba;
  CuurrentBuf = BufferAddress;
  RemainingBlocks = BlockCount;

  while (RemainingBlocks > 0) {
    //
    // Build extended INT13 packet
    //
    Packet.PacketSize = 0x20;
    Packet.Reserved = 0;
    TransferBlocks = RemainingBlocks;
    if (TransferBlocks > BlocksPerTransfer) {
      TransferBlocks = BlocksPerTransfer;
    }
    Packet.BlockCount = (UINT16)TransferBlblocks;
    Packet.Lba = Lba;
    Packet.BufferOffset = (UINT16)((Int13TransferSegement & 0xF000);
    Packet.BufferSegement = (UINT16)(
      (mInt13TransferSegement2 >> 4) + Packet.BufferOffset
      );

    Private->Int13Command = 0x42;  // extended read
    Private->Int13TransferBuffer = (VOID *)(UINTN)Lba;

    //
    // First copy data into transfer buffer, then issue INT13
    //
    if (Command == 0x03) {  // write
      CsmMemCopy ((VOID *)mInt13TransferBuffer, (VOID *)CurrentBuf, TransferBytes);
    }

    (*Private->Int13HandlerEntry) (Private, 0x13, &Packet);

    Private->MediaChanged = 0;

    if ((Private->Int13Flags & 1) != 0) {
      *Private->Int13ExtendedError = Private->Int13Command;
      if (Private->Int13Command == 6) {
        //
        // Disk changed -- re-detect
        //
        Private->MediaId++;
        if (Int13IdentifyDevice (Private, (UINT8 *)&Private->DeviceInfo)) {
          if (Int13GetDriveParameters (Private, (UINT8 *)&Private->DeviceInfo)) {
            Private->MaxSector = Private->DeviceInfo.MaxSector;
            Private->BlockSize = Private->DeviceInfo.BytesPerSector;
          } else {
            CsmAssert ("", 947, "((BOOLEAN)(0==1))");
          }
          gBS->ReinstallProtocolInterface (
                 Private->BlockIo,
                 &gEfiDiskIoProtocolGuid,
                 Private->DiskIo,
                 Private->DiskIo
                 );
          return EFI_INVALID_PARAMETER;
        }
      } else if (Private->Int13Command == 3) {
        Private->MediaChanged = 1;
        return EFI_NO_MEDIA;
      }
      if (Private->RemovableMedia) {
        Private->MediaChanged = 0;
      }
      return EFI_UNSUPPORTED;
    }

    CurrentBuf += TransferBytes;
    Lba += TransferBlocks;
    RemainingBlocks -= TransferBytes;
    Private->MediaChanged = 0;
  }

  Int13RestoreState (Private);
  return EFI_SUCCESS;
}

//
// sub_2104 -- INT13h CHS read/write (traditional CHS, function 0x02/0x03)
//
EFI_STATUS
Int13ChsReadWrite (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN UINT8                 Command,
  IN UINT64                StartLba,
  IN UINT64                BlockCount,
  IN UINT64                BufferAddress
  )
{
  UINT64  BlockSize;
  UINT64  RemainingBlocks;
  UINT64  Lba;
  UINT64  TransferBlocks;
  UINT64  TransferBytes;
  UINT64  CurrentBuf;
  UINT64  Head, Cylinder, Sector;
  UINT64  SectorsPerHead;
  UINT64  HeadsPerCylinder;
  UINT64  Retry;
  UINT64  TotalSectors;
  UINT64  MaxTransfer;
  UINT64  SectorOffset, HeadOffset, CylinderOffset;

  BlockSize = Private->BlockSize;
  if (Command != Private->MediaId) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount == 0) {
    return EFI_SUCCESS;
  }
  if (StartLba > Private->MaxSector ||
      (BlockCount / BlockSize + StartLba - 1) > Private->MaxSector) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount % BlockSize != 0) {
    return EFI_BAD_BUFFER_SIZE;
  }
  if (BufferAddress == 0 ||
      (Private->Alignment > 1 && BufferAddress % Private->Alignment != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  Int13SaveState (Private);

  Lba = StartLba;
  CurrentBuf = BufferAddress;
  RemainingBlocks = BlockCount;

  while (RemainingBlocks > 0) {
    //
    // Convert LBA to CHS
    //
    SectorsPerHead = Private->Sectors + 1;
    HeadsPerCylinder = Private->Heads + 1;
    TotalSectors = SectorsPerHead * HeadsPerCylinder;

    SectorOffset = Lba % Private->Sectors;
    HeadOffset = (Lba / Private->Sectors) % (Private->Heads + 1);
    CylinderOffset = (Lba / Private->Sectors) / (Private->Heads + 1);

    MaxTransfer = Private->Sectors - SectorOffset + 1;
    TransferBlocks = RemainingBlocks / BlockSize;
    if (TransferBlocks > MaxTransfer) {
      TransferBlocks = MaxTransfer;
    }

    //
    // Retry loop (up to 3 attempts)
    //
    Retry = 3;
    do {
      Private->Int13Sector = (UINT8)(SectorOffset & 0x3F);
      Private->Int13Head = (UINT8)((HeadOffset & 0x3F) |
                           ((CylinderOffset >> 2) & 0xC0));
      Private->Int13Cylinder = (UINT16)(mInt13TransferSegment);
      Private->Int13SectorCount = (UINT8)TransferBlocks;
      Private->Int13BufferSegment = ((UINT64)mInt13TransferSegment >> 4) & 0xF000;

      (*Private->Int13HandlerEntry) (
        Private, 0x13, &Private->Int13ChsPacket
        );

      Retry--;
      if ((Private->Int13Flags & 1) == 0) {
        break;
      }
      if (Retry == 0) {
        break;
      }
    } while (Private->Int13Command != 6);

    Private->MediaChanged = 1;

    if ((Private->Int13Flags & 1) != 0) {
      *Private->Int13ExtendedError = Private->Int13Command;
      if (Private->Int13Command == 6) {
        Private->MediaId++;
        if (Int13IdentifyDevice (Private, (UINT8 *)&Private->DeviceInfo)) {
          if (Int13GetDriveParameters (Private, (UINT8 *)&Private->DeviceInfo)) {
            Private->MaxSector = Private->DeviceInfo.MaxSector;
            Private->BlockSize = Private->DeviceInfo.BytesPerSector;
          } else {
            Private->BlockSize = 512;
            Private->MaxSector = (UINT64)(
              (Private->Heads + 1) *
              (Private->Cylinders + 1) *
              Private->Sectors
              ) - 1;
          }
        }
        gBS->ReinstallProtocolInterface (
               Private->BlockIo,
               &gEfiDiskIoProtocolGuid,
               Private->DiskIo,
               Private->DiskIo
               );
        return EFI_INVALID_PARAMETER;
      }
      if (Private->RemovableMedia) {
        Private->MediaChanged = 0;
      }
      return EFI_UNSUPPORTED;
    }

    CurrentBuf += TransferBlocks * BlockSize;
    Lba += TransferBlocks;
    RemainingBlocks -= TransferBlocks * BlockSize;
    Private->MediaChanged = 0;
  }

  Int13RestoreState (Private);
  return EFI_SUCCESS;
}

//
// sub_23E8 -- INT13h Extended Write (function 0x43), Verify (0x44)
//
EFI_STATUS
Int13ExtendedWrite (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN UINT8                 Command,
  IN UINT64                StartLba,
  IN UINT64                BlockCount,
  IN UINT64                BufferAddress
  )
{
  UINT64  BlockSize;
  UINT64  RemainingBlocks;
  UINT64  Lba;
  UINT64  TransferBlocks;
  UINT64  TransferBytes;
  UINT64  CurrentBuf;
  UINT64  SectorOffset, CylinderOffset, HeadOffset;
  UINT64  SectorsPerHead;
  UINT64  HeadsPerCylinder;
  UINT64  TotalSectors;
  UINT64  MaxTransfer;
  UINT64  Retry;
  UINT64  SectorNum, CylinderHigh;

  BlockSize = Private->BlockSize;
  if (Command != Private->MediaId) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount == 0) {
    return EFI_SUCCESS;
  }
  if (StartLba > Private->MaxSector ||
      (BlockCount / BlockSize + StartLba - 1) > Private->MaxSector) {
    return EFI_INVALID_PARAMETER;
  }
  if (BlockCount % BlockSize != 0) {
    return EFI_BAD_BUFFER_SIZE;
  }
  if (BufferAddress == 0 ||
      (Private->Alignment > 1 && BufferAddress % Private->Alignment != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  Int13SaveState (Private);

  Lba = StartLba;
  CurrentBuf = BufferAddress;
  RemainingBlocks = BlockCount;

  while (RemainingBlocks > 0) {
    SectorsPerHead = Private->Sectors + 1;
    HeadsPerCylinder = Private->Heads + 1;

    SectorOffset = Lba % Private->Sectors;
    SectorNum = SectorOffset + 1;
    CylinderOffset = (Lba / Private->Sectors) / (Private->Heads + 1);
    HeadOffset = (Lba / Private->Sectors) % (Private->Heads + 1);
    CylinderHigh = CylinderOffset >> 2;

    MaxTransfer = Private->Sectors - SectorOffset;
    TransferBlocks = RemainingBlocks / BlockSize;
    if (TransferBlocks > MaxTransfer) {
      TransferBlocks = MaxTransfer;
    }

    TransferBytes = TransferBlocks * BlockSize;
    Retry = 3;

    do {
      //
      // Copy data to transfer buffer first for write
      //
      CsmMemCopy ((VOID *)mInt13TransferBuffer, (VOID *)CurrentBuf, TransferBytes);

      Private->Int13SectorCount = (UINT8)TransferBlocks;
      Private->Int13Head = (UINT8)((HeadOffset & 0x3F) |
                           (CylinderHigh & 0xC0));
      Private->Int13Sector = (UINT8)(SectorOffset & 0x3F);
      Private->Int13CylinderHigh = CylinderHigh & 0xF000;
      Private->Int13BufferSegment = (UINT16)mInt13TransferSegment;

      (*Private->Int13HandlerEntry) (
        Private, 0x13, &Private->Int13ChsPacket
        );

      Retry--;
      if ((Private->Int13Flags & 1) == 0) {
        break;
      }
      if (Retry == 0) {
        break;
      }
    } while (Private->Int13Command != 6);

    Private->MediaChanged = 0;

    if ((Private->Int13Flags & 1) != 0) {
      *Private->Int13ExtendedError = Private->Int13Command;
      if (Private->Int13Command == 6) {
        Private->MediaId++;
        if (Int13IdentifyDevice (Private, (UINT8 *)&Private->DeviceInfo)) {
          if (Int13GetDriveParameters (Private, (UINT8 *)&Private->DeviceInfo)) {
            Private->MaxSector = Private->DeviceInfo.MaxSector;
            Private->BlockSize = Private->DeviceInfo.BytesPerSector;
          } else {
            Private->BlockSize = 512;
            Private->MaxSector = (UINT64)(
              (Private->Headss + 1) *
              (Private->Cylinders + 1) *
              Private->Sectors
              ) - 1;
          }
        }
        gBS->ReinstallProtocolInterface (
               Private->BlockIo,
               &gEfiDiskIoProtocolGuid,
               Private->DiskIo,
               Private->DiskIo
               );
        return EFI_INVALID_PARAMETER;
      }
      if (Private->Int13Command != 3) {
        if (Private->RemovableMedia) {
          Private->MediaChanged = 0;
        }
        return EFI_UNSUPPORTED;
      }
      Private->MediaChanged = 1;
      return EFI_NO_MEDIA;
    }

    Lba += TransferBlocks;
    CuurrentBuf += TransferBytes;
    ReemainingBlocks -= TransferBytes;
    Private->MediaChanged = 0;
  }

  Int13RestoreState (Private);
  return EFI_SUCCESS;
}

//
// ===========================================================================
// Disk Info Protocol: Inquiry and Identify
// ============================================================================
//

//
// sub_1554 -- EFI_DISK_INFO.inquiry
//
EFI_STATUS
EFAPI
DiskInfoInquiry (
  IN EFI_DISK_INFO_PROTOCOL *This,
  IN UINTN                  *InquiryData
  )
{
  return EFI_SUCCESS;
}

//
// sub_1564 -- EFI_DISK_INFO.Identify
//
EFI_STATUS
EFIAPI
DiskInfoIdentify (
  IN EFI_DISK_INFO_PROTOCOL *This,
  IN OUT UINT32             *IdentifyData
  )
{
  return EFI_SUCCESS;
}

//
// ============================================================================
// Legacy BIOS Protocol / INT13 Dispatch
// ============================================================================
//

//
// sub_4C8 -- Legacy Disk Info handler (first entry point)
// Handles the EFI_DISK_INFO_PROTOCOL interface for identifying disk types
// and locating the appropriate legacy block I/O region.
//
EFI_STATUS
CsmDiskInfoHandler (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN EFI_HANDLE            Handle
  )
{
  EFI_STATUS          Status;
  EFI_LEGACY_REGION   *LegacyRegion;
  UINTN               RegionSize;
  UINT8               MbrBuffer[16];
  UINT8               BootSignature[2];
  UINT8               MediaType;
  UINT8               DeviceType;

  //
  // Locate the Legacy Interrupt protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiLegacyInterruptProtocolGuid,
                  NULL,
                  (VOID **)&Private->LegacyInterrupt
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Open the Block I/O protocol on this handle
  //
  Status = gBS->OpenProtocol (
                  Handle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **)&Private->BlockIo,
                  Private->Handle,
                  Handle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  gBS->CloseProtocol (
         Handle,
         &gEfiBlockIoProtocolGuid,
         Private->Handle,
         Handle
         );

  //
  // Determine if Legacy BIOS Platform protocol is available
  //
  Status = gBS->OpenProtocol (
                  Handle,
                  &gEfiLegacyBiosPlatformProtocolGuid,
                  (VOID **)&Private->LegacyBiosPlatform,
                  Private->Handle,
                  Handle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    //
    // Check for Legacy MBR
    //
    Status = gBS->OpenProtocol (
                    Handle,
                    &gEfiLegacyMbrProtocolGuid,
                    (VOID **)&Private->LegacyMbr,
                    Private->Handle,
                    Handle,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (!EFI_ERROR (Status)) {
      //
      // Read MBR and check for boot signature
      //
      LegacyRegion = Private->LegacyRegion;
      Status = LegacyRegion->Read (
                LegacyRegion,
                0LL,  // offset
                60,   // bytes
                1,    // count
                &DeviceType
                );
      if (EFI_ERROR (Status)) {
        CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
        CsmAssert (
          "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
          356,
          "!EFI_ERROR (Status)"
          );
      }

      //
      // Check device type
      //
      if (DeviceType <= 0x0D) {
        Status = gBS->LocateProtocol (
                        &gCsmBlockIoInternalGuid,
                        NULL,
                        (VOID **)&Private->Internal
                        );
        if (EFI_ERROR (Status)) {
          CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
          CsmAssert (
            "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
            359,
            "!EFI_ERROR (Status)"
            );
        }
        Status = Private->Internal->GetDeviceType (
                   Private->Internal,
                   DeviceType,
                   &DeviceType
                   );
        if (EFI_ERROR (Status)) {
          CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
          CsmAssert (
            "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
            362,
            "!EFI_ERROR (Status)"
            );
        }
      }
    }
  }

  //
  // Set BBS device type from IPLDT table
  //
  Private->BbsType = mIplDtTable[DeviceType];

  //
  // Read transfer buffer base
  //
  Private->TransferBuffer = Private->LegacyRegion->GetBase (
                              Private->LegacyRegion, 4, 0
                              );

  //
  // Set transfer buffer flags
  //
  Private->TransferBuffer = Private->LegacyRegion->SetFlags (
                              Private->LegacyRegion,
                              2,
                              Private->TransferBuffer & 0x700
                              );
  // preserve bits 8-10

  //
  // Initialize INT13 handler entry
  //
  (*(*Private->Int13HandlerTable->Init)(
    Private->Int13HandlerTable,
    Handle,
    0,
    0,
    Private->Int13Status
    );

  //
  // Get BBS device table
  //
  (*Private->BbsTable->GetTable)(
    &Private->BbsEntry,
    Private->Int13Packet
    );

  //
  // Count active BBS entries
  //
  for (Index = 0; Index < 256; Index++) {
    if (Private->BbsEntry[Index] != 0xFFFF) {
      BbsBitmap[Index] = 1;
      BbsBeforeCount++;
    }
  }

  //
  // Execute INT13 to discover drives
  //
  Status = Private->BbsTable->Execute (
             Private->BbsTable,
             Handle,
             0,
             Private->Int13Status,
             &DriveIndex,
             Private->Int13Packet,
             0,
             0
             );
  if (EFI_ERROR (Status)) {
    goto Cleanup;
  }

  //
  // Count post-INT13 BBS entries
  //
  for (Index = 0; Index < 256; Index++) {
    if (Private->BbsEntry[Index] != 0xFFFF) {
      if (!BbsBitmap[Index] && !PostCount) {
        PostCount = Index;
      }
      BbsAfterCount++;
    }
  }

  if (BbsAfterCount < BbsBeforeCount) {
    CsmAssert (
      "e:\hs\\AmiiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
      435,
      "NumberOfBbsEntriesAfterOpron >= NumberOfBbsEntriesBeforeOpron"
      );
  }

  Private->NewBbsEntryCount = BbsAfterCount - BbsBeforeCount;
  Private->BbsType = mIplDtTable[DeviceType];

  //
  // Allocate BBS entry table in legacy region
  //
  if (mIplDtHandleCounter == 0) {
    mIplDtHandleCounter = 0xFFFFF;
    Status = gBS->AllocatePool (1, 4, 16, &mIplDtHandleCounter);
    if (EFI_ERROR (Status)) {
      CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
      CsmAssert (
        "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
        635,
        "!EFI_ERROR (Status)"
        );
    }
    mIplDtHandleCounter = 0;
  }

  return EFI_SUCCESS;

Cleanup:
  //
  // Close protocols and return error
  //
  gBS->CloseProtocol (
         Handle,
         &gEfiLegacyRegionProtocolGuid,
         Private->Handle,
         Handle
         );
  gBS->CloseProtocol (
         Handle,
         &gEfiBlockIoProtocolGuid,
         Private->Handle,
         Handle
         );
  return Status;
}

//
// ============================================================================
// Entry Point
// ============================================================================
//

EFI_STATUS
EFIAPI
CsmBlockIoEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Save global protocol pointers
  //
  gImageHandle = ImageHandle;
  gST = SystemTable;
  gBS = SystemTable->BootServices;
  gRT = SystemTable->RuntimeServices;

  //
  // Initialize HOB list
  //
  GetHobList ();

  //
  // Install three protocol interfaces on the image handle:
  //   1. EFI_DISK_INFO_PROTOCOL  (0x32B0)
  //   2. EFI_LEGACY_BIOS_EXT_PROTOCOL (0x32E0)
  //   3. EFI_LEGACY_BIOS_PROTOCOL (0x32C0)
  //
  return gBS->InstallMultipleProtocolInterfaces (
           &gImageHandle,
           &gEfiDiskInfoProtocolGuid,
           &mDispatchTable,       // offf3330 - dispatch table with sub_4C8, sub_6D4, sub_FA8
           &gEfiLegacyBiosExtProtocolGuid,
           &mLegacyBiosExtTable,  // off_3360 - legacy bios ext table
           &gEfiLegacyBiosProtocolGuid,
           NULL,                   // no interface (protocol-only notification)
           NULL
           );
}

//
// ============================================================================
// sub_6D4 -- Main INT13 handler / CSM Block I/O initialization per device
// Called for each disk device that needs CSM legacy support.
// ============================================================================
//
// Parameters:
//   a1 - Private context (CSM_BLOCK_IO_PRIVATE *)
//   a2 - EFI_HANDLE for the block device
//
EFI_STATUS
CsmBlockIoInitDevice (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN EFI_HANDLE            DeviceHandle
  )
{
  EFI_STATUS          Status;
  UINT8               DeviceType;
  UINT8               DeviceIndex;
  EFI_LEGACY_REGION   *LegacyRegion;
  EFI_BLOCK_IO        *BlockIo;
  EFI_LEGACY_BIOS_PLATFORM *BiosPlatform;
  UINT8               BbsBitmap[256];
  UINT8               BbsBeforeCount;
  UINT8               BbsAfterCount;
  UINT8               BbsNewCount;

  //
  // Initialize state
  //
  CsmZeroMem (BbsBitmap, sizeof(BbsBitmap));
  BbsBeforeCount = 0;
  BbsAfterCount = 0;
  BbsNewCount = 0;
  Private->DeviceIndex = 0;
  Private->BbsType = 0;

  //
  // Locate Legacy Interrupt protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiLegacyInterruptProtocolGuid,
                  NULL,
                  (VOID **)&Private->LegacyInterrupt
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Locate Legacy 8259 protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiLegacy8259ProtocolGuid,
                  NULL,
                  (VOID **)&Private->Legacy8259
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Open Block I/O protocol on this handle
  //
  Status = gBS->OpenProtocol (
                  DeviceHandle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **)&Private->BlockIo,
                  Private->Handle,
                  DeviceHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Try Legacy Bios Platform protocol (optional)
  //
  v38 = FALSE;
  Status = gBS->OpenProtocol (
                  DeviceHandle,
                  &gEfiLegacyBiosPlatformProtocolGuid,
                  (VOID **)&Private->LegacyBiosPlatform,
                  Private->Handle,
                  DeviceHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    v38 = TRUE;
    //
    // Open for Legacy MBR too
    //
    Status = gBS->OpenProtocol (
                    DeviceHandle,
                    &gEfiLegacyMbrProtocolGuid,
                    (VOID **)&Private->LegacyMbr,
                    Private->Handle,
                    DeviceHandle,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (!EFI_ERROR (Status)) {
      //
      // Legacy MBR is available -- read device type via Legacy Region
      //
      LegacyRegion = Private->LegacyRegion;
      Status = LegacyRegion->Read (
                LegacyRegion,
                0LL,
                60,
                1,
                &DeviceType
                );
      if (EFI_ERROR (Status)) {
        CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
        CsmAssert (
          "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
          356,
          "!EFI_ERROR (Status)"
          );
      }

      if (DeviceType <= 0x0D) {
        Status = gBS->LocateProtocol (
                        &gCsmBlockIoInternalGuid,
                        NULL,
                        (VOID **)&Private->Internal
                        );
        if (EFI_ERROR (Status)) {
          CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
          CsmAssert (
            "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
            359,
            "!EFI_ERROR (Status)"
            );
        }
        Status = Private->Internal->GetDeviceType (
                   Private->Internal,
                   DeviceType,
                   &DeviceType
                   );
        if (EFI_ERROR (Status)) {
          CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
          CsmAssert (
            "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
            362,
            "!EFI_ERROR (Status)"
            );
        }
      }
    }
  }

  Private->BbsType = mIplDtTable[DeviceType];

  //
  // Get transfer buffer base from legacy region (offset 4)
  //
  Private->TransferBuffer = Private->LegacyRegion->GetBase (
                              Private->LegacyRegion, 4, 0
                              );

  //
  // Configure transfer buffer flags (mask 0x700)
  //
  Private->TransferBuffer = Private->LegacyRegion->SetFlags (
                              Private->LegacyRegion,
                              2,
                              Private->TransferBuffer & 0x700
                              );

  //
  // Call BIOS INT13 handler entry
  //
  Status = Private->BbsTable->Init (
             Private->BbsTable,
             DeviceHandle,
             0,
             0,
             Private->Int13Status
             );
  if (EFI_ERROR (Status)) {
    goto Cleanup;
  }

  //
  // Get BBS table
  //
  Status = Private->BbsTable->GetTable (
             &Private->BbsEntry,
             Private->Int13Packet
             );
  if (EFI_ERROR (Status)) {
    CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    CsmAssert (
      "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
      397,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // Count current BBS entries
  //
  for (Index = 0; Index < 256; Index++) {
    if (Private->BbsEntry[Index] != 0xFFFF) {
      BbsBitmap[Index] = 1;
      BbsBeforeCount++;
    }
  }

  //
  // Execute INT13 to discover drives
  //
  Status = Private->BbsTable->Execute (
             Private->BbsTable,
             DeviceHandle,
             0,
             Private->Int13Status,
             &DeviceIndex,
             Private->Int13Packet,
             0,
             0
             );
  if (EFI_ERROR (Status)) {
    goto Cleanup;
  }

  //
  // Count post-INT13 BBS entries
  //
  for (Index = 0; Index < 256; Index++) {
    if (Private->BbsEntry[Index] != 0xFFFF) {
      if (!BbsBitmap[Index] && !BbsAfterCount) {
        BbsAfterCount = Index;
      }
      BbsNewCount++;
    }
  }

  if (BbsNewCount < BbsBeforeCount) {
    CsmAssert (
      "e:\hs\\AmiiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
      435,
      "NumberOfBbsEntriesAfterOpron >= NumberOfBbsEntriesBeforeOpron"
      );
  }

  DeviceIndex = BbsNewCount - BbsBeforeCount;
  Private->BbsType = mIplDtTable[DeviceType];

  if (mIplDtHandleCounter == mIplDtHandleCounter) {
    mIplDtHandleCounter = 0xFFFF;
    Status = gBS->AllocatePool (
               1,
               4,
               16,
               &mIplDtHandleCounter
               );
    if (EFI_ERROR (Status)) {
      CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
      CsmAssert (
        "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
        635,
        "!EFI_ERROR (Status)"
        );
    }
    mIplDtHandleCounter = 0;
  }

  return EFI_SUCCESS;

Cleanup:
  gBS->CloseProtocol (
         DeviceHandle,
         &gEfiLegacyRegionProtocolGuid,
         Private->Handle,
         DeviceHandle
         );
  gBS->CloseProtocol (
         DeviceHandle,
         &gEfiBlockIoProtocolGuid,
         Private->Handle,
         DeviceHandle
         );
  return Status;
}

//
// ============================================================================
// sub_FA8 -- Close / Cleanup INT13 for a device
// Called when a device handle is removed or when shutting down CSM
// block I/O legacy support.
// ============================================================================
//
EFI_STATUS
CsmBlockIoCloseDevice (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN EFI_HANDLE            Handle,
  IN UINTN                 DeviceCount,
  IN EFI_HANDLE            *DeviceHandles
  )
{
  EFI_STATUS          Status;
  BOOLEAN             PlatformAvailable;
  UINTN               Index;
  EFI_LEGACY_REGION   *LegacyRegion;

  //
  // Decrement reference count on IPLDT allocation
  //
  if (--mIplDtRefCount == 0) {
    Status = gBS->FreePool (mIplDtHandleCounter, 16);
    if (EFI_ERROR (Status)) {
      CsmDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
      CsmAssert (
        "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
        635,
        "!EFI_ERROR (Status)"
        );
    }
    mIplDtHandleCounter = 0;
  }

  PlatformAvailable = FALSE;
  Status = gBS->OpenProtocol (
                  Handle,
                  &gEfiLegacyBiosPlatformProtocolGuid,
                  (VOID **)&Private->LegacyBiosPlatform,
                  Private->Handle,
                  Handle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    PlatformAvailable = TRUE;
  }

  //
  // Process each device handle
  //
  for (Index = 0; Index < DeviceCount; Index++) {
    //
    // Open Disk Info protocol on the child handle
    //
    Status = gBS->OpenProtocol (
                    DeviceHandles[Index],
                    &gEfiDiskInfoProtocolGuid,
                    (VOID **)&Private->DiskInfo,
                    Private->Handle,
                    Handle,
                    2
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    LegacyRegion = Private->LegacyRegion;

    //
    // If Legacy BIOS Platform is available, transfer to it
    //
    if (PlatformAvailable) {
      gBS->CloseProtocol (
             Handle,
             &gEfiBlockIoProtocolGuid,
             Private->Handle,
             DeviceHandles[Index]
             );
    }

    //
    // Free the INT13 handler's memory
    //
    gBS->FreePool (LegacyRegion->GetInt13Handler (LegacyRegion));

    //
    // Install the protocol interface on the child handle
    //
    Status = gBS->InstallProtocolInterface (
                    &DeviceHandles[Index],
                    &gEfiDiskInfoProtocolGuid,
                    (VOID *)LegacyRegion,
                    LegacyRegion->GetInterface (LegacyRegion),
                    &gEfiBlockIoProtocolGuid,
                    LegacyRegion->GetBlockIo (LegacyRegion),
                    0
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    //
    // Set legacy region flags
    //
    LegacyRegion->SetFlags (LegacyRegion, 3, 0x700, 0);

    //
    // If Platform is not available, close BlockIo
    //
    if (!PlatformAvailable) {
      gBS->CloseProtocol (
             Handle,
             &gEfiLegacyRegionProtocolGuid,
             Private->Handle,
             DeviceHandles[Index]
             );
    }

    gBS->FreePool (LegacyRegion);
  }

  //
  // Final cleanup
  //
  gBS->CloseProtocol (
         Handle,
         &gEfiBlockIoProtocolGuid,
         Private->Handle,
         Handle
         );
  if (!PlatformAvailable) {
    gBS->CloseProtocol (
           Handle,
           &gEfiLegacyRegionProtocolGuid,
           Private->Handle,
           Handle
           );
  }

  return EFI_SUCCESS;
}

//
// ============================================================================
// sub_1468 -- Find device in IPLDT (Legacy Device Table)
// Searches the IPLDT for a matching bus:device tuple and sets
// the device index.
// ============================================================================
//
VOID
CsmFindInIplDt (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN EFI_HANDLE            DeviceHandle
  )
{
  UINT8   Index;
  UINTN   EntryOffset;
  UINT16  Bus, Device;

  Bus = *(UINT16 *)((UINT8 *)DeviceHandle + 264);     // Bus number
  Device = *(UINT16 *)((UINT8 *)DeviceHandle + 266);  // Device number

  CsmDebugPrint (0x80000000, "CsmBlockIo L2E: BCV at %x:%x\n", Bus, Device);

  EntryOffset = 16 * mIplDtCurrentEntry + 0x460;
  for (Index = 0; Index < 32; Index++) {
    if (*(UINT16 *)(EntryOffset + 14) == Device &&
        *(UINT16 *)(EntryOffset + 16) == Bus) {
      break;
    }
    EntryOffset += 64;  // IPLDT_ENTRY_SIZE
  }

  if (Index == 32) {
    CsmDebugPrint (0x80000000, "Entry is not found in IPLDT\n");
    return;
  }

  Private->DeviceIndex = *(UINT8 *)(mIplDtCurrentEntry * 16 + Index + 1);
  CsmDebugPrint (0x80000000, "IPLDT[%x], index %x, handle %x\n",
                 Index, *(UINT8 *)(EntryOffset + 2), Private->DeviceIndex);

  if (Private->DeviceIndex <= 0x7F) {
    CsmAssert (
      "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmBlockIo.c",
      886,
      "Handle > 0x7f"
      );
  }

  Private->CsmDeviceIndex = Private->DeviceIndex;
}

//
// ============================================================================
// sub_1570 -- INT13 handler initialization
// Called to set up INT13 handler function table for a device.
// ============================================================================
//
BOOLEAN
CsmInitInt13Handler (
  IN CSM_BLOCK_IO_PRIVATE  *Private
  )
{
  //
  // Initialize the media descriptor pointer and INT13 saved state array
  //
  Private->Media = &Private->MediaDescriptor;
  Private->Int13SavedFlagsBase = (UINT32 *)&Private->Int13SavedFlags;

  //
  // Set signature based on system table revision
  //
  if (gST->Hdr.Revision < 0x2001F) {
    Private->Signature = 0x1FFF1;
  } else {
    Private->Signature = 0x20031;
  }

  //
  // Identify and set up drive parameters
  //
  if (!Int13IdentifyDevice (Private, (UINT8 *)&Private->DeviceInfo)) {
    return FALSE;
  }

  if (Int13GetDriveParameters (Private, (UINT8 *)&Private->DeviceInfo)) {
    //
    // LBA device -- use extended INT13
    //
    Private->LastBlock = Private->DeviceInfo.MaxSector - 1;
    Private->BlockSize = Private->DeviceInfo.BytesPerSector;
    if ((Private->DeviceInfo.Flags & 4) != 0) {
      Private->RemovableMedia = 1;
    }
  } else {
    //
    // CHS device
    //
    Private->BlockSize = 512;
    Private->LastBlock = (UINT64)(
      (Private->DeviceInfo.Heads + 1) *
      (Private->DeviceInfo.Cylinders + 1) *
      Private->DeviceInfo.Sectors
      ) - 1;
  }

  //
  // Only support 512-byte sectors
  //
  if (Private->BlockSize != 512) {
    return FALSE;
  }

  //
  // Set up INT13 handler function table
  //
  Private->MediaId = 0;
  Private->MediaPresent = 1;
  Private->Alignment = 1;

  Private->Int13DiskIo = (UINT64)Int13GetStatus;
  Private->Int13ErrorHandler = (UINT64)Int13ErrorStub;

  if (Private->DeviceInfo.ExtInt13Support) {
    //
    // Extended INT13 device -- use LBA handlers
    //
    Private->Int13ReadWrite = (UINT64)Int13ReadWriteChs;
    Private->Int13Extensions = (UINT64)Int13ExtendedRead;
  } else {
    //
    // CHS-only device
    //
    Private->Int13ReadWrite = (UINT64)Int13ChsReadWrite;
    Private->Int13Extensions = (UINT64)Int13ExtendedWrite;
  }

  Private->DmaSupported = 0;
  Private->Alignment = 0;

  if (gST->Hdr.Revision >= 0x2001F) {
    Private->Alignment = 0;
    Private->AlignmentShift = Private->BlockSize;
    Private->AlignmentMask = 1;
  }

  return TRUE;
}

//
// ============================================================================
// sub_16B0 -- Identify device parameters via INT13
// Issues INT13 function 0x13 to get drive parameters
// ============================================================================
//
BOOLEAN
Int13IdentifyDevice (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  OUT UINT8                *DeviceInfo
  )
{
  UINT8   DeviceParam;

  DeviceParam = DeviceInfo[1];
  DeviceInfo[1] = 8;

  Int13SaveState (Private);

  (*Private->Int13HandlerEntry) (Private, 0x13, (UINT8 *)&DeviceParam);

  Int13RestoreState (Private);

  if ((Private->Int13Flags & 1) != 0 || DeviceInfo[1] != 0) {
    DeviceInfo[8] = DeviceInfo[1];
    return FALSE;
  }

  if (DeviceInfo[24] == 0) {
    //
    // CHS device -- extract geometry
    //
    DeviceInfo[26] = DeviceInfo[13] & 0x3F;                // Sectors
    *(UINT16 *)&DeviceInfo[28] = (UINT16)(
      DeviceInfo[11] + 4 * (DeviceInfo[10] & 0xC0 |
      (4 * (DeviceInfo[13] & 0xC0)))
      );
    DeviceInfo[27] = DeviceInfo[10] & 0x3F;                // Heads
    return TRUE;
  }

  if (DeviceInfo[4] == 16) {
    DeviceInfo[25] = 1;   // ATAPI device
    return TRUE;
  }

  DeviceInfo[26] = DeviceInfo[13];             // Sectors
  *(UINT16 *)&DeviceInfo[28] = *(UINT16 *)&DeviceInfo[11]; // Cylinders
  DeviceInfo[27] = DeviceInfo[10];             // Heads

  if (DeviceInfo[27]) {
    return TRUE;
  }

  return FALSE;
}

//
// ============================================================================
// sub_1784 -- Get extended drive parameters (INT13 function 0x48)
// For EDD-3.0 compatible devices, retrieves full geometry.
// ============================================================================
//
BOOLEAN
Int13GetDriveParameters (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  OUT UINT8                *DriveParams
  )
{
  UINT8   ParamPacket;

  ParamPacket = 65;           // parameter packet size (41h)
  DriveParams[2] = 21930;     // signature
  DriveParams[1] = 8;

  Int13SaveState (Private);

  (*Private->Int13HandlerEntry) (Private, 0x13, &ParamPacket);

  Int13RestoreState (Private);

  if ((Private->Int13Flags & 1) != 0 || *(UINT16 *)&DriveParams[2] != (UINT16)~21931) {
    DriveParams[3] = 0;
    DriveParams[5] = 0;
    return FALSE;
  }

  DriveParams[2] = ParamPacket;      // sector size low
  DriveParams[4] = (DriveParams[1] & 2) != 0;  // DMA
  DriveParams[6] = DriveParams[1] & 8;         // LBA
  DriveParams[5] = (DriveParams[1] & 4) != 0;  // removable
  DriveParams[3] = DriveParams[1] & 1;          // extended INT13

  //
  // Get CHS geometry from INT13 function
  //
  DriveParams[7] = Int13ChsGeometry (Private, DriveParams);

  return TRUE;
}

//
// ============================================================================
// sub_1834 -- Get CHS geometry from INT13 (function 0x08 or ATA identify)
// ============================================================================
//
BOOLEAN
Int13ChsGeometry (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN UINT8                 *DriveParams
  )
{
  UINT32  CmosParams[8];
  UINT8   ParamPacket;
  UINT8   FunctionCode;

  //
  // Initialize CMOS parameter table for geometry decode
  //
  CmosParams[0] = 0x014F001;
  CmosParams[1] = 0x01004012;
  CmosParams[2] = 0x4F200000;
  CmosParams[3] = 0x100;
  CmosParams[4] = 0x1000001;
  CmosParams[5] = 0x10000;
  CmosParams[6] = 0x1000400;
  CmosParams[7] = 0x0F000009;

  //
  // Set up INT13 function 0x08 parameter block
  //
  ParamPacket = 'O';  // 79
  FunctionCode = 'H'; // 72
  *(UINT16 *)(mInt13TransferSegment2 + 32) = 74;

  CmosParams[3] = 0x100;
  *(UINT16 *)((UINT64)&CmosParams[3] + 2) = ((UINT64)(mInt13TransferSegment2 + 32) >> 4) & 0xF000;

  Int13SaveState (Private);

  (*Private->Int13HandlerEntry) (Private, 0x13, &ParamPacket);

  if ((Private->Int13Flags & 1) == 0 && FunctionCode == 0) {
    //
    // Success -- read geometry from transfer buffer
    //
    gBS->SetMem (
           (VOID *)((UINTN)DriveParams + 32),
           74,
           0
           );
    gBS->CopyMem (
           (VOID *)((UINTN)DriveParams + 32),
           (VOID *)(mInt13TransferSegment2 + 32),
           74
           );

    if (DriveParams[25] != 0) {
      //
      // EDD device -- read more geometry
      //
      DriveParams[1] = 8;
      ParamPacket = ' ';
      FunctionCode = 32;

      (*Private->Int13HandlerEntry) (Private, 0x13, &ParamPacket);

      if ((Private->Int13Flags & 1) != 0) {
        if ((DriveParams[34] & 2) != 0) {
          DriveParams[26] = DriveParams[40] - 1;   // Heads
          DriveParams[27] = DriveParams[44];        // Sectors
          if (DriveParams[27] == 0) {
            CsmAssert (
              "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmInt13.c",
              344,
              "Drive->MaxSector != 0"
              );
          }
        }
      } else {
        //
        // Decode CHS from function 0x08 response
        //
        if (FunctionCode != 10) {
          if ((UINT8)(FunctionCode - 3) <= 10) {
            DriveParams[26] = CmosParams[(UINT8)(3 * (FunctionCode - 3))];
            DriveParams[27] = CmosParams[(UINT8)(3 * (FunctionCode - 3) + 1)];
            *(UINT16 *)&DriveParams[28] = (UINT16)CmosParams[(UINT8)(3 * (FunctionCode - 3) + 2)];
          } else {
            DriveParams[26] = 256;
          }
        } else {
          if ((DriveParams[34] & 2) != 0) {
            DriveParams[26] = DriveParams[40] - 1;
            DriveParams[27] = DriveParams[44];
            if (DriveParams[27] == 0) {
              CsmAssert (
                "e:\\hs\\AmiModulePkg\\CSM\\CsmBlockIo\\CsmInt13.c",
                369,
                "Drive->MaxSector != 0"
                );
            }
            *(UINT16 *)&DriveParams[28] = *(UINT16 *)&DriveParams[36] - 1;
          } else {
            DriveParams[26] = 256;
          }
        }

        //
        // Calculate total sectors
        //
        *(UINT64 *)&DriveParams[48] =
          (UINT64)(DriveParams[26] + 1) *
          (*(UINT16 *)&DriveParams[28] + 1) *
          DriveParams[27];

        *(UINT16 *)&DriveParams[56] = 512;  // bytes per sector
      }
    }

    //
    // Set total sectors from CHS
    //
    *(UINT64 *)&DriveParams[16] =
      *(UINT16 *)&DriveParams[58] +
      16 * (((UINT32)*(UINT16 *)&DriveParams[58] >> 4) & 0xF000);

    Int13RestoreState (Private);
    return TRUE;
  }

  Int13RestoreState (Private);

  *(UINT8 *)&DriveParams[8] = FunctionCode;
  gBS->SetMem (
         (VOID *)((UINTN)DriveParams + 32),
         74,
         (UINT8)(-81)
         );

  return FALSE;
}

//
// ============================================================================
// sub_11E4 -- Build BBS device type ID
// Parses device path media type string and generates BBS device type ID
// for the IPLDT / BBS table.
// ============================================================================
//
UINT64
EFIAPI
BbsDeviceTypeBuilder (
  IN CSM_BLOCK_IO_PRIVATE  *Private,
  IN VOID                  *DevicePath,
  OUT UINT64               *OutBbsType
  )
{
  UINT64  Result;
  UINT32  TypeId;
  UINT8   TypeFields[12];
  UINT8   *MediaType;
  UINT8   InterfaceType;    // offset +2 from device path
  UINT16  DevicePathLen;

  //
  // Default type for unrecognized devices
  //
  *(UINT64 *)&TypeFields[0] = 0xC51FAC4F3F2C1D11ULL;
  *(UINT64 *)&TypeFields[4] = 0xF38500A0C93EC9B3ULL;

  //
  // Validate device path node type
  //
  if (*(UINT8 *)((UINTN)DevicePath + 2) != 0x30) {     // MESSAGING_DEVICE_PATH
    goto UseDefault;
  }
  if (*(UINT16 *)((UINTN)DevicePath + 32) <= 0x1A) {   // length too small
    goto UseDefault;
  }

  MediaType = (UINT8 *)((UINTN)DevicePath + 72);
  InterfaceType = *(UINT8 *)((UINTN)DevicePath + 83);

  if (*(UINT32 *)((UINTN)DevicePath + 72) == 0) {      // no media type
    goto UseDefault;
  }

  //
  // Compare media type strings
  //

  // ATAPI
  if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_ATAPI, 5) == 0) {
    TypeFields[0] = InterfaceType;
    TypeFields[1] = *(UINT8 *)((UINTN)DevicePath + 88);
    TypeFields[2] = *(UINT8 *)((UINTN)DevicePath + 89);
    TypeId = 0x080247;  // ATA master
    goto Done;
  }

  // ATA (same as ATAPI)
  if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_ATA, 3) == 0) {
    TypeFields[0] = InterfaceType;
    TypeFields[1] = *(UINT8 *)((UINTN)DevicePath + 88);
    TypeFields[2] = *(UINT8 *)((UINTN)DevicePath + 89);
    TypeId = 0x080247;
    goto Done;
  }

  // SCSI
  if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_SCSI, 4) != 0) {
    // USB
    if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_USB, 3) != 0) {
      // 1394
      if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_1394, 4) != 0) {
        // FIBRE
        if (AsciiStrnCmp ((CHAR8 *)MediaType, MEDIA_FIBRE, 5) != 0) {
          goto UseDefault;
        }
        // FIBRE
        *(UINT64 *)&TypeFields[4] = *(UINT64 *)((UINTN)DevicePath + 88);
        TypeId = 0x180403;
        goto Done;
      }
      // 1394
      *(UINT64 *)&TypeFields[4] = *(UINT64 *)((UINTN)DevicePath + 88);
      TypeId = 0x100403;
      goto Done;
    }
    // USB
    TypeFields[0] = *(UINT8 *)((UINTN)DevicePath + 96);
    TypeId = 0x060503;
    goto Done;
  }

  // SCSI
  *(UINT32 *)&TypeFields[0] = *(UINT32 *)((UINTN)DevicePath + 88);
  TypeId = 0x080203;
  goto Done;

UseDefault:
  TypeFields[0] = *(UINT8 *)((UINTN)DevicePath + 1);
  TypeId = 0x150101;
  *(UINT64 *)&TypeFields[0] = *(UINT64 *)&TypeFields[0]; // default GUID-like type
  goto Done;

Done:
  Result = CsmBbsTableAllocate (Private, &TypeId);
  *OutBbsType = Result;
  return Result;
}