]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fdt] Allow an initrd to be specified when creating a device tree
authorMichael Brown <mcb30@ipxe.org>
Wed, 21 May 2025 13:26:56 +0000 (14:26 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 21 May 2025 13:31:18 +0000 (14:31 +0100)
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>
src/core/fdt.c
src/image/lkrn.c
src/include/ipxe/fdt.h
src/interface/efi/efi_fdt.c

index d20c63c31500d884e2f9546bb0276eaf746c958a..c8ae4d94915491af77cf66b6208ec74f6664ea11 100644 (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 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:
index f8929f3b393b088a835fb34cc30e2e1a58037da8..4f04c3ff6784a0e96edd3bca2d480a452a0887f5 100644 (file)
@@ -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 );
 
index 45ae0f92b3e03a6fdfc3e1766747ab56f547d259..461b09632624efbc2b5d637637d257dd16300055 100644 (file)
@@ -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 */
index 1e0d4b8b7649a45202798f1726b1bb7f93d6d11f..3a90fd7ce4cbb4f4c8e3196b24e720b452e5d3a0 100644 (file)
@@ -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;