diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-03-07 14:19:01 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-03-07 14:19:01 +0000 |
commit | 2aef08b7a5fa98e5b309d47d933b5cd32a6feec0 (patch) | |
tree | 2b1455479ecc83cfaa1c897ade901b50e6403e8e | |
parent | 54fcb7c29ce2fabe109286e3c4dfeb297e0f3916 (diff) | |
download | qemu-ipxe-2aef08b7a5fa98e5b309d47d933b5cd32a6feec0.tar.gz |
WIP - shim
-rw-r--r-- | src/config/config.c | 3 | ||||
-rw-r--r-- | src/config/defaults/efi.h | 1 | ||||
-rw-r--r-- | src/config/general.h | 1 | ||||
-rw-r--r-- | src/hci/commands/shim_cmd.c | 98 | ||||
-rw-r--r-- | src/image/efi_image.c | 25 | ||||
-rw-r--r-- | src/include/ipxe/efi/efi_shim.h | 30 |
6 files changed, 153 insertions, 5 deletions
diff --git a/src/config/config.c b/src/config/config.c index a8186613..40f9c72c 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -290,6 +290,9 @@ REQUIRE_OBJECT ( cert_cmd ); #ifdef IMAGE_MEM_CMD REQUIRE_OBJECT ( image_mem_cmd ); #endif +#ifdef SHIM_CMD +REQUIRE_OBJECT ( shim_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index 8e53b9ab..998bdcc1 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -47,6 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define USB_BLOCK /* USB block devices */ #define REBOOT_CMD /* Reboot command */ +#define SHIM_CMD /* EFI shim command */ #if defined ( __i386__ ) || defined ( __x86_64__ ) #define IOAPI_X86 diff --git a/src/config/general.h b/src/config/general.h index e75a2aff..2a371d0e 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -160,6 +160,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); //#define CERT_CMD /* Certificate management commands */ //#define IMAGE_MEM_CMD /* Read memory command */ #define IMAGE_ARCHIVE_CMD /* Archive image management commands */ +//#define SHIM_CMD /* EFI shim command */ /* * ROM-specific options diff --git a/src/hci/commands/shim_cmd.c b/src/hci/commands/shim_cmd.c new file mode 100644 index 00000000..f8a841a3 --- /dev/null +++ b/src/hci/commands/shim_cmd.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <getopt.h> +#include <ipxe/command.h> +#include <ipxe/parseopt.h> +#include <ipxe/efi/efi_shim.h> +#include <usr/imgmgmt.h> + +/** @file + * + * EFI shim command + * + */ + +/** "shim" options */ +struct shim_options { + /** Keep original image */ + int keep; + /** Download timeout */ + unsigned long timeout; +}; + +/** "shim" option list */ +static struct option_descriptor shim_opts[] = { + OPTION_DESC ( "keep", 'k', no_argument, + struct shim_options, keep, parse_flag ), + OPTION_DESC ( "timeout", 't', required_argument, + struct shim_options, timeout, parse_timeout ), +}; + +/** "shim" command descriptor */ +static struct command_descriptor shim_cmd = + COMMAND_DESC ( struct shim_options, shim_opts, 1, 1, NULL ); + +/** + * The "shim" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int shim_exec ( int argc, char **argv ) { + struct shim_options opts; + struct image *image; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &shim_cmd, &opts ) ) != 0 ) + goto err_parse; + + /* Acquire image */ + if ( ( rc = imgacquire ( argv[optind], opts.timeout, &image ) ) != 0 ) + goto err_acquire; + + /* Register as shim */ + efi_set_shim ( image ); + + /* Success */ + rc = 0; + + /* Discard original image unless --keep was specified */ + if ( ! opts.keep ) + unregister_image ( image ); + err_acquire: + err_parse: + return rc; +} + +/** Shim commands */ +struct command shim_commands[] __command = { + { + .name = "shim", + .exec = shim_exec, + }, +}; diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 467fb05a..6235ea03 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/efi/efi_wrap.h> #include <ipxe/efi/efi_pxe.h> #include <ipxe/efi/efi_driver.h> +#include <ipxe/efi/efi_shim.h> #include <ipxe/image.h> #include <ipxe/init.h> #include <ipxe/features.h> @@ -55,6 +56,9 @@ FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); "Could not start image" ) #define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc ) +/** Registered shim, if any */ +struct image *efi_shim; + /** * Create device path for image * @@ -132,12 +136,14 @@ static wchar_t * efi_image_cmdline ( struct image *image ) { */ static int efi_image_exec ( struct image *image ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + struct image *shim = efi_shim; struct efi_snp_device *snpdev; EFI_DEVICE_PATH_PROTOCOL *path; union { EFI_LOADED_IMAGE_PROTOCOL *image; void *interface; } loaded; + struct image *exec; EFI_HANDLE handle; EFI_MEMORY_TYPE type; wchar_t *cmdline; @@ -160,8 +166,9 @@ static int efi_image_exec ( struct image *image ) { goto err_file_install; } - /* Install PXE base code protocol */ - if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){ + /* Install PXE base code protocol (unless using a shim) */ + if ( ( ! shim ) && + ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){ DBGC ( image, "EFIIMAGE %s could not install PXE protocol: " "%s\n", image->name, strerror ( rc ) ); goto err_pxe_install; @@ -192,11 +199,18 @@ static int efi_image_exec ( struct image *image ) { goto err_cmdline; } + /* Execute image or shim as applicable */ + exec = ( shim ? shim : image ); + if ( shim ) { + DBGC ( image, "EFIIMAGE %s executing via %s\n", + image->name, shim->name ); + } + /* Attempt loading image */ handle = NULL; if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path, - user_to_virt ( image->data, 0 ), - image->len, &handle ) ) != 0 ) { + user_to_virt ( exec->data, 0 ), + exec->len, &handle ) ) != 0 ) { /* Not an EFI image */ rc = -EEFI_LOAD ( efirc ); DBGC ( image, "EFIIMAGE %s could not load: %s\n", @@ -292,7 +306,8 @@ static int efi_image_exec ( struct image *image ) { err_image_path: efi_download_uninstall ( snpdev->handle ); err_download_install: - efi_pxe_uninstall ( snpdev->handle ); + if ( ! shim ) + efi_pxe_uninstall ( snpdev->handle ); err_pxe_install: efi_file_uninstall ( snpdev->handle ); err_file_install: diff --git a/src/include/ipxe/efi/efi_shim.h b/src/include/ipxe/efi/efi_shim.h new file mode 100644 index 00000000..ef655995 --- /dev/null +++ b/src/include/ipxe/efi/efi_shim.h @@ -0,0 +1,30 @@ +#ifndef _IPXE_EFI_SHIM_H +#define _IPXE_EFI_SHIM_H + +/** @file + * + * EFI shim + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <ipxe/image.h> + +extern struct image *efi_shim; + +/** + * Set shim image + * + * @v image Shim image, or NULL to clear shim + */ +static inline void efi_set_shim ( struct image *image ) { + + /* Clear any existing shim */ + image_put ( efi_shim ); + + /* Record as shim */ + efi_shim = image_get ( image ); +} + +#endif /* _IPXE_EFI_SHIM_H */ |