aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-05-21 14:27:27 +0100
committerMichael Brown <mcb30@ipxe.org>2021-05-21 20:18:50 +0100
commite5f02551735922eb235388bff08249a6f31ded3d (patch)
tree30d7136dfb8e477ce1b8ca27f2a4b5c2777d721b
parentef9953b7122937dc12762e9f5ce797ba6859a24e (diff)
downloadipxe-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>
-rw-r--r--src/interface/efi/efi_file.c88
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
*