From: Ani Sinha Date: Fri, 12 Jun 2026 06:40:47 +0000 (+0530) Subject: chid_match: match UEFI firmware hwid entry with the current smbios data X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f4f348c8eb51123b3fce2f79ae9e906943b3c9b;p=thirdparty%2Fsystemd.git chid_match: match UEFI firmware hwid entry with the current smbios data UEFI firmware type hwids must be matched against the current hardware first. This change implements that. Additionally, some extra validations on the hwids entries have also been added. --- diff --git a/src/boot/chid.c b/src/boot/chid.c index 6cb11e8b1c1..23bd60537fa 100644 --- a/src/boot/chid.c +++ b/src/boot/chid.c @@ -121,12 +121,35 @@ EFI_STATUS chid_match(const void *hwid_buffer, size_t hwid_length, uint32_t matc /* Count devices and check validity */ for (; (n_devices + 1) * sizeof(*devices) < hwid_length;) { + const Device *device = &devices[n_devices]; - if (devices[n_devices].descriptor == DEVICE_DESCRIPTOR_EOL) + if (device->descriptor == DEVICE_DESCRIPTOR_EOL) break; - if (!IN_SET(DEVICE_TYPE_FROM_DESCRIPTOR(devices[n_devices].descriptor), - DEVICE_TYPE_UEFI_FW, DEVICE_TYPE_DEVICETREE)) + + uint32_t device_type = DEVICE_TYPE_FROM_DESCRIPTOR(device->descriptor); + size_t name_off, off; + + if (!IN_SET(device_type, DEVICE_TYPE_UEFI_FW, DEVICE_TYPE_DEVICETREE)) return EFI_UNSUPPORTED; + + if (device_type == DEVICE_TYPE_DEVICETREE) { + off = device->devicetree.compatible_offset; + name_off = device->devicetree.name_offset; + } else if (device_type == DEVICE_TYPE_UEFI_FW) { + off = device->uefi_fw.fwid_offset; + name_off = device->uefi_fw.name_offset; + } else + assert_not_reached(); + + if (off >= hwid_length || name_off >= hwid_length) + return EFI_INVALID_PARAMETER; + + /* check for NULL termination */ + if (off && !memchr((const uint8_t *) hwid_buffer + off, 0, hwid_length - off)) + return EFI_INVALID_PARAMETER; + if (name_off && !memchr((const uint8_t *) hwid_buffer + name_off, 0, hwid_length - name_off)) + return EFI_INVALID_PARAMETER; + n_devices++; } diff --git a/src/boot/pe.c b/src/boot/pe.c index e96600ab05d..872cb9e6220 100644 --- a/src/boot/pe.c +++ b/src/boot/pe.c @@ -345,13 +345,14 @@ static void pe_locate_sections_internal( } } -static bool looking_for_dtbauto(const char *const section_names[]) { +static bool looking_for_dtbauto_or_efifw(const char *const section_names[]) { assert(section_names); for (size_t i = 0; section_names[i]; i++) - if (pe_section_name_equal(section_names[i], ".dtbauto")) + if (pe_section_name_equal(section_names[i], ".dtbauto") || + pe_section_name_equal(section_names[i], ".efifw")) return true; - return false; + return false; } static void pe_locate_sections( @@ -361,7 +362,7 @@ static void pe_locate_sections( size_t validate_base, PeSectionVector sections[]) { - if (!looking_for_dtbauto(section_names)) + if (!looking_for_dtbauto_or_efifw(section_names)) return pe_locate_sections_internal( section_table, n_section_table, @@ -377,40 +378,64 @@ static void pe_locate_sections( const void *hwids = NULL; const Device *device = NULL; - if (!firmware_devicetree_exists()) { - /* Find HWIDs table and search for the current device */ - static const char *const hwid_section_names[] = { ".hwids", NULL }; - PeSectionVector hwids_section[1] = {}; - - pe_locate_sections_internal( - section_table, - n_section_table, - hwid_section_names, - validate_base, - /* device_table= */ NULL, - /* device= */ NULL, - hwids_section); - - if (PE_SECTION_VECTOR_IS_SET(hwids_section)) { - hwids = (const uint8_t *) SIZE_TO_PTR(validate_base) + hwids_section[0].memory_offset; - - EFI_STATUS err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_DEVICETREE, &device); - if (err != EFI_SUCCESS) { + /* Find HWIDs table and search for the current device */ + static const char *const hwid_section_names[] = { ".hwids", NULL }; + PeSectionVector hwids_section[1] = {}; + + pe_locate_sections_internal( + section_table, + n_section_table, + hwid_section_names, + validate_base, + /* device_table= */ NULL, + /* device= */ NULL, + hwids_section); + + if (PE_SECTION_VECTOR_IS_SET(hwids_section)) { + hwids = (const uint8_t *) SIZE_TO_PTR(validate_base) + hwids_section[0].memory_offset; + EFI_STATUS err; + + if (!firmware_devicetree_exists()) { + err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_DEVICETREE, &device); + if (err == EFI_SUCCESS) + pe_locate_sections_internal( + section_table, + n_section_table, + section_names, + validate_base, + hwids, + device, + sections); + else log_full(err, err == EFI_NOT_FOUND ? LOG_DEBUG : LOG_ERR, "HWID matching failed, no DT blob will be selected: %m"); - hwids = NULL; - } } - } + err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_UEFI_FW, &device); + if (err == EFI_SUCCESS) + pe_locate_sections_internal( + section_table, + n_section_table, + section_names, + validate_base, + hwids, + device, + sections); + else { + log_full(err, err == EFI_NOT_FOUND ? LOG_DEBUG : LOG_ERR, + "No UEFI FW will be selected: %m"); + hwids = NULL; + device = NULL; + } + } return pe_locate_sections_internal( - section_table, - n_section_table, - section_names, - validate_base, - hwids, - device, - sections); + section_table, + n_section_table, + section_names, + validate_base, + hwids, + device, + sections); } static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) { diff --git a/src/boot/stub.c b/src/boot/stub.c index 712a82e7398..e69faca00b0 100644 --- a/src/boot/stub.c +++ b/src/boot/stub.c @@ -599,7 +599,7 @@ static EFI_STATUS load_addons( err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, sections); if (err != EFI_SUCCESS) { log_error_status(err, - "Unable to locate embedded .cmdline/.dtb/.dtbauto/.initrd/.ucode sections in %ls, ignoring: %m", + "Unable to locate embedded .cmdline/.dtb/.dtbauto/.efifw/.initrd/.ucode sections in %ls, ignoring: %m", items[i]); continue; }