[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 <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-21 14:26:56 +01:00
parent c1cd54ad74
commit 9bc559850c
4 changed files with 41 additions and 18 deletions

View File

@@ -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 fdt Device tree
* @v offset Starting node offset * @v offset Starting node offset
* @v name Property name * @v name Property name
* @v data Property data * @v data Property data, or NULL to delete property
* @v len Length of property data * @v len Length of property data
* @ret rc Return status code * @ret rc Return status code
*/ */
static int fdt_ensure_property ( struct fdt *fdt, unsigned int offset, static int fdt_set ( struct fdt *fdt, unsigned int offset, const char *name,
const char *name, const void *data, const void *data, size_t len ) {
size_t len ) {
struct fdt_descriptor desc; struct fdt_descriptor desc;
struct { struct {
fdt_token_t token; fdt_token_t token;
@@ -1112,6 +1111,10 @@ static int fdt_ensure_property ( struct fdt *fdt, unsigned int offset,
insert = ( sizeof ( *hdr ) + len ); insert = ( sizeof ( *hdr ) + len );
} }
/* Leave property erased if applicable */
if ( ! data )
return 0;
/* Insert space */ /* Insert space */
if ( ( rc = fdt_insert_nop ( fdt, desc.offset, insert ) ) != 0 ) if ( ( rc = fdt_insert_nop ( fdt, desc.offset, insert ) ) != 0 )
return rc; return rc;
@@ -1166,10 +1169,15 @@ static int fdt_urealloc ( struct fdt *fdt, size_t len ) {
* *
* @v fdt Device tree * @v fdt Device tree
* @v cmdline Command line, or 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 * @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; unsigned int chosen;
physaddr_t addr;
const void *data;
size_t len; size_t len;
int rc; 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 ) if ( ( rc = fdt_ensure_child ( fdt, 0, "chosen", &chosen ) ) != 0 )
return rc; return rc;
/* Use empty command line if none specified */ /* Set or clear "bootargs" property */
if ( ! cmdline ) len = ( cmdline ? ( strlen ( cmdline ) + 1 /* NUL */ ) : 0 );
cmdline = ""; if ( ( rc = fdt_set ( fdt, chosen, "bootargs", cmdline, len ) ) != 0 )
return rc;
/* Ensure "bootargs" property exists */ /* Set or clear initrd properties */
len = ( strlen ( cmdline ) + 1 /* NUL */ ); data = ( initrd_len ? &addr : NULL );
if ( ( rc = fdt_ensure_property ( fdt, chosen, "bootargs", cmdline, len = ( initrd_len ? sizeof ( addr ) : 0 );
len ) ) != 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 rc;
return 0; 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 hdr Device tree header to fill in (may be set to NULL)
* @v cmdline Command line, or 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 * @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 image *image;
struct fdt fdt; struct fdt fdt;
void *copy; void *copy;
@@ -1228,7 +1250,7 @@ int fdt_create ( struct fdt_header **hdr, const char *cmdline ) {
fdt.realloc = fdt_urealloc; fdt.realloc = fdt_urealloc;
/* Populate boot arguments */ /* Populate boot arguments */
if ( ( rc = fdt_bootargs ( &fdt, cmdline ) ) != 0 ) if ( ( rc = fdt_bootargs ( &fdt, cmdline, initrd, initrd_len ) ) != 0 )
goto err_bootargs; goto err_bootargs;
no_fdt: no_fdt:

View File

@@ -153,7 +153,7 @@ static int lkrn_fdt ( struct image *image, struct lkrn_context *ctx ) {
int rc; int rc;
/* Build device tree (which may change system memory map) */ /* 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; goto err_create;
len = be32_to_cpu ( fdt->totalsize ); len = be32_to_cpu ( fdt->totalsize );

View File

@@ -199,7 +199,8 @@ 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, struct fdt_header *hdr, extern int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr,
size_t max_len ); 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 ); extern void fdt_remove ( struct fdt_header *hdr );
#endif /* _IPXE_FDT_H */ #endif /* _IPXE_FDT_H */

View File

@@ -114,7 +114,7 @@ int efi_fdt_install ( const char *cmdline ) {
int rc; int rc;
/* Create device tree */ /* 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", DBGC ( &efi_fdt, "EFI_FDT could not install: %s\n",
strerror ( rc ) ); strerror ( rc ) );
goto err_create; goto err_create;