diff --git a/src/boot/chid.c b/src/boot/chid.c index 6cb11e8b1c..23bd60537f 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 e96600ab05..872cb9e622 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] = {}; + /* 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); + 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; + 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; - EFI_STATUS err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_DEVICETREE, &device); - if (err != EFI_SUCCESS) { + 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 712a82e739..e69faca00b 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; }