UEFI程序如何读取实际USB端口数?使用GetCapability获额外端口
读取UEFI环境下实际USB端口数量的实现方法
你遇到的问题是因为GetCapability方法返回的是USB控制器硬件支持的最大端口数,其中包含了未物理部署的虚端口,并非实际存在的物理端口数量。要获取真实的物理端口数,需要遍历每个端口并检查其物理存在状态。
核心实现思路
通过USB控制器协议提供的GetPortStatus接口,逐个检查每个端口的PortExists状态位——该位为TRUE时表示此端口是物理存在的。
具体实现步骤
- 获取系统中的USB控制器句柄(可通过
LocateHandleBuffer枚举所有支持USB HC协议的句柄) - 对每个控制器句柄,获取对应的USB协议(兼容USB 1.1和USB 2.0版本)
- 调用
GetCapability获取控制器支持的最大端口数 - 遍历每个端口,调用
GetPortStatus检查PortExists位,统计物理存在的端口数量
示例代码
#include <Uefi.h> #include <Protocol/UsbHc.h> #include <Protocol/Usb2Hc.h> UINTN GetPhysicalUsbPortCount(EFI_HANDLE UsbHcHandle) { EFI_STATUS Status; UINTN PortCount = 0; EFI_USB_HC_CAPABILITY HcCapability; EFI_USB_PORT_STATUS PortStatus; // 优先尝试获取USB 2.0控制器协议 EFI_USB2_HC_PROTOCOL *Usb2Hc = NULL; Status = gBS->HandleProtocol(UsbHcHandle, &gEfiUsb2HcProtocolGuid, (VOID**)&Usb2Hc); if (!EFI_ERROR(Status)) { Status = Usb2Hc->GetCapability(Usb2Hc, &HcCapability); if (EFI_ERROR(Status)) return 0; for (UINTN PortNum = 1; PortNum <= HcCapability.MaxPortNumber; PortNum++) { Status = Usb2Hc->GetPortStatus(Usb2Hc, PortNum, &PortStatus); if (!EFI_ERROR(Status) && PortStatus.PortExists) { PortCount++; } } return PortCount; } // 兼容USB 1.1控制器协议 EFI_USB_HC_PROTOCOL *UsbHc = NULL; Status = gBS->HandleProtocol(UsbHcHandle, &gEfiUsbHcProtocolGuid, (VOID**)&UsbHc); if (EFI_ERROR(Status)) return 0; Status = UsbHc->GetCapability(UsbHc, &HcCapability); if (EFI_ERROR(Status)) return 0; for (UINTN PortNum = 1; PortNum <= HcCapability.MaxPortNumber; PortNum++) { Status = UsbHc->GetPortStatus(UsbHc, PortNum, &PortStatus); if (!EFI_ERROR(Status) && PortStatus.PortExists) { PortCount++; } } return PortCount; } // 枚举所有USB控制器并计算总端口数 UINTN GetTotalPhysicalUsbPorts() { EFI_HANDLE *UsbHcHandles = NULL; UINTN HandleCount = 0; EFI_STATUS Status; UINTN TotalPorts = 0; // 枚举所有支持USB HC协议的控制器句柄 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiUsbHcProtocolGuid, NULL, &HandleCount, &UsbHcHandles); if (!EFI_ERROR(Status)) { for (UINTN i = 0; i < HandleCount; i++) { TotalPorts += GetPhysicalUsbPortCount(UsbHcHandles[i]); } gBS->FreePool(UsbHcHandles); } // 补充枚举USB 2.0控制器(部分设备可能仅注册此协议) Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiUsb2HcProtocolGuid, NULL, &HandleCount, &UsbHcHandles); if (!EFI_ERROR(Status)) { for (UINTN i = 0; i < HandleCount; i++) { TotalPorts += GetPhysicalUsbPortCount(UsbHcHandles[i]); } gBS->FreePool(UsbHcHandles); } return TotalPorts; }
关键注意事项
- 端口存在判断:必须依赖
PortExists位,而非PortConnectStatus(后者仅表示是否有设备连接)或PortEnabledStatus(后者表示端口是否启用) - 协议兼容性:需同时处理USB 1.1和USB 2.0控制器协议,避免遗漏设备
- 控制器初始化:调用上述函数前,确保USB控制器已通过
Initialize接口完成初始化,否则可能无法正确获取端口状态
内容的提问来源于stack exchange,提问作者yiii
相关产品推荐
相关产品推荐

