From: Michael Brown Date: Wed, 21 May 2025 13:26:56 +0000 (+0100) Subject: [fdt] Allow an initrd to be specified when creating a device tree X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=9bc559850c53eb630f9bb1089c98bae1d776d3d8;p=thirdparty%2Fipxe.git [fdt] Allow an initrd to be specified when creating a device tree Allow an initrd location to be specified in our constructed device tree via the "linux,initrd-start" and "linux,initrd-end" properties. Signed-off-by: Michael Brown --- diff --git a/src/core/fdt.c b/src/core/fdt.c index d20c63c31..c8ae4d949 100644 --- a/src/core/fdt.c +++ b/src/core/fdt.c @@ -1055,18 +1055,17 @@ static int fdt_ensure_child ( struct fdt *fdt, unsigned int offset, } /** - * Ensure property exists with specified value + * Set property value * * @v fdt Device tree * @v offset Starting node offset * @v name Property name - * @v data Property data + * @v data Property data, or NULL to delete property * @v len Length of property data * @ret rc Return status code */ -static int fdt_ensure_property ( struct fdt *fdt, unsigned int offset, - const char *name, const void *data, - size_t len ) { +static int fdt_set ( struct fdt *fdt, unsigned int offset, const char *name, + const void *data, size_t len ) { struct fdt_descriptor desc; struct { fdt_token_t token; @@ -1112,6 +1111,10 @@ static int fdt_ensure_property ( struct fdt *fdt, unsigned int offset, insert = ( sizeof ( *hdr ) + len ); } + /* Leave property erased if applicable */ + if ( ! data ) + return 0; + /* Insert space */ if ( ( rc = fdt_insert_nop ( fdt, desc.offset, insert ) ) != 0 ) return rc; @@ -1166,10 +1169,15 @@ static int fdt_urealloc ( struct fdt *fdt, size_t len ) { * * @v fdt Device tree * @v cmdline Command line, or NULL + * @v initrd Initial ramdisk address (or 0 for no initrd) + * @v initrd_len Initial ramdisk length (or 0 for no initrd) * @ret rc Return status code */ -static int fdt_bootargs ( struct fdt *fdt, const char *cmdline ) { +static int fdt_bootargs ( struct fdt *fdt, const char *cmdline, + physaddr_t initrd, size_t initrd_len ) { unsigned int chosen; + physaddr_t addr; + const void *data; size_t len; int rc; @@ -1177,14 +1185,25 @@ static int fdt_bootargs ( struct fdt *fdt, const char *cmdline ) { if ( ( rc = fdt_ensure_child ( fdt, 0, "chosen", &chosen ) ) != 0 ) return rc; - /* Use empty command line if none specified */ - if ( ! cmdline ) - cmdline = ""; + /* Set or clear "bootargs" property */ + len = ( cmdline ? ( strlen ( cmdline ) + 1 /* NUL */ ) : 0 ); + if ( ( rc = fdt_set ( fdt, chosen, "bootargs", cmdline, len ) ) != 0 ) + return rc; - /* Ensure "bootargs" property exists */ - len = ( strlen ( cmdline ) + 1 /* NUL */ ); - if ( ( rc = fdt_ensure_property ( fdt, chosen, "bootargs", cmdline, - len ) ) != 0 ) + /* Set or clear initrd properties */ + data = ( initrd_len ? &addr : NULL ); + len = ( initrd_len ? sizeof ( addr ) : 0 ); + addr = initrd; + addr = ( ( sizeof ( addr ) == sizeof ( uint64_t ) ) ? + cpu_to_be64 ( addr ) : cpu_to_be32 ( addr ) ); + if ( ( rc = fdt_set ( fdt, chosen, "linux,initrd-start", data, + len ) ) != 0 ) + return rc; + addr = ( initrd + initrd_len ); + addr = ( ( sizeof ( addr ) == sizeof ( uint64_t ) ) ? + cpu_to_be64 ( addr ) : cpu_to_be32 ( addr ) ); + if ( ( rc = fdt_set ( fdt, chosen, "linux,initrd-end", data, + len ) ) != 0 ) return rc; return 0; @@ -1195,9 +1214,12 @@ static int fdt_bootargs ( struct fdt *fdt, const char *cmdline ) { * * @v hdr Device tree header to fill in (may be set to NULL) * @v cmdline Command line, or NULL + * @v initrd Initial ramdisk address (or 0 for no initrd) + * @v initrd_len Initial ramdisk length (or 0 for no initrd) * @ret rc Return status code */ -int fdt_create ( struct fdt_header **hdr, const char *cmdline ) { +int fdt_create ( struct fdt_header **hdr, const char *cmdline, + physaddr_t initrd, size_t initrd_len ) { struct image *image; struct fdt fdt; void *copy; @@ -1228,7 +1250,7 @@ int fdt_create ( struct fdt_header **hdr, const char *cmdline ) { fdt.realloc = fdt_urealloc; /* Populate boot arguments */ - if ( ( rc = fdt_bootargs ( &fdt, cmdline ) ) != 0 ) + if ( ( rc = fdt_bootargs ( &fdt, cmdline, initrd, initrd_len ) ) != 0 ) goto err_bootargs; no_fdt: diff --git a/src/image/lkrn.c b/src/image/lkrn.c index f8929f3b3..4f04c3ff6 100644 --- a/src/image/lkrn.c +++ b/src/image/lkrn.c @@ -153,7 +153,7 @@ static int lkrn_fdt ( struct image *image, struct lkrn_context *ctx ) { int rc; /* Build device tree (which may change system memory map) */ - if ( ( rc = fdt_create ( &fdt, image->cmdline ) ) != 0 ) + if ( ( rc = fdt_create ( &fdt, image->cmdline, 0, 0 ) ) != 0 ) goto err_create; len = be32_to_cpu ( fdt->totalsize ); diff --git a/src/include/ipxe/fdt.h b/src/include/ipxe/fdt.h index 45ae0f92b..461b09632 100644 --- a/src/include/ipxe/fdt.h +++ b/src/include/ipxe/fdt.h @@ -199,7 +199,8 @@ extern int fdt_mac ( struct fdt *fdt, unsigned int offset, struct net_device *netdev ); extern int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ); -extern int fdt_create ( struct fdt_header **hdr, const char *cmdline ); +extern int fdt_create ( struct fdt_header **hdr, const char *cmdline, + physaddr_t initrd, size_t initrd_len ); extern void fdt_remove ( struct fdt_header *hdr ); #endif /* _IPXE_FDT_H */ diff --git a/src/interface/efi/efi_fdt.c b/src/interface/efi/efi_fdt.c index 1e0d4b8b7..3a90fd7ce 100644 --- a/src/interface/efi/efi_fdt.c +++ b/src/interface/efi/efi_fdt.c @@ -114,7 +114,7 @@ int efi_fdt_install ( const char *cmdline ) { int rc; /* Create device tree */ - if ( ( rc = fdt_create ( &efi_fdt_installed, cmdline ) ) != 0 ) { + if ( ( rc = fdt_create ( &efi_fdt_installed, cmdline, 0, 0 ) ) != 0 ) { DBGC ( &efi_fdt, "EFI_FDT could not install: %s\n", strerror ( rc ) ); goto err_create;