[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>
pull/373/head
Michael Brown 2021-05-21 14:27:27 +01:00
parent ef9953b712
commit e5f0255173
1 changed files with 88 additions and 0 deletions

View File

@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h> #include <errno.h>
#include <wchar.h> #include <wchar.h>
#include <ipxe/image.h> #include <ipxe/image.h>
#include <ipxe/cpio.h>
#include <ipxe/efi/efi.h> #include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/SimpleFileSystem.h> #include <ipxe/efi/Protocol/SimpleFileSystem.h>
#include <ipxe/efi/Protocol/BlockIo.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_root;
static struct efi_file efi_file_initrd;
/** /**
* Free EFI file * Free EFI file
@ -209,6 +211,67 @@ static size_t efi_file_read_image ( struct efi_file_reader *reader ) {
return efi_file_read_chunk ( reader, image->data, image->len ); return efi_file_read_chunk ( reader, image->data, image->len );
} }
/**
* 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 * Open fixed file
* *
@ -289,6 +352,10 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
return EFI_WRITE_PROTECTED; 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 */ /* Identify image */
image = efi_file_find ( name ); image = efi_file_find ( name );
if ( ! image ) { if ( ! image ) {
@ -637,6 +704,27 @@ static struct efi_file efi_file_root = {
.name = "", .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 * Open root directory
* *