diff options
author | Michael Brown <mcb30@ipxe.org> | 2021-05-21 14:27:27 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2021-05-21 20:18:50 +0100 |
commit | e5f02551735922eb235388bff08249a6f31ded3d (patch) | |
tree | 30d7136dfb8e477ce1b8ca27f2a4b5c2777d721b /src | |
parent | ef9953b7122937dc12762e9f5ce797ba6859a24e (diff) | |
download | ipxe-e5f02551735922eb235388bff08249a6f31ded3d.zip ipxe-e5f02551735922eb235388bff08249a6f31ded3d.tar.gz ipxe-e5f02551735922eb235388bff08249a6f31ded3d.tar.bz2 |
[efi] Provide an "initrd.magic" file for use by UEFI kernels
Provide a file "initrd.magic" via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
that contains the initrd file as constructed for BIOS bzImage kernels
(including injected files with CPIO headers constructed by iPXE).
This allows BIOS and UEFI kernels to obtain the exact same initramfs
image, by adding "initrd=initrd.magic" to the kernel command line.
For example:
#!ipxe
kernel boot/vmlinuz initrd=initrd.magic
initrd boot/initrd.img
initrd boot/modules/e1000.ko /lib/modules/e1000.ko
initrd boot/modules/af_packet.ko /lib/modules/af_packet.ko
boot
Do not include the "initrd.magic" file within the root directory
listing, since doing so would break software such as wimboot that
processes all files within the root directory.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/interface/efi/efi_file.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index c67fdea..fc64b36 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <errno.h> #include <wchar.h> #include <ipxe/image.h> +#include <ipxe/cpio.h> #include <ipxe/efi/efi.h> #include <ipxe/efi/Protocol/SimpleFileSystem.h> #include <ipxe/efi/Protocol/BlockIo.h> @@ -84,6 +85,7 @@ struct efi_file { }; static struct efi_file efi_file_root; +static struct efi_file efi_file_initrd; /** * Free EFI file @@ -210,6 +212,67 @@ static size_t efi_file_read_image ( struct efi_file_reader *reader ) { } /** + * Read from magic initrd file + * + * @v reader EFI file reader + * @ret len Length read + */ +static size_t efi_file_read_initrd ( struct efi_file_reader *reader ) { + struct efi_file *file = reader->file; + struct cpio_header cpio; + struct image *image; + const char *name; + size_t pad_len; + size_t cpio_len; + size_t name_len; + size_t len; + + /* Read from file */ + len = 0; + for_each_image ( image ) { + + /* Ignore currently executing image */ + if ( image == current_image ) + continue; + + /* Pad to alignment boundary */ + pad_len = ( ( -reader->pos ) & ( INITRD_ALIGN - 1 ) ); + if ( pad_len ) { + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) pad\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + pad_len ) ); + } + len += efi_file_read_chunk ( reader, UNULL, pad_len ); + + /* Read CPIO header, if applicable */ + cpio_len = cpio_header ( image, &cpio ); + if ( cpio_len ) { + name = cpio_name ( image ); + name_len = cpio_name_len ( image ); + pad_len = ( cpio_len - sizeof ( cpio ) - name_len ); + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) %s header\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + cpio_len ), image->name ); + len += efi_file_read_chunk ( reader, + virt_to_user ( &cpio ), + sizeof ( cpio ) ); + len += efi_file_read_chunk ( reader, + virt_to_user ( name ), + name_len ); + len += efi_file_read_chunk ( reader, UNULL, pad_len ); + } + + /* Read file data */ + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) %s\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + image->len ), image->name ); + len += efi_file_read_chunk ( reader, image->data, image->len ); + } + + return len; +} + +/** * Open fixed file * * @v file EFI file @@ -289,6 +352,10 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, return EFI_WRITE_PROTECTED; } + /* Allow magic initrd to be opened */ + if ( strcasecmp ( name, efi_file_initrd.name ) == 0 ) + return efi_file_open_fixed ( &efi_file_initrd, new ); + /* Identify image */ image = efi_file_find ( name ); if ( ! image ) { @@ -637,6 +704,27 @@ static struct efi_file efi_file_root = { .name = "", }; +/** Magic initrd file */ +static struct efi_file efi_file_initrd = { + .refcnt = REF_INIT ( ref_no_free ), + .file = { + .Revision = EFI_FILE_PROTOCOL_REVISION, + .Open = efi_file_open, + .Close = efi_file_close, + .Delete = efi_file_delete, + .Read = efi_file_read, + .Write = efi_file_write, + .GetPosition = efi_file_get_position, + .SetPosition = efi_file_set_position, + .GetInfo = efi_file_get_info, + .SetInfo = efi_file_set_info, + .Flush = efi_file_flush, + }, + .image = NULL, + .name = "initrd.magic", + .read = efi_file_read_initrd, +}; + /** * Open root directory * |