mirror of
https://github.com/ipxe/ipxe
synced 2026-02-05 08:53:52 +03:00
[efi] Install a device tree for the booted OS, if available
If we have a device tree available (e.g. because the user has explicitly downloaded a device tree using the "fdt" command), then provide it to the booted operating system as an EFI configuration table. Since x86 does not typically use device trees, we create weak symbols for efi_fdt_install() and efi_fdt_uninstall() to avoid dragging FDT support into all x86 UEFI binaries. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -24,9 +24,12 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <string.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/fdt.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/efi_table.h>
|
||||
#include <ipxe/efi/efi_fdt.h>
|
||||
#include <ipxe/efi/Guid/Fdt.h>
|
||||
|
||||
/** @file
|
||||
@@ -76,3 +79,82 @@ static void efi_fdt_init ( void ) {
|
||||
struct init_fn efi_fdt_init_fn __init_fn ( INIT_EARLY ) = {
|
||||
.initialise = efi_fdt_init,
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine length of EFI Flattened Device Tree
|
||||
*
|
||||
* @v data Configuration table data (presumed valid)
|
||||
* @ret len Length of table
|
||||
*/
|
||||
static size_t efi_fdt_len ( const void *data ) {
|
||||
const struct fdt_header *hdr = data;
|
||||
|
||||
return be32_to_cpu ( hdr->totalsize );
|
||||
}
|
||||
|
||||
/** EFI Flattened Device Tree table type */
|
||||
static struct efi_table efi_fdt_table = {
|
||||
.guid = &efi_fdt_table_guid,
|
||||
.len = efi_fdt_len,
|
||||
};
|
||||
|
||||
/** EFI Flattened Device Tree table backup */
|
||||
static void *efi_fdt_backup;
|
||||
|
||||
/** EFI Flattened Device Tree installed table */
|
||||
static struct fdt_header *efi_fdt_installed;
|
||||
|
||||
/**
|
||||
* Install EFI Flattened Device Tree table
|
||||
*
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int efi_fdt_install ( void ) {
|
||||
int rc;
|
||||
|
||||
/* Create device tree */
|
||||
if ( ( rc = fdt_create ( &efi_fdt_installed ) ) != 0 ) {
|
||||
DBGC ( &efi_fdt, "EFI_FDT could not install: %s\n",
|
||||
strerror ( rc ) );
|
||||
goto err_create;
|
||||
}
|
||||
|
||||
/* Install table */
|
||||
if ( ( rc = efi_install_table ( &efi_fdt_table, efi_fdt_installed,
|
||||
&efi_fdt_backup ) ) != 0 ) {
|
||||
DBGC ( &efi_fdt, "EFIFDT could not install: %s\n",
|
||||
strerror ( rc ) );
|
||||
goto err_install;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
efi_uninstall_table ( &efi_fdt_table, &efi_fdt_backup );
|
||||
err_install:
|
||||
fdt_remove ( efi_fdt_installed );
|
||||
err_create:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall EFI Flattened Device Tree table
|
||||
*
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int efi_fdt_uninstall ( void ) {
|
||||
int rc;
|
||||
|
||||
/* Uninstall table */
|
||||
if ( ( rc = efi_uninstall_table ( &efi_fdt_table,
|
||||
&efi_fdt_backup ) ) != 0 ) {
|
||||
DBGC ( &efi_fdt, "EFIFDT could not %sinstall: %s\n",
|
||||
( efi_fdt_backup ? "re" : "un" ), strerror ( rc ) );
|
||||
/* Leak memory: there is nothing else we can do */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Remove table */
|
||||
fdt_remove ( efi_fdt_installed );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user