/**
* @file UsbInt13.c
* @brief USB INT13 Legacy Driver - Full source reconstruction
*
* This module provides legacy INT13 BIOS support for USB mass storage devices
* in Lenovo HR650X (and similar) platforms. It enables booting from USB floppy,
* USB HDD, and USB CDROM devices when the system is in legacy BIOS / CSM mode.
*
* Source: e:\hs\AmiModulePkg\Usb\Int13\UsbInt13.c
*
* Key features:
* - Allocates and manages INT13 device parameter tables in legacy BIOS data areas
* - Handles USB hotplug events by installing/uninstalling INT13 handlers
* - Reorders boot priority at ReadyToBoot event to honor user boot selection
* - Manages three hotplug device types: FDD, HDD, CDROM
*
* All addresses are relative to image base 0x0.
*/
#include "UsbInt13.h"
// ============================================================================
// Globals
// ============================================================================
EFI_HANDLE gImageHandle = NULL; // 0x1EF0
EFI_SYSTEM_TABLE *gSystemTable = NULL; // 0x1EE0
EFI_BOOT_SERVICES *gBootServices = NULL; // 0x1EE8
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL; // 0x1EF8
EFI_SYSTEM_TABLE *gSystemTable2 = NULL; // 0x1F18
EFI_RUNTIME_SERVICES *gRuntimeServices2= NULL; // 0x1F10
VOID *gUsbHcDevice = NULL; // 0x1EC0
USB_INT13_DEVICE_ENTRY *gInt13DeviceTable= NULL; // 0x1EC8
VOID *gBbsProtocol = NULL; // 0x1ED0
UINT8 *gBbsDataBase = NULL; // 0x1EB0
UINT8 *gBbsDeviceMap = NULL; // 0x1EA0
EFI_USB_HC_PROTOCOL *gUsbHcProtocol = NULL; // 0x1ED8
VOID *gDebugProtocol = NULL; // 0x1F00
VOID *gHobList = NULL; // 0x1F08
UINT8 gBootIndex = 0; // 0x1EB8
BOOLEAN gBbsPortPatched = FALSE; // 0x1EA8
UINT8 gSystemPowerState = 0; // 0x1F20
USB_INT13_HOTPLUG_DEVICE gHotplugFdd = { NULL, 0xFFFF, 3, 126, "USB Hotplug FDD", NULL };
USB_INT13_HOTPLUG_DEVICE gHotplugHdd = { NULL, 0xFFFF, 1, 125, "USB Hotplug HDD", NULL };
USB_INT13_HOTPLUG_DEVICE gHotplugCdrom = { NULL, 0xFFFF, 2, 127, "USB Hotplug CDROM", NULL };
// ============================================================================
// Library helpers
// ============================================================================
void *SetMem(void *Buffer, UINTN Size, UINT8 Value)
{
return memset(Buffer, Value, Size);
}
void *ZeroMem(void *Buffer, UINTN Size)
{
return SetMem(Buffer, Size, 0);
}
UINT64 ReadUnaligned64(const VOID *Buffer)
{
return *(const UINT64 *)Buffer;
}
BOOLEAN CompareGuid(const GUID *Guid1, const GUID *Guid2)
{
return ReadUnaligned64(Guid1) == ReadUnaligned64(&Guid1->Data2)
&& ReadUnaligned64((VOID *)Guid2 + 8) == ReadUnaligned64((VOID *)Guid1 + 8);
}
// ============================================================================
// Debug support
// ============================================================================
VOID *EfiGetDebugProtocol(VOID)
{
UINTN Pages;
EFI_STATUS Status;
if (gDebugProtocol != NULL)
return gDebugProtocol;
Pages = gBootServices->GetMemoryMap(&Pages, NULL, NULL, NULL, NULL);
gBootServices->GetMemoryMap(&Pages, NULL, NULL, NULL, NULL);
if (Pages <= 16) {
Status = gBootServices->LocateProtocol(&gEfiDebugProtocolGuid, NULL, &gDebugProtocol);
if (EFI_ERROR(Status))
gDebugProtocol = NULL;
}
return gDebugProtocol;
}
UINTN EFIAPI DebugPrint(UINTN ErrorLevel, CONST CHAR8 *Format, ...)
{
VA_LIST Marker;
UINTN Result;
if (!EfiGetDebugProtocol())
return 0;
Result = GetSystemPowerState();
if ((Result & ErrorLevel) != 0) {
VA_START(Marker, Format);
VA_END(Marker);
}
return Result;
}
VOID EFIAPI AssertHandler(CONST CHAR8 *FileName, UINTN LineNumber, CONST CHAR8 *Description)
{
VOID *DebugProtocol;
DebugProtocol = EfiGetDebugProtocol();
if (DebugProtocol != NULL) {
((EFI_DEBUG_PROTOCOL *)DebugProtocol)->Assert(FileName, LineNumber, Description);
}
}
// ============================================================================
// HOB list retrieval
// ============================================================================
VOID *EfiGetHobList(VOID)
{
UINTN Index;
if (gHobList != NULL)
return gHobList;
gHobList = NULL;
for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) {
if (CompareGuid(
(GUID *)&gSystemTable->ConfigurationTable[Index].VendorGuid,
&gEfiHobListGuid))
{
gHobList = gSystemTable->ConfigurationTable[Index].VendorTable;
break;
}
}
if (gHobList == NULL)
AssertHandler("e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 54, "!EFI_ERROR (Status)");
if (gHobList == NULL)
AssertHandler("e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 55, "mHobList != ((void *) 0)");
return gHobList;
}
// ============================================================================
// System power state
// ============================================================================
UINTN GetSystemPowerState(VOID)
{
UINT8 Index;
UINT8 CmosValue;
UINT8 PowerState;
Index = __inbyte(CMOS_REG_ADDRESS);
__outbyte(CMOS_REG_ADDRESS, (Index & 0x80) | CMOS_STATUS_REGISTER);
CmosValue = __inbyte(CMOS_REG_DATA);
PowerState = CmosValue;
if (PowerState > 3) {
if (gSystemPowerState) {
PowerState = gSystemPowerState;
} else {
PowerState = (MEMORY[0xFDAF0490] & 2) | 1;
}
}
if (PowerState - 1 > 0xFD)
return 0;
return (PowerState == SYSTEM_POWER_STATE_S5) ? 0x80000004 : 0x80000005;
}
// ============================================================================
// Entry point
// ============================================================================
EFI_STATUS EFIAPI _ModuleEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
gImageHandle = ImageHandle;
if (!ImageHandle)
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c", 51, "gImageHandle != ((void *) 0)");
gSystemTable = SystemTable;
if (!SystemTable)
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c", 57, "gST != ((void *) 0)");
gBootServices = SystemTable->BootServices;
if (!gBootServices)
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c", 63, "gBS != ((void *) 0)");
gRuntimeServices = SystemTable->RuntimeServices;
if (!gRuntimeServices)
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c", 47, "gRT != ((void *) 0)");
EfiGetHobList();
return UsbInt13DriverEntry(ImageHandle, SystemTable);
}
// ============================================================================
// Main driver entry
// ============================================================================
EFI_STATUS EFIAPI UsbInt13DriverEntry(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
EFI_EVENT ReadyToBootEvent;
if (gSystemTable2 == NULL) {
gSystemTable2 = SystemTable;
gRuntimeServices2 = SystemTable->RuntimeServices;
}
Status = gBootServices->LocateProtocol(&gEfiUsbHcProtocolGuid, NULL, &gUsbHcProtocol);
if (EFI_ERROR(Status)) {
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 81, "!EFI_ERROR (Status)");
return Status;
}
gUsbHcDevice = *(VOID **)gUsbHcProtocol;
Status = UsbInt13AllocateLegacyStructs();
if (EFI_ERROR(Status)) {
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 89, "!EFI_ERROR (Status)");
return Status;
}
*(UINT64 *)(gUsbHcProtocol + 40) = (UINT64)UsbInt13EnumerateUsbDevices;
*(UINT64 *)(gUsbHcProtocol + 48) = (UINT64)UsbInt13InstallDevice;
*(UINT64 *)(gUsbHcProtocol + 56) = (UINT64)UsbInt13UninstallDevice;
Status = RegisterReadyToBootEvent(&ReadyToBootEvent);
if (EFI_ERROR(Status)) {
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 99, "!EFI_ERROR (Status)");
return Status;
}
return EFI_SUCCESS;
}
// ============================================================================
// Legacy struct allocation
// ============================================================================
EFI_STATUS UsbInt13AllocateLegacyStructs(VOID)
{
EFI_STATUS Status;
UINT16 BbsConfigSize;
UINT16 BbsDeviceMapOffset;
UINT8 *BbsDataArea;
BbsConfigSize = 0;
if (MEMORY[0xF0018] < 8 && MEMORY[0xF0019] < 0x55)
return EFI_UNSUPPORTED;
gBbsDataBase = (UINT8 *)(MEMORY[0xFFF4C] + 0xF0000);
Status = gBootServices->LocateProtocol(&gEfiBbsTableProtocolGuid, NULL, &gBbsProtocol);
if (EFI_ERROR(Status))
return Status;
Status = ((BBS_PROTOCOL *)gBbsProtocol)->GetConfig(1, 0, 2, &BbsConfigSize, &BbsDeviceMapOffset);
if (EFI_ERROR(Status))
return Status;
BbsDataArea = (UINT8 *)(BbsDeviceMapOffset + gBbsDataBase[BbsConfigSize * 2 + 0x5A0]);
*(UINT64 *)BbsDataArea = 0x31000000B2000001ULL;
*(UINT16 *)(BbsDataArea + 8) = 0;
*(UINT8 *)(BbsDataArea + 10) = 0;
gInt13DeviceTable = (USB_INT13_DEVICE_ENTRY *)(
((BBS_PROTOCOL *)gBbsProtocol)->Allocate(BbsDeviceMapOffset, BbsConfigSize, 16));
if (gInt13DeviceTable == NULL)
return EFI_OUT_OF_RESOURCES;
gBbsDeviceMap = (UINT8 *)gInt13DeviceTable + *(UINT16 *)((UINT8 *)gInt13DeviceTable + 1442);
return EFI_SUCCESS;
}
// ============================================================================
// Hotplug init
// ============================================================================
EFI_STATUS UsbInt13InitHotplugStructs(VOID)
{
UINT8 *HcDeviceBase;
HcDeviceBase = (UINT8 *)gUsbHcDevice;
gHotplugFdd.Handle = NULL;
gHotplugFdd.Int13DriveNum = 0xFFFF;
gHotplugFdd.DeviceType = USB_INT13_DEVICE_TYPE_FLOPPY;
gHotplugFdd.LegacyInt13Num = 126;
gHotplugFdd.Buffer = HcDeviceBase + 27712;
gHotplugFdd.NameString = "USB Hotplug FDD";
gHotplugHdd.Handle = NULL;
gHotplugHdd.Int13DriveNum = 0xFFFF;
gHotplugHdd.DeviceType = USB_INT13_DEVICE_TYPE_HDD;
gHotplugHdd.LegacyInt13Num = 125;
gHotplugHdd.Buffer = HcDeviceBase + 28160;
gHotplugHdd.NameString = "USB Hotplug HDD";
gHotplugCdrom.Handle = NULL;
gHotplugCdrom.Int13DriveNum = 0xFFFF;
gHotplugCdrom.DeviceType = USB_INT13_DEVICE_TYPE_CDROM;
gHotplugCdrom.LegacyInt13Num = 127;
gHotplugCdrom.Buffer = HcDeviceBase + 28608;
gHotplugCdrom.NameString = "USB Hotplug CDROM";
if (((HcDeviceBase[30497] - 1) & 0xFD) == 0)
UsbInt13InstallDevice((VOID *)&gHotplugFdd);
if (((HcDeviceBase[30498] - 1) & 0xFD) == 0)
UsbInt13InstallDevice((VOID *)&gHotplugHdd);
if (((HcDeviceBase[30499] - 1) & 0xFD) == 0)
UsbInt13InstallDevice((VOID *)&gHotplugCdrom);
return EFI_SUCCESS;
}
// ============================================================================
// ReadyToBoot callback
// ============================================================================
VOID EFIAPI UsbInt13ReadyToBootCallback(
IN EFI_EVENT Event,
IN VOID *Context)
{
EFI_STATUS Status;
UINTN HandleCount;
VOID *BbsProtocol;
BBS_TABLE *BbsTable;
UINT16 BbsEntryCount;
UINT16 EntryIndex;
UINT16 BestBbsIndex;
HandleCount = 0;
Status = gBootServices->LocateProtocol(&gEfiBbsTableProtocolGuid, NULL, &HandleCount);
ASSERT(!EFI_ERROR(Status));
if (EFI_ERROR(Status))
return;
BbsProtocol = (VOID *)HandleCount;
HandleCount = 0;
BbsTable = NULL;
Status = ((BBS_PROTOCOL *)BbsProtocol)->GetTable(
(VOID *)&Event, (UINT8 *)&BbsTable, &BbsEntryCount, &HandleCount);
ASSERT(!EFI_ERROR(Status));
if (EFI_ERROR(Status))
return;
for (EntryIndex = 0; EntryIndex < BbsEntryCount; EntryIndex++) {
BBS_ENTRY *Entry = &BbsTable->Entries[EntryIndex];
if (Entry->DeviceType == BBS_TYPE_ATAPI) {
switch (Entry->InterfaceType & 0x0F) {
case 2:
Entry->DeviceType = BBS_TYPE_ATA;
break;
case 3:
Entry->DeviceType = 3;
break;
case 4:
Entry->DeviceType = BBS_TYPE_ATA;
break;
default:
Entry->DeviceType = 0xFF;
break;
}
}
}
if (gBootIndex != 0) {
BestBbsIndex = 256;
UINT8 BootDeviceIndex = gBootIndex;
UINT16 BootDeviceEntryCount = BbsTable->Entries[BootDeviceIndex].Priority;
for (EntryIndex = 0; EntryIndex < 256; EntryIndex++) {
if (EntryIndex != BootDeviceIndex) {
if (BbsTable->Entries[EntryIndex].Priority < BootDeviceEntryCount) {
BootDeviceEntryCount = BbsTable->Entries[EntryIndex].Priority;
BestBbsIndex = EntryIndex;
}
}
}
if (BestBbsIndex < 256) {
UINT16 Temp = BbsTable->Entries[BootDeviceIndex].Priority;
BbsTable->Entries[BootDeviceIndex].Priority = BbsTable->Entries[BestBbsIndex].Priority;
BbsTable->Entries[BestBbsIndex].Priority = Temp;
}
}
}
// ============================================================================
// Build INT13 param table
// ============================================================================
EFI_STATUS UsbInt13BuildInt13ParamTable(
IN UINT8 DevIndex,
IN VOID *UsbDevice,
OUT INT13_PARAM_TABLE *ParamTable)
{
UINT8 DeviceType;
UINT8 *ProductName;
UINT8 *ProductNameDest;
CHAR8 NameChar;
UINT8 *PatchedEntry;
UINTN EbbOffset;
UINT8 MediaType;
if (DevIndex >= USB_INT13_MAX_DEVICES)
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 412, "DevIndex < 16");
if (gBbsProtocol == NULL)
return EFI_NOT_FOUND;
ZeroMem(ParamTable, USB_INT13_DEVICE_ENTRY_SIZE);
ParamTable->Heads = *(UINT8 *)(UsbDevice + 137);
ParamTable->SectorsPerTrack= (*(UINT16 *)(UsbDevice + 136) >> 3) & 0x1F;
ParamTable->Cylinders = *(UINT16 *)(UsbDevice + 136) & 7;
ParamTable->BytesPerSector = INT13_SECTOR_SIZE;
ParamTable->Int13Flags = INT13_DISK_SIZE_HEAD_MULT;
ProductName = *(UINT8 **)(UsbDevice + 144);
ParamTable->NameStrLen = (UINT8)((UINTN)gInt13DeviceTable + 25 + DevIndex * 89) & 0xFF;
ProductNameDest = (UINT8 *)((UINTN)gInt13DeviceTable + 25 + DevIndex * 89);
for (UINTN i = 0; i < 63; i++) {
NameChar = *ProductName;
if (NameChar == 0)
break;
if (NameChar != ' ' || *(ProductName - 1) != ' ')
*ProductNameDest++ = NameChar;
ProductName++;
}
*ProductNameDest = 0;
ParamTable->NameStrOff = (UINT16)(UINTN)ProductNameDest;
ParamTable->NameStrSeg = (UINT16)((UINTN)ProductNameDest >> 4) & 0xF000;
ParamTable->DevPathSegment = ((UINTN)gInt13DeviceTable + 1424) >> 4 & 0xF000;
ParamTable->DevPathOffset = (UINT16)(UINTN)((UINTN)gInt13DeviceTable + 1424);
DeviceType = *(UINT8 *)(UsbDevice + 152);
MediaType = *(UINT8 *)(UsbDevice + 120);
switch (DeviceType) {
case USB_INT13_DEVICE_TYPE_FLOPPY:
MediaType |= 0x80;
ParamTable->Int13DevType = INT13_DEVICE_TYPE_HDD;
ParamTable->ControllerIndex = 2;
break;
case USB_INT13_DEVICE_TYPE_CDROM:
ParamTable->Int13DevType = INT13_DEVICE_TYPE_HDD;
ParamTable->ControllerIndex = 4;
break;
case USB_INT13_DEVICE_TYPE_HDD:
ParamTable->Int13DevType = INT13_DEVICE_TYPE_FLOPPY;
ParamTable->EbbTableSegment = 0xF000;
ParamTable->EbbTableOffset = *(UINT16 *)(gBbsDataBase + 12);
if (!gBbsPortPatched) {
EbbOffset = ((UINTN)gInt13DeviceTable << 12) + *(UINT16 *)((UINT8 *)gInt13DeviceTable + 1438);
gBbsPortPatched = TRUE;
PatchedEntry = (UINT8 *)(*(UINT16 *)(gBbsDataBase + 14) + 0xF0005);
*PatchedEntry = BBS_PORT_PATCH_OPCODE;
*(UINT32 *)(PatchedEntry + 1) = EbbOffset;
}
break;
default:
ParamTable->Int13DevType = INT13_DEVICE_TYPE_UNKNOWN;
ParamTable->ControllerIndex = 0;
break;
}
ParamTable->Int13Flags = ((MediaType + (ControllerIndex << 16)) << 8) + 17;
ParamTable->DeviceSectors = *(UINT64 *)(UsbDevice + 128);
return EFI_SUCCESS;
}
// ============================================================================
// Device enumeration
// ============================================================================
EFI_STATUS UsbInt13EnumerateUsbDevices(VOID)
{
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
UINTN HandleCount;
UINTN HandleIndex;
VOID *UsbIoProtocol;
USB_DEVICE_DESCRIPTOR DevDesc;
VOID *BbsProtocol;
UINT8 *UsbHcDevice;
UINT8 *UsbDevice;
UINT8 DeviceProtocol;
if (*(UINT8 *)((UINT8 *)gUsbHcDevice + 4) & 4)
return EFI_UNSUPPORTED;
UsbInt13InitHotplugStructs();
Status = gBootServices->LocateHandleBuffer(
ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
if (EFI_ERROR(Status))
return Status;
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
if (EFI_ERROR(gBootServices->OpenProtocol(
HandleBuffer[HandleIndex], &gEfiUsbHcProtocolGuid, &BbsProtocol,
gImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)))
continue;
if (EFI_ERROR(((USB_IO_PROTOCOL *)BbsProtocol)->GetDeviceDescriptor(
(USB_DEVICE_DESCRIPTOR *)&DevDesc)))
continue;
if (DevDesc.DeviceClass != USB_CLASS_MASS_STORAGE)
continue;
if (EFI_ERROR(gBootServices->OpenProtocol(
HandleBuffer[HandleIndex], &gEfiUsbIoProtocolGuid, &UsbIoProtocol,
gImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)))
continue;
UsbHcDevice = (UINT8 *)UsbIoProtocol - 8;
if (*(UINT32 *)UsbHcDevice != 0x73657255)
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 568, "CR has Bad Signature");
UsbDevice = *(UINT8 **)(UsbHcDevice + 112);
DeviceProtocol = *(UINT8 *)(UsbDevice + 101);
if (DeviceProtocol &&
(DeviceProtocol == 2 || (UINT16)(*(UINT16 *)(UsbDevice + 78) - 513) > 0xFDFD))
{
UsbInt13InstallDevice((VOID *)UsbHcDevice);
}
}
if (HandleBuffer != NULL)
gBootServices->FreePool(HandleBuffer);
return EFI_SUCCESS;
}
// ============================================================================
// Install device
// ============================================================================
EFI_STATUS UsbInt13InstallDevice(VOID *UsbDevice)
{
EFI_STATUS Status;
UINT8 UsbPort;
UINT8 DevIndex;
INT13_PARAM_TABLE ParamTable;
UINT8 BbsEntryIndex;
UINT8 *HcDataArea;
USB_INT13_DEVICE_ENTRY *Entry;
UINTN TableOffset;
UINT8 HcNumber;
UINT8 PortNumber;
UsbPort = *(UINT8 *)(UsbDevice + 120);
BbsEntryIndex = 0xFF;
for (DevIndex = 0; DevIndex < USB_INT13_MAX_DEVICES; DevIndex++) {
if (gInt13DeviceTable[DevIndex].UsbPort == UsbPort) {
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 608, "((BOOLEAN)(0==1))");
return EFI_INVALID_PARAMETER;
}
}
for (DevIndex = 0; DevIndex < USB_INT13_MAX_DEVICES; DevIndex++) {
if (gInt13DeviceTable[DevIndex].UsbPort == 0)
break;
}
if (DevIndex >= USB_INT13_MAX_DEVICES) {
AssertHandler("e:\\hs\\AmiModulePkg\\Usb\\Int13\\UsbInt13.c", 620, "Index<16");
if (DevIndex == 16)
return EFI_OUT_OF_RESOURCES;
}
Status = ((BBS_PROTOCOL *)gBbsProtocol)->Reset(0, 0, 0, 0);
ASSERT(!EFI_ERROR(Status));
Status = UsbInt13BuildInt13ParamTable(DevIndex, UsbDevice, &ParamTable);
ASSERT(!EFI_ERROR(Status));
Status = ((BBS_PROTOCOL *)gBbsProtocol)->AddEntry(gBbsProtocol, &ParamTable, &BbsEntryIndex);
if (EFI_ERROR(Status)) {
((BBS_PROTOCOL *)gBbsProtocol)->EndConfig(0, 0);
return Status;
}
Entry = &gInt13DeviceTable[DevIndex];
Entry->UsbPort = UsbPort;
Entry->BbsIndex = BbsEntryIndex;
Entry->DeviceType = *(UINT16 *)(*(UINT8 **)(UsbDevice + 112) + 94);
Entry->VendorId = *(UINT16 *)(*(UINT8 **)(UsbDevice + 112) + 88);
Entry->ProductId = *(UINT16 *)(*(UINT8 **)(UsbDevice + 112) + 98);
Entry->BcdRevision = *(UINT16 *)(*(UINT8 **)(UsbDevice + 112) + 92);
Entry->ConfigValue = *(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 96);
Entry->InterfaceNumber = *(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 90);
Entry->RemovableMedia = *(UINT16 *)(*(UINT8 **)(UsbDevice + 112) + 78);
Entry->Reserved3 = *(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 102);
Entry->UsbDevPathPtr = *(UINT64 *)(*(UINT8 **)(UsbDevice + 112) + 80);
TableOffset = (UINTN)gBbsDeviceMap + 2 * DevIndex;
*(UINT8 *)(DevIndex + (UINTN)gBbsDeviceMap) = UsbPort;
*(UINT16 *)(DevIndex + (UINTN)gBbsDeviceMap + 1) = *(UINT16 *)(UsbDevice + 136);
Status = ((BBS_PROTOCOL *)gBbsProtocol)->EndConfig(0, 0);
ASSERT(!EFI_ERROR(Status));
*(UINT32 *)(*(UINT8 **)(UsbDevice + 112)) |= 4;
if ((*(CHAR8 *)(*(UINT8 **)(UsbDevice + 112) + 12) < 0) &&
(gUsbHcProtocol->GetPortStatus(&BbsEntryIndex, &(UINT8){0}) >= 0) &&
!gBootIndex)
{
gUsbHcProtocol->GetPortStatus(&HcNumber, &PortNumber);
DebugPrint(DEBUG_INIT,
"OemUsbGetAssignBootPort: HC %d, Port %d; current HC %d, Port %d\n",
HcNumber, PortNumber,
*(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 11),
*(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 13));
if ((*(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 11) == HcNumber) &&
(*(UINT8 *)(*(UINT8 **)(UsbDevice + 112) + 13) == PortNumber))
{
DebugPrint(DEBUG_INIT, "---OemUsbGetAssignBootPort: BBS Entry# %d\n", BbsEntryIndex);
gBootIndex = BbsEntryIndex;
}
}
if ((UsbDevice != (VOID *)&gHotplugFdd) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_FLOPPY) &&
(*(UINT8 *)((UINT8 *)gUsbHcDevice + 30497) == 3))
{
DebugPrint(DEBUG_INIT, "Uninstalling Hotplug Floppy (Setup 'Auto' option)\n");
UsbInt13UninstallDevice((VOID *)&gHotplugFdd);
}
if ((UsbDevice != (VOID *)&gHotplugHdd) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_HDD) &&
(*(UINT8 *)((UINT8 *)gUsbHcDevice + 30498) == 3))
{
DebugPrint(DEBUG_INIT, "Uninstalling Hotplug HDD (Setup 'Auto' option)\n");
UsbInt13UninstallDevice((VOID *)&gHotplugHdd);
}
if ((UsbDevice != (VOID *)&gHotplugCdrom) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_CDROM) &&
(*(UINT8 *)((UINT8 *)gUsbHcDevice + 30499) == 3))
{
DebugPrint(DEBUG_INIT, "Uninstalling Hotplug CDROM (Setup 'Auto' option)\n");
UsbInt13UninstallDevice((VOID *)&gHotplugCdrom);
}
return EFI_SUCCESS;
}
// ============================================================================
// Uninstall device
// ============================================================================
EFI_STATUS UsbInt13UninstallDevice(VOID *UsbDevice)
{
EFI_STATUS Status;
UINT8 DevIndex;
UINT8 BbsEntryIndex;
UINT8 *HcDeviceBase;
DebugPrint(DEBUG_INIT, "Uninstalling INT13 device %x\n", UsbDevice);
Status = ((BBS_PROTOCOL *)gBbsProtocol)->Reset(0, 0, 0, 0);
ASSERT(!EFI_ERROR(Status));
for (DevIndex = 0; DevIndex < USB_INT13_MAX_DEVICES; DevIndex++) {
if (gInt13DeviceTable[DevIndex].UsbPort == *(UINT8 *)(UsbDevice + 120))
break;
}
if (DevIndex >= USB_INT13_MAX_DEVICES)
goto End;
BbsEntryIndex = gInt13DeviceTable[DevIndex].BbsIndex;
gInt13DeviceTable[DevIndex].UsbPort = 0;
Status = ((BBS_PROTOCOL *)gBbsProtocol)->RemoveEntry(gBbsProtocol, BbsEntryIndex);
ASSERT(!EFI_ERROR(Status));
if (gBootIndex == BbsEntryIndex)
gBootIndex = 0;
*(UINT8 *)((UINTN)gBbsDeviceMap + 2 * DevIndex) = 0;
End:
((BBS_PROTOCOL *)gBbsProtocol)->EndConfig(0, 0);
if (EFI_ERROR(Status))
return Status;
*(UINT32 *)(*(UINT8 **)(UsbDevice + 112)) &= 0xFFFFFFFA;
HcDeviceBase = (UINT8 *)gUsbHcDevice;
if ((UsbDevice != (VOID *)&gHotplugFdd) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_FLOPPY) &&
(HcDeviceBase[30497] == 3) &&
!(HcDeviceBase[30507]))
{
DebugPrint(DEBUG_INIT, "Installing Hotplug Floppy (Setup 'Auto' option)\n");
UsbInt13InstallDevice((VOID *)&gHotplugFdd);
}
if ((UsbDevice != (VOID *)&gHotplugHdd) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_HDD) &&
(HcDeviceBase[30498] == 3) &&
!(HcDeviceBase[30508]))
{
DebugPrint(DEBUG_INIT, "Installing Hotplug HDD (Setup 'Auto' option)\n");
UsbInt13InstallDevice((VOID *)&gHotplugHdd);
}
if ((UsbDevice != (VOID *)&gHotplugCdrom) &&
(*(UINT8 *)(UsbDevice + 152) == USB_INT13_DEVICE_TYPE_CDROM) &&
(HcDeviceBase[30499] == 3) &&
!(HcDeviceBase[30509]))
{
DebugPrint(DEBUG_INIT, "Installing Hotplug CDROM (Setup 'Auto' option)\n");
UsbInt13InstallDevice((VOID *)&gHotplugCdrom);
}
return Status;
}
// ============================================================================
// Register ReadyToBoot event
// ============================================================================
EFI_STATUS RegisterReadyToBootEvent(OUT EFI_EVENT *ReadyToBootEvent)
{
if (ReadyToBootEvent == NULL) {
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiNotTiano.c", 181,
"ReadyToBootEvent != ((void *) 0)");
return EFI_INVALID_PARAMETER;
}
if (gSystemTable->Hdr.Revision >= 0x20000) {
return gBootServices->CreateEventEx(
EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
UsbInt13ReadyToBootCallback, NULL,
&gEfiEventReadyToBootGuid,
ReadyToBootEvent);
}
DebugPrint(DEBUG_ERROR, "EFI1.1 can't support ReadyToBootEvent!");
AssertHandler("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiNotTiano.c", 185,
"((BOOLEAN)(0==1))");
return EFI_UNSUPPORTED;
}