Newer
Older
AMI-Aptio-BIOS-Reversed / Uhcd / Uhcd.c
@Ajax Dong Ajax Dong 2 days ago 14 KB Init
/**
 *Uhcd.c - USB Host Controller Driver (xHCI) for Lenovo HR650X
 *
 *Source: AmiModulePkg/Usb/Uhcd.c (and related: UsbMisc.c, AmiUsbHc.c)
 *
 *This module implements an AMI-proprietary USB Host Controller Driver
 *that manages xHCI controllers on the Lenovo HR650X platform. It handles:
 *
 * - Driver entry and UHCD protocol installation
 * - xHCI controller enumeration, initialization, and register access
 * - USB device tree management (add/remove/update devices)
 * - Control, bulk, interrupt, and isochronous transfer scheduling
 * - Root hub emulation (port status, feature control)
 * - Timer-based polling for interrupt transfers
 * - Memory pool management for RT USB data structures
 *
 *The driver defines a large global structure (gUsbData, ~30KB) allocated
 *from runtime memory pool. It also defines a private vtable (gUsbCallbacks)
 *for internal helper dispatch.
 */

#include "Uhcd.h"

/*===========================================================================
 *Global variables
 *===========================================================================*/

USB_DATA *gUsbData = NULL; /*Main driver context (qword_11A90) */
USB_HC_CALLBACKS *gUsbCallbacks = NULL; /*Private vtable (qword_11A38) */
EFI_CPU_IO2_PROTOCOL *gCpuIo = NULL; /*SystemTable->BootServices derived */
EFI_BOOT_SERVICES *gBootServices = NULL; /*gBS */
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL; /*gRT */
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gSystemTable = NULL;

/*===========================================================================
 *Utility functions (memory, string, compare)
 *===========================================================================*/

/**
 *MemCopy - Overlapping-safe memory copy.
 *
 *Equivalent to UefiLib CopyMem with overlap handling.
 *When src < dst and ranges overlap, copies from end to start.
 *Otherwise, uses qmemcpy (fast 8-byte aligned copy + trailing bytes).
 *
 * @param dst Destination buffer
 * @param src Source buffer
 * @param count Number of bytes to copy
 *
 * @return dst
 */
void *MemCopy (
 void *dst,
 const void *src,
 UINTN count
 )
{
 return memmove(dst, src, count);
}

/**
 *MemSet - Fill memory with a constant byte.
 *
 * @param buf Buffer to fill
 * @param count Number of bytes
 * @param value Fill byte value
 *
 * @return buf
 */
void *MemSet (
 void *buf,
 UINTN count,
 UINT8 value
 )
{
 return memset(buf, value, count);
}

/**
 *MemCmp - Compare two memory buffers.
 *
 * @param a1 First buffer
 * @param a2 Second buffer
 * @param len Number of bytes to compare
 *
 * @return 0 if equal, nonzero otherwise
 */
INTN MemCmp (
 const VOID *a1,
 const VOID *a2,
 UINTN len
 )
{
 return memcmp(a1, a2, len);
}

/*===========================================================================
 *USB memory pool management
 *===========================================================================*/

/**
 *UsbRtAllocPool - Allocate from USB runtime memory pool.
 *
 *Uses a pre-allocated RT memory region (gBS->AllocatePages of
 *EfiRuntimeServicesData) and sub-allocates entries aligned to
 * @c Alignment.
 *
 * @param Size Requested allocation size
 * @param Alignment Required alignment (must be power of 2)
 *
 * @return Allocated virtual address, or NULL on failure
 */
VOID *UsbRtAllocPool (
 UINT32 Size,
 UINT16 Alignment
 )
{
 /*See decompiled sub_2AB0 */
 return NULL;
}

/**
 *UsbRtAllocPages - Allocate aligned physical pages from system memory.
 *
 *Uses gBS->AllocatePages with AllocateMaxAddress to obtain physical
 *pages aligned to @c Alignment.
 *
 * @param CpuIo EFI_CPU_IO2_PROTOCOL instance
 * @param Pages Number of 4KB pages requested
 * @param Alignment Required alignment in bytes (power of 2)
 *
 * @return Physical address of allocated memory, or 0 on failure
 */
UINT64 UsbRtAllocPages (
 IN EFI_CPU_IO2_PROTOCOL *CpuIo,
 IN UINTN Pages,
 IN UINT64 Alignment
 )
{
 /*See decompiled sub_2C18 */
 return 0;
}

/*===========================================================================
 *xHCI controller enumeration and initialization
 *===========================================================================*/

/**
 *LocateAndInitXhciController - Find and initialize xHCI controllers.
 *
 *Scans the ACPI DSDT/SSDT for xHCI controller devices, opens PCI I/O
 *protocol, reads capability registers, resets the controller, and
 *prepares the operational register range.
 *
 * @param ImageHandle The driver's image handle
 * @param AcpiTable Pointer to DSDT/SSDT table
 *
 * @return EFI_STATUS
 */
EFI_STATUS LocateAndInitXhciController (
 EFI_HANDLE ImageHandle,
 VOID *AcpiTable
 )
{
 /*See decompiled sub_2634 */
 return EFI_UNSUPPORTED;
}

/**
 *XhciCapabilityProbe - Probe xHCI controller capabilities.
 *
 *Reads CAPLENGTH, HCSPARAMS1/2, HCCPARAMS1, DBOFF, RTSOFF,
 *and extended capabilities (USB2/USB3 support, legacy support, debug).
 *
 * @param MmioBase MMIO base address of the xHCI controller
 * @param Regs Output: filled-in register offsets
 *
 * @return EFI_STATUS
 */
EFI_STATUS XhciCapabilityProbe (
 UINT64 MmioBase,
 VOID *Regs
 )
{
 /*See decompiled sub_5718, sub_5AD0 */
 return EFI_UNSUPPORTED;
}

/*===========================================================================
 *USB device tree management
 *===========================================================================*/

/**
 *UsbBusInstallDevice - Install a new USB device in the device tree.
 */
EFI_STATUS UsbBusInstallDevice (
 UINT8 *DeviceData,
 VOID *ParentHub
 )
{
 /*See decompiled sub_7E98 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbBusUninstallDevice - Remove a USB device from the device tree.
 */
EFI_STATUS UsbBusUninstallDevice (
 UINT8 *DeviceData
 )
{
 /*See decompiled sub_8778 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbBusRemoveDeviceGroup - Remove all devices on a hub port.
 */
EFI_STATUS UsbBusRemoveDeviceGroup (
 VOID *HubNode,
 UINT8 Port
 )
{
 /*See decompiled sub_8A70 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcNodeTimerCheck - Periodic HC timer callback.
 */
VOID UsbHcNodeTimerCheck (
 VOID *HubNode
 )
{
 /*See decompiled sub_8C70 */
 return;
}

/*===========================================================================
 *USB transfer scheduling
 *===========================================================================*/

/**
 *UsbHcControlTransfer - Execute a USB control transfer.
 */
EFI_STATUS UsbHcControlTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndpointAddress,
 IN VOID *Request,
 IN UINTN RequestLen,
 IN EFI_USB_DEVICE_REQUEST *UsbRequest,
 IN UINT32 Timeout,
 OUT VOID *Data,
 IN OUT UINTN *DataLength,
 OUT UINT64 *TransferStatus
 )
{
 /*See decompiled sub_3FF0 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcBulkTransfer - Execute a USB bulk transfer.
 */
EFI_STATUS UsbHcBulkTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndPoint,
 IN UINT8 Direction,
 IN OUT VOID *Data,
 IN OUT UINTN *DataLength,
 IN UINTN Timeout,
 OUT UINT64 *TransferStatus
 )
{
 /*See decompiled sub_4274 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcAsyncInterruptTransfer - Set up or remove async interrupt xfer.
 */
EFI_STATUS UsbHcAsyncInterruptTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndPoint,
 IN BOOLEAN IsNewTransfer,
 IN UINTN PollingInterval,
 IN UINTN DataLength,
 IN VOID *CallBackFunction,
 IN VOID *Context
 )
{
 /*See decompiled sub_4720 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcSyncInterruptTransfer - Execute a synchronous interrupt xfer.
 */
EFI_STATUS UsbHcSyncInterruptTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndPoint,
 IN OUT VOID *Data,
 IN OUT UINTN *DataLength,
 IN UINTN Timeout,
 OUT UINT64 *TransferStatus
 )
{
 /*See decompiled sub_49A4 */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcIsochronousTransfer - Execute an isochronous transfer.
 */
EFI_STATUS UsbHcIsochronousTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndPoint,
 IN OUT VOID *Data,
 IN UINTN DataLength,
 OUT UINT64 *TransferStatus
 )
{
 /*See decompiled sub_50BC */
 return EFI_UNSUPPORTED;
}

/**
 *UsbHcAsyncIsochronousTransfer - Set up or remove async isochronous.
 */
EFI_STATUS UsbHcAsyncIsochronousTransfer (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 DeviceAddress,
 IN UINT8 EndPoint,
 IN VOID *CallBackFunction,
 IN VOID *Context
 )
{
 /*See decompiled sub_53E8 */
 return EFI_UNSUPPORTED;
}

/*===========================================================================
 *Root hub emulation
 *===========================================================================*/

EFI_STATUS UsbHcGetRootHubPortStatus (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 PortNumber,
 OUT UINT64 *PortStatus
 )
{
 /*See decompiled sub_3B1C, sub_3B68 */
 return EFI_UNSUPPORTED;
}

EFI_STATUS UsbHcSetRootHubPortFeature (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 PortNumber,
 IN EFI_USB_PORT_FEATURE Feature
 )
{
 /*See decompiled sub_3C7C */
 return EFI_UNSUPPORTED;
}

EFI_STATUS UsbHcClearRootHubPortFeature (
 IN USB_HC_PROTOCOL *This,
 IN UINT8 PortNumber,
 IN EFI_USB_PORT_FEATURE Feature
 )
{
 /*See decompiled sub_3CEC */
 return EFI_UNSUPPORTED;
}

EFI_STATUS UsbHcSetState (
 IN USB_HC_PROTOCOL *This,
 IN UINT32 State
 )
{
 /*See decompiled sub_3908 */
 return EFI_UNSUPPORTED;
}

/*===========================================================================
 *Device enumeration / descriptor helpers
 *===========================================================================*/

EFI_STATUS UsbBusLoadEndpointPolicy (
 UINT8 *DeviceData
 )
{
 /*See decompiled sub_674C, sub_6A7C */
 return EFI_UNSUPPORTED;
}

EFI_STATUS UsbBusConfigureEndpoints (
 UINT8 *DeviceData
 )
{
 /*See decompiled sub_6BC0 */
 return EFI_UNSUPPORTED;
}

EFI_STATUS UsbBusGetDeviceDescriptor (
 UINT8 *DeviceData,
 VOID *Desc
 )
{
 /*See decompiled sub_6384 */
 return EFI_UNSUPPORTED;
}

/*===========================================================================
 *Driver binding protocol
 *===========================================================================*/

EFI_STATUS EFIAPI UhcdDriverBindingSupported (
 IN EFI_DRIVER_BINDING_PROTOCOL *This,
 IN EFI_HANDLE Controller,
 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
 )
{
 /*See decompiled sub_2448 */
 return EFI_UNSUPPORTED;
}

EFI_STATUS EFIAPI UhcdDriverBindingStart (
 IN EFI_DRIVER_BINDING_PROTOCOL *This,
 IN EFI_HANDLE Controller,
 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
 )
{
 /*See decompiled sub_1290 */
 return EFI_UNSUPPORTED;
}

EFI_STATUS EFIAPI UhcdDriverBindingStop (
 IN EFI_DRIVER_BINDING_PROTOCOL *This,
 IN EFI_HANDLE Controller,
 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
 )
{
 /*See decompiled sub_1620 */
 return EFI_UNSUPPORTED;
}

EFI_STATUS EFIAPI UhcdDriverBindingStopChild (
 IN EFI_DRIVER_BINDING_PROTOCOL *This,
 IN EFI_HANDLE Controller,
 IN EFI_HANDLE ChildHandle
 )
{
 /*See decompiled sub_116C */
 return EFI_UNSUPPORTED;
}

/*===========================================================================
 *Driver entry point
 *===========================================================================*/

/**
 *UhcdDriverEntryPoint - Entry point for the UHCD driver.
 *
 *Performs:
 *1. Save ImageHandle, SystemTable, BootServices, RuntimeServices
 *2. Read UsbSupport variable before initialization
 *3. Allocate gUsbData (~30KB) and initialize all fields
 *4. Allocate gUsbCallbacks vtable with helper function pointers
 *5. Install USB_HC protocol interface (sub_52C as HC handler)
 *6. Register driver binding, install components, create timer events
 *7. Register USB bus, mass storage, HID, and keyboard class drivers
 *
 * @param ImageHandle The firmware-allocated handle for this image
 * @param SystemTable The UEFI system table
 *
 * @return EFI_STATUS
 */
EFI_STATUS EFIAPI UhcdDriverEntryPoint (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 EFI_STATUS Status;
 UINT32 VarSize;
 UINT8 UsbEnabled;

 //
 // Save global table pointers
 //
 if (gSystemTable == NULL) {
 gSystemTable = SystemTable;
 gBootServices = SystemTable->BootServices;
 gRuntimeServices = SystemTable->RuntimeServices;
 }

 //
 // Check firmware variable: UsbSupport must be enabled (=1)
 //
 VarSize = sizeof (UsbEnabled);
 Status = gRuntimeServices->GetVariable (
 L"UsbSupport",
 &gUsbSupportVarGuid,
 NULL,
 &VarSize,
 &UsbEnabled
 );
 if (EFI_ERROR (Status) || !(UsbEnabled & 1)) {
 return EFI_UNSUPPORTED;
 }

 //
 // Allocate main driver context (gUsbData)
 //
 gUsbData = AllocateRuntimePool (sizeof (USB_DATA));
 if (gUsbData == NULL) {
 return EFI_OUT_OF_RESOURCES;
 }
 ZeroMem (gUsbData, sizeof (USB_DATA));

 gUsbData->Signature = USB_DATA_SIGNATURE;
 gUsbData->Flags = USB_DATA_FLAG_INITIALIZED;

 //
 // Allocate device address map
 //
 gUsbData->DeviceAddressMap = ~(UINT64)0;

 //
 // Initialize timer list head (self-referencing)
 //
 InitializeListHead (&gUsbData->TimerListHead);
 gUsbData->TimerInterval = 100; /*100 ms */
 gUsbData->TimerMaxCount = 6;

 //
 // Allocate memory map via PciIo->AllocateBuffer
 //
 // ... see decompiled sub_678 ...

 //
 // Allocate gUsbCallbacks vtable and populate function pointers
 //
 gUsbCallbacks = AllocatePool (sizeof (USB_HC_CALLBACKS));
 if (gUsbCallbacks == NULL) {
 return EFI_OUT_OF_RESOURCES;
 }
 gUsbCallbacks->UsbData = gUsbData;
 gUsbCallbacks->DriverBinding = NULL; /*set during InstallProtocolInterface */
 gUsbCallbacks->GetCurrentDevice = UsbHcGetCurrentDevice;
 gUsbCallbacks->SetDeviceAddress = UsbHcSetDeviceAddress;
 gUsbCallbacks->ResetDevice = UsbHcResetDevice;
 gUsbCallbacks->GetPollingMap = UsbHcGetNullMap;
 gUsbCallbacks->GetBulkMap = UsbHcGetNullMap;
 gUsbCallbacks->GetControlMap = UsbHcGetNullMap;
 gUsbCallbacks->TimerCallback = UsbHcTimerCallback;
 gUsbCallbacks->StopController = UsbHcStopPolling;
 gUsbCallbacks->SkipDevice = UsbHcSkipDevice;
 gUsbCallbacks->LegacySupport = UsbHcLegacySupport;

 //
 // Install USB_HC protocol interface
 //
 // ... see InstallProtocolInterface(&ImageHandle, &gUhcdProtocolGuid, ...) ...

 //
 // Install USB_BUS protocol, UHCD timer event, etc.
 //

 DEBUG ((DEBUG_INFO, "AmiUsb Version: %d\n", *(UINT8*)gUsbData));
 DEBUG ((DEBUG_INFO,
 "AMIUHCD USB Init: data located at........... %x\n",
 gUsbData));
 DEBUG ((DEBUG_INFO, "Log address: %x\n", (UINT64)&gUsbData + 8));
 DEBUG ((DEBUG_INFO, "Memory map: %x\n", gUsbData->MemoryMapPhys));
 DEBUG ((DEBUG_INFO, "Device address map: %x\n", gUsbData->DeviceAddressMap));

 return Status;
}

/**
 *ModuleEntryPoint - PE/COFF entry point.
 *
 *Standard UEFI DXE driver entry. Saves global table pointers
 *and invokes UhcdDriverEntryPoint.
 *
 * @param ImageHandle Image handle
 * @param SystemTable System table
 *
 * @return EFI_STATUS
 */
EFI_STATUS EFIAPI ModuleEntryPoint (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 gImageHandle = ImageHandle;
 gSystemTable = SystemTable;
 gBootServices = SystemTable->BootServices;
 gRuntimeServices = SystemTable->RuntimeServices;

 return UhcdDriverEntryPoint (ImageHandle, SystemTable);
}