Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions onnxruntime/core/platform/windows/device_discovery.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,29 @@ struct DriverInfo {
}
};

bool IsHexString(const std::wstring& str) {
for (const wchar_t& c : str) {
if (!((c >= L'0' && c <= L'9') || (c >= L'A' && c <= L'F') || (c >= L'a' && c <= L'f'))) {
return false;
}
}
return true;
}

// Converts a wide string ACPI (up to 4 characters) representing a hardware ID component from into a uint32_t.
// e.g., "QCOM" from "VEN_QCOM". The conversion is done in a little-endian manner, meaning the first character
// of the string becomes the least significant byte of the integer, and the fourth character
// becomes the most significant byte.
uint32_t AcpiWStringToUint32Id(const std::wstring& vendor_name) {
uint32_t vendor_id = 0;
for (size_t i = 0; i < 4 && i < vendor_name.size(); ++i) {
// For little-endian, place each character at the appropriate byte position
// First character goes into lowest byte, last character into highest byte
vendor_id |= static_cast<unsigned char>(vendor_name[i] & 0xFF) << (i * 8);
}
return vendor_id;
}

uint64_t GetDeviceKey(uint32_t vendor_id, uint32_t device_id) {
return (uint64_t(vendor_id) << 32) | device_id;
}
Expand Down Expand Up @@ -134,25 +157,35 @@ std::unordered_map<uint64_t, DeviceInfo> GetDeviceInfoSetupApi(const std::unorde
// PCI\VEN_xxxx&DEV_yyyy&...
// ACPI\VEN_xxxx&DEV_yyyy&... if we're lucky.
// ACPI values seem to be very inconsistent, so we check fairly carefully and always require a device id.
const auto get_id = [](const std::wstring& hardware_id, const std::wstring& prefix) -> uint32_t {
const auto get_id = [](bool is_pci, const std::wstring& hardware_id, const std::wstring& prefix) -> uint32_t {
if (auto idx = hardware_id.find(prefix); idx != std::wstring::npos) {
auto id = hardware_id.substr(idx + prefix.size(), 4);

if (id.size() == 4) {
return static_cast<uint32_t>(std::stoul(id, nullptr, 16));
if (is_pci || IsHexString(id)) {
// PCI entries have hex numbers. ACPI might.
return static_cast<uint32_t>(std::stoul(id, nullptr, 16));
} else {
// ACPI can have things like "VEN_QCOM". Fallback to using this conversion where the characters
// are converted in little-endian order.
return AcpiWStringToUint32Id(id);
}
}
}

return 0;
};

// Processor ID should come from CPUID mapping.
const bool is_pci = std::wstring(buffer, 3) == std::wstring(L"PCI");

if (guid == GUID_DEVCLASS_PROCESSOR) {
// Processor ID should come from CPUID mapping.
vendor_id = CPUIDInfo::GetCPUIDInfo().GetCPUVendorId();
} else {
vendor_id = get_id(buffer, L"VEN_");
vendor_id = get_id(is_pci, buffer, L"VEN_");
}

device_id = get_id(buffer, L"DEV_");
device_id = get_id(is_pci, buffer, L"DEV_");

// Won't always have a vendor id from an ACPI entry. ACPI is not defined for this purpose.
if (vendor_id == 0 && device_id == 0) {
Expand Down
Loading