lib/misc: Measure device tree blob before fdt_open_into resizes it
diff --git a/common/lib/misc.c b/common/lib/misc.c
index 1173e70d..de7f50a0 100644
--- a/common/lib/misc.c
+++ b/common/lib/misc.c
@@ -10,6 +10,7 @@
#include <lib/uri.h>
#include <lib/bli.h>
#include <lib/rng_seed.h>
+#include <lib/tpm.h>
#include <fs/file.h>
#include <mm/pmm.h>
#include <libfdt.h>
@@ -117,7 +118,8 @@ size_t get_trailing_zeros(uint64_t val) {
return 64;
}
-void *get_device_tree_blob(const char *config, size_t extra_size) {
+void *get_device_tree_blob(const char *config, size_t extra_size,
+ const char *measure_label) {
int ret;
size_t size = 0;
@@ -152,6 +154,13 @@ void *get_device_tree_blob(const char *config, size_t extra_size) {
panic(soft_panic, "dtb: Invalid device tree blob at `%#`: '%s'", dtb_path, fdt_strerror(ret));
}
+#if defined (UEFI)
+ if (measure_label != NULL) {
+ tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
+ dtb, size, measure_label);
+ }
+#endif
+
printv("dtb: loaded dtb at %p from file `%#`\n", dtb, dtb_path);
}
}
@@ -164,6 +173,10 @@ void *get_device_tree_blob(const char *config, size_t extra_size) {
if (memcmp(&cur_table->VendorGuid, &dtb_guid, sizeof(EFI_GUID)))
continue;
size = fdt_totalsize(cur_table->VendorTable);
+ if (measure_label != NULL) {
+ tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
+ cur_table->VendorTable, size, measure_label);
+ }
dtb = ext_mem_alloc(size);
ret = fdt_open_into(cur_table->VendorTable, dtb, size);
if (ret < 0) {
@@ -173,6 +186,8 @@ void *get_device_tree_blob(const char *config, size_t extra_size) {
break;
}
}
+#else
+ (void)measure_label;
#endif
if (extra_size == 0) {
diff --git a/common/lib/misc.h b/common/lib/misc.h
index 5de32a92..394449dc 100644
--- a/common/lib/misc.h
+++ b/common/lib/misc.h
@@ -30,7 +30,8 @@ bool efi_exit_boot_services(void);
bool is_efi_serial_present(void);
#endif
-void *get_device_tree_blob(const char *config, size_t extra_size);
+void *get_device_tree_blob(const char *config, size_t extra_size,
+ const char *measure_label);
extern struct volume *boot_volume;
diff --git a/common/protos/limine.c b/common/protos/limine.c
index b1a6b212..d13213c1 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -1180,16 +1180,9 @@ FEAT_START
break; // next feature
}
- void *dtb = get_device_tree_blob(config, 0);
+ void *dtb = get_device_tree_blob(config, 0, "Limine DTB");
if (dtb) {
-#if defined (UEFI)
- // Measure the device tree as loaded, before applying our memory-node
- // fixups below, so the resulting PCR is stable across boots.
- tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
- dtb, fdt_totalsize(dtb), "Limine DTB");
-#endif
-
// Delete all /memory@... nodes.
// The executable must use the given UEFI memory map instead.
while (true) {
diff --git a/common/protos/linux_risc.c b/common/protos/linux_risc.c
index bdb8f07e..9b15e023 100644
--- a/common/protos/linux_risc.c
+++ b/common/protos/linux_risc.c
@@ -172,11 +172,6 @@ static void prepare_device_tree_blob(struct boot_param *p) {
void *dtb = p->dtb;
int ret;
- // Measure the device tree as loaded, before applying our /chosen and
- // memory-node fixups, so the resulting PCR is stable across boots.
- tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
- dtb, fdt_totalsize(dtb), "Linux DTB");
-
// Delete all /memory@... nodes. Linux will use the given UEFI memory map
// instead.
while (true) {
@@ -474,7 +469,7 @@ noreturn void linux_load(char *config, char *cmdline) {
struct boot_param p;
memset(&p, 0, sizeof(p));
p.cmdline = cmdline;
- p.dtb = get_device_tree_blob(config, 0x1000);
+ p.dtb = get_device_tree_blob(config, 0x1000, "Linux DTB");
if (cmdline != NULL) {
tpm_measure(TPM_PCR_BOOT_AUTH, TPM_EV_IPL,
diff --git a/common/sys/cpu_riscv.c b/common/sys/cpu_riscv.c
index 0330b45d..70210622 100644
--- a/common/sys/cpu_riscv.c
+++ b/common/sys/cpu_riscv.c
@@ -313,7 +313,7 @@ void init_riscv(const char *config) {
if (!prioritise_dtb && acpi_get_rsdp()) {
init_riscv_acpi();
} else {
- riscv_fdt = get_device_tree_blob(config, 0);
+ riscv_fdt = get_device_tree_blob(config, 0, NULL);
if (riscv_fdt != NULL) {
init_riscv_fdt(riscv_fdt);
} else {
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 7393218b..feb68c87 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -798,7 +798,7 @@ struct limine_mp_info *init_smp(const char *config,
return info;
// No RSDP means no ACPI, try device trees in that case.
- void *dtb = get_device_tree_blob(config, 0);
+ void *dtb = get_device_tree_blob(config, 0, NULL);
if (dtb) {
info = try_dtb_smp(dtb,
cpu_count, bsp_mpidr, pagemap,
@@ -1212,7 +1212,7 @@ struct limine_mp_info *init_smp(size_t *cpu_count, uint32_t *bsp_phys_id,
if (acpi_get_rsdp() && (info = try_acpi_smp(cpu_count, bsp_phys_id, pagemap, hhdm_offset)))
return info;
- void *dtb = get_device_tree_blob(NULL, 0);
+ void *dtb = get_device_tree_blob(NULL, 0, NULL);
if (dtb) {
info = try_dtb_smp(dtb, cpu_count, bsp_phys_id, pagemap, hhdm_offset);
pmm_free(dtb, fdt_totalsize(dtb));
