/* 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++;
}
}
}
-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(
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,
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) {