[efi] Create a copy of the system flattened device tree, if present

EFI configuration tables may be freed at any time, and there is no way
to be notified when the table becomes invalidated.  Create a copy of
the system flattened device tree (if present), so that we do not risk
being left with an invalid pointer.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-03-28 14:10:55 +00:00
parent 3860313dd5
commit 666929e311
3 changed files with 15 additions and 5 deletions

View File

@@ -456,8 +456,7 @@ int fdt_mac ( struct fdt *fdt, unsigned int offset,
* @v max_len Maximum device tree length * @v max_len Maximum device tree length
* @ret rc Return status code * @ret rc Return status code
*/ */
int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr, int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
size_t max_len ) {
const uint8_t *end; const uint8_t *end;
/* Sanity check */ /* Sanity check */

View File

@@ -78,9 +78,9 @@ struct fdt {
/** Tree data */ /** Tree data */
union { union {
/** Tree header */ /** Tree header */
const struct fdt_header *hdr; struct fdt_header *hdr;
/** Raw data */ /** Raw data */
const void *raw; void *raw;
}; };
/** Length of tree */ /** Length of tree */
size_t len; size_t len;
@@ -107,7 +107,7 @@ extern int fdt_u64 ( struct fdt *fdt, unsigned int offset, const char *name,
uint64_t *value ); uint64_t *value );
extern int fdt_mac ( struct fdt *fdt, unsigned int offset, extern int fdt_mac ( struct fdt *fdt, unsigned int offset,
struct net_device *netdev ); struct net_device *netdev );
extern int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr, extern int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr,
size_t max_len ); size_t max_len );
#endif /* _IPXE_FDT_H */ #endif /* _IPXE_FDT_H */

View File

@@ -44,6 +44,8 @@ EFI_USE_TABLE ( FDT_TABLE, &efi_fdt, 0 );
* *
*/ */
static void efi_fdt_init ( void ) { static void efi_fdt_init ( void ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc;
int rc; int rc;
/* Do nothing if no configuration table is present */ /* Do nothing if no configuration table is present */
@@ -59,6 +61,15 @@ static void efi_fdt_init ( void ) {
strerror ( rc ) ); strerror ( rc ) );
return; return;
} }
/* Create copy, since table may be removed at any time */
if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, sysfdt.len,
&sysfdt.raw ) ) != 0 ) {
DBGC ( &efi_fdt, "EFIFDT could not create copy\n" );
sysfdt.len = 0;
return;
}
memcpy ( sysfdt.raw, efi_fdt, sysfdt.len );
} }
/** EFI Flattened Device Tree initialisation function */ /** EFI Flattened Device Tree initialisation function */