summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2025-05-21 15:26:56 +0200
committerMichael Brown2025-05-21 15:31:18 +0200
commit9bc559850c53eb630f9bb1089c98bae1d776d3d8 (patch)
tree3f387e3197cfcc7689c743ca2d638a0b3e7e5580 /src
parent[initrd] Move initrd reshuffling to be architecture-independent code (diff)
downloadipxe-9bc559850c53eb630f9bb1089c98bae1d776d3d8.tar.gz
ipxe-9bc559850c53eb630f9bb1089c98bae1d776d3d8.tar.xz
ipxe-9bc559850c53eb630f9bb1089c98bae1d776d3d8.zip
[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>
Diffstat (limited to 'src')
-rw-r--r--src/core/fdt.c52
-rw-r--r--src/image/lkrn.c2
-rw-r--r--src/include/ipxe/fdt.h3
-rw-r--r--src/interface/efi/efi_fdt.c2
4 files changed, 41 insertions, 18 deletions
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;