mirror of
				https://gitlab.com/qemu-project/ipxe.git
				synced 2025-11-03 07:59:06 +08:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4b7ad95261 | |||
| 99aad39037 | |||
| b123d32870 | |||
| 2aef08b7a5 | 
@ -290,6 +290,9 @@ REQUIRE_OBJECT ( cert_cmd );
 | 
				
			|||||||
#ifdef IMAGE_MEM_CMD
 | 
					#ifdef IMAGE_MEM_CMD
 | 
				
			||||||
REQUIRE_OBJECT ( image_mem_cmd );
 | 
					REQUIRE_OBJECT ( image_mem_cmd );
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef SHIM_CMD
 | 
				
			||||||
 | 
					REQUIRE_OBJECT ( shim_cmd );
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Drag in miscellaneous objects
 | 
					 * Drag in miscellaneous objects
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
				
			|||||||
#define USB_BLOCK		/* USB block devices */
 | 
					#define USB_BLOCK		/* USB block devices */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	REBOOT_CMD		/* Reboot command */
 | 
					#define	REBOOT_CMD		/* Reboot command */
 | 
				
			||||||
 | 
					#define SHIM_CMD		/* EFI shim command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined ( __i386__ ) || defined ( __x86_64__ )
 | 
					#if defined ( __i386__ ) || defined ( __x86_64__ )
 | 
				
			||||||
#define IOAPI_X86
 | 
					#define IOAPI_X86
 | 
				
			||||||
 | 
				
			|||||||
@ -160,6 +160,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
				
			|||||||
//#define CERT_CMD		/* Certificate management commands */
 | 
					//#define CERT_CMD		/* Certificate management commands */
 | 
				
			||||||
//#define IMAGE_MEM_CMD		/* Read memory command */
 | 
					//#define IMAGE_MEM_CMD		/* Read memory command */
 | 
				
			||||||
#define IMAGE_ARCHIVE_CMD	/* Archive image management commands */
 | 
					#define IMAGE_ARCHIVE_CMD	/* Archive image management commands */
 | 
				
			||||||
 | 
					//#define SHIM_CMD		/* EFI shim command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * ROM-specific options
 | 
					 * ROM-specific options
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										108
									
								
								src/hci/commands/shim_cmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/hci/commands/shim_cmd.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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>
 | 
				
			||||||
 | 
					#include <usr/shimmgmt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * EFI shim command
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** "shim" options */
 | 
				
			||||||
 | 
					struct shim_options {
 | 
				
			||||||
 | 
						/** Keep original image */
 | 
				
			||||||
 | 
						int keep;
 | 
				
			||||||
 | 
						/** Download timeout */
 | 
				
			||||||
 | 
						unsigned long timeout;
 | 
				
			||||||
 | 
						/** Second stage alternative name */
 | 
				
			||||||
 | 
						char *altname;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** "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 ),
 | 
				
			||||||
 | 
						OPTION_DESC ( "altname", 'a', required_argument,
 | 
				
			||||||
 | 
							      struct shim_options, altname, parse_string ),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** "shim" command descriptor */
 | 
				
			||||||
 | 
					static struct command_descriptor shim_cmd =
 | 
				
			||||||
 | 
						COMMAND_DESC ( struct shim_options, shim_opts, 0, 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 = NULL;
 | 
				
			||||||
 | 
						char *name_uri = NULL;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse options */
 | 
				
			||||||
 | 
						if ( ( rc = parse_options ( argc, argv, &shim_cmd, &opts ) ) != 0 )
 | 
				
			||||||
 | 
							goto err_parse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse name/URI string */
 | 
				
			||||||
 | 
						name_uri = argv[optind];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Acquire image, if applicable */
 | 
				
			||||||
 | 
						if ( name_uri &&
 | 
				
			||||||
 | 
						     ( rc = imgacquire ( name_uri, opts.timeout, &image ) ) != 0 ) {
 | 
				
			||||||
 | 
							goto err_acquire;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* (Un)register as shim */
 | 
				
			||||||
 | 
						if ( ( rc = shim ( image, opts.altname ) ) != 0 )
 | 
				
			||||||
 | 
							goto err_shim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Unregister original image unless --keep was specified */
 | 
				
			||||||
 | 
						if ( image && ( ! opts.keep ) )
 | 
				
			||||||
 | 
							unregister_image ( image );
 | 
				
			||||||
 | 
					 err_shim:
 | 
				
			||||||
 | 
					 err_acquire:
 | 
				
			||||||
 | 
					 err_parse:
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Shim commands */
 | 
				
			||||||
 | 
					struct command shim_commands[] __command = {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.name = "shim",
 | 
				
			||||||
 | 
							.exec = shim_exec,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
				
			|||||||
#include <ipxe/efi/efi_wrap.h>
 | 
					#include <ipxe/efi/efi_wrap.h>
 | 
				
			||||||
#include <ipxe/efi/efi_pxe.h>
 | 
					#include <ipxe/efi/efi_pxe.h>
 | 
				
			||||||
#include <ipxe/efi/efi_driver.h>
 | 
					#include <ipxe/efi/efi_driver.h>
 | 
				
			||||||
 | 
					#include <ipxe/efi/efi_shim.h>
 | 
				
			||||||
#include <ipxe/image.h>
 | 
					#include <ipxe/image.h>
 | 
				
			||||||
#include <ipxe/init.h>
 | 
					#include <ipxe/init.h>
 | 
				
			||||||
#include <ipxe/features.h>
 | 
					#include <ipxe/features.h>
 | 
				
			||||||
@ -55,6 +56,9 @@ FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
 | 
				
			|||||||
			  "Could not start image" )
 | 
								  "Could not start image" )
 | 
				
			||||||
#define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
 | 
					#define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Registered shim, if any */
 | 
				
			||||||
 | 
					struct image *efi_shim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Create device path for image
 | 
					 * Create device path for image
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -104,20 +108,26 @@ efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Create command line for image
 | 
					 * Create command line for image
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @v image             EFI image
 | 
					 * @v image		EFI image
 | 
				
			||||||
 | 
					 * @v prefix		Command line prefix, or NULL
 | 
				
			||||||
 * @ret cmdline		Command line, or NULL on failure
 | 
					 * @ret cmdline		Command line, or NULL on failure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static wchar_t * efi_image_cmdline ( struct image *image ) {
 | 
					static wchar_t * efi_image_cmdline ( struct image *image,
 | 
				
			||||||
 | 
									     const char *prefix ) {
 | 
				
			||||||
	wchar_t *cmdline;
 | 
						wchar_t *cmdline;
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len = ( strlen ( image->name ) +
 | 
						len = ( ( prefix ?
 | 
				
			||||||
 | 
							  ( strlen ( prefix ) + 1 /* NUL */ + 1 /* " " */ ) : 0 ) +
 | 
				
			||||||
 | 
							strlen ( image->name ) +
 | 
				
			||||||
		( image->cmdline ?
 | 
							( image->cmdline ?
 | 
				
			||||||
		  ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
 | 
							  ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
 | 
				
			||||||
	cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
 | 
						cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
 | 
				
			||||||
	if ( ! cmdline )
 | 
						if ( ! cmdline )
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
 | 
						efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s%s%s",
 | 
				
			||||||
 | 
							       ( prefix ? prefix : "" ),
 | 
				
			||||||
 | 
							       ( prefix ? " " : "" ),
 | 
				
			||||||
		       image->name,
 | 
							       image->name,
 | 
				
			||||||
		       ( image->cmdline ? " " : "" ),
 | 
							       ( image->cmdline ? " " : "" ),
 | 
				
			||||||
		       ( image->cmdline ? image->cmdline : "" ) );
 | 
							       ( image->cmdline ? image->cmdline : "" ) );
 | 
				
			||||||
@ -132,12 +142,16 @@ static wchar_t * efi_image_cmdline ( struct image *image ) {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static int efi_image_exec ( struct image *image ) {
 | 
					static int efi_image_exec ( struct image *image ) {
 | 
				
			||||||
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
						EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
				
			||||||
 | 
						struct image *shim = efi_shim;
 | 
				
			||||||
	struct efi_snp_device *snpdev;
 | 
						struct efi_snp_device *snpdev;
 | 
				
			||||||
	EFI_DEVICE_PATH_PROTOCOL *path;
 | 
						EFI_DEVICE_PATH_PROTOCOL *path;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		EFI_LOADED_IMAGE_PROTOCOL *image;
 | 
							EFI_LOADED_IMAGE_PROTOCOL *image;
 | 
				
			||||||
		void *interface;
 | 
							void *interface;
 | 
				
			||||||
	} loaded;
 | 
						} loaded;
 | 
				
			||||||
 | 
						struct image *exec;
 | 
				
			||||||
 | 
						const char *prefix;
 | 
				
			||||||
 | 
						const char *altname;
 | 
				
			||||||
	EFI_HANDLE handle;
 | 
						EFI_HANDLE handle;
 | 
				
			||||||
	EFI_MEMORY_TYPE type;
 | 
						EFI_MEMORY_TYPE type;
 | 
				
			||||||
	wchar_t *cmdline;
 | 
						wchar_t *cmdline;
 | 
				
			||||||
@ -153,15 +167,29 @@ static int efi_image_exec ( struct image *image ) {
 | 
				
			|||||||
		goto err_no_snpdev;
 | 
							goto err_no_snpdev;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Choose to execute image via shim if applicable */
 | 
				
			||||||
 | 
						if ( shim ) {
 | 
				
			||||||
 | 
							exec = shim;
 | 
				
			||||||
 | 
							prefix = shim->name;
 | 
				
			||||||
 | 
							altname = shim->cmdline;
 | 
				
			||||||
 | 
							DBGC ( image, "EFIIMAGE %s (aka %s) executing via %s\n",
 | 
				
			||||||
 | 
							       image->name, altname, shim->name );
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							exec = image;
 | 
				
			||||||
 | 
							prefix = NULL;
 | 
				
			||||||
 | 
							altname = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Install file I/O protocols */
 | 
						/* Install file I/O protocols */
 | 
				
			||||||
	if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
 | 
						if ( ( rc = efi_file_install ( snpdev->handle, image, altname ) ) != 0){
 | 
				
			||||||
		DBGC ( image, "EFIIMAGE %s could not install file protocol: "
 | 
							DBGC ( image, "EFIIMAGE %s could not install file protocol: "
 | 
				
			||||||
		       "%s\n", image->name, strerror ( rc ) );
 | 
							       "%s\n", image->name, strerror ( rc ) );
 | 
				
			||||||
		goto err_file_install;
 | 
							goto err_file_install;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Install PXE base code protocol */
 | 
						/* Install PXE base code protocol (unless using a shim) */
 | 
				
			||||||
	if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
 | 
						if ( ( ! shim ) &&
 | 
				
			||||||
 | 
						     ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
 | 
				
			||||||
		DBGC ( image, "EFIIMAGE %s could not install PXE protocol: "
 | 
							DBGC ( image, "EFIIMAGE %s could not install PXE protocol: "
 | 
				
			||||||
		       "%s\n", image->name, strerror ( rc ) );
 | 
							       "%s\n", image->name, strerror ( rc ) );
 | 
				
			||||||
		goto err_pxe_install;
 | 
							goto err_pxe_install;
 | 
				
			||||||
@ -175,7 +203,7 @@ static int efi_image_exec ( struct image *image ) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create device path for image */
 | 
						/* Create device path for image */
 | 
				
			||||||
	path = efi_image_path ( image, snpdev->path );
 | 
						path = efi_image_path ( exec, snpdev->path );
 | 
				
			||||||
	if ( ! path ) {
 | 
						if ( ! path ) {
 | 
				
			||||||
		DBGC ( image, "EFIIMAGE %s could not create device path\n",
 | 
							DBGC ( image, "EFIIMAGE %s could not create device path\n",
 | 
				
			||||||
		       image->name );
 | 
							       image->name );
 | 
				
			||||||
@ -184,7 +212,7 @@ static int efi_image_exec ( struct image *image ) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create command line for image */
 | 
						/* Create command line for image */
 | 
				
			||||||
	cmdline = efi_image_cmdline ( image );
 | 
						cmdline = efi_image_cmdline ( image, prefix );
 | 
				
			||||||
	if ( ! cmdline ) {
 | 
						if ( ! cmdline ) {
 | 
				
			||||||
		DBGC ( image, "EFIIMAGE %s could not create command line\n",
 | 
							DBGC ( image, "EFIIMAGE %s could not create command line\n",
 | 
				
			||||||
		       image->name );
 | 
							       image->name );
 | 
				
			||||||
@ -195,8 +223,8 @@ static int efi_image_exec ( struct image *image ) {
 | 
				
			|||||||
	/* Attempt loading image */
 | 
						/* Attempt loading image */
 | 
				
			||||||
	handle = NULL;
 | 
						handle = NULL;
 | 
				
			||||||
	if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
 | 
						if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
 | 
				
			||||||
				       user_to_virt ( image->data, 0 ),
 | 
									       user_to_virt ( exec->data, 0 ),
 | 
				
			||||||
				       image->len, &handle ) ) != 0 ) {
 | 
									       exec->len, &handle ) ) != 0 ) {
 | 
				
			||||||
		/* Not an EFI image */
 | 
							/* Not an EFI image */
 | 
				
			||||||
		rc = -EEFI_LOAD ( efirc );
 | 
							rc = -EEFI_LOAD ( efirc );
 | 
				
			||||||
		DBGC ( image, "EFIIMAGE %s could not load: %s\n",
 | 
							DBGC ( image, "EFIIMAGE %s could not load: %s\n",
 | 
				
			||||||
@ -292,7 +320,8 @@ static int efi_image_exec ( struct image *image ) {
 | 
				
			|||||||
 err_image_path:
 | 
					 err_image_path:
 | 
				
			||||||
	efi_download_uninstall ( snpdev->handle );
 | 
						efi_download_uninstall ( snpdev->handle );
 | 
				
			||||||
 err_download_install:
 | 
					 err_download_install:
 | 
				
			||||||
	efi_pxe_uninstall ( snpdev->handle );
 | 
						if ( ! shim )
 | 
				
			||||||
 | 
							efi_pxe_uninstall ( snpdev->handle );
 | 
				
			||||||
 err_pxe_install:
 | 
					 err_pxe_install:
 | 
				
			||||||
	efi_file_uninstall ( snpdev->handle );
 | 
						efi_file_uninstall ( snpdev->handle );
 | 
				
			||||||
 err_file_install:
 | 
					 err_file_install:
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
					FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int efi_file_install ( EFI_HANDLE handle );
 | 
					struct image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int efi_file_install ( EFI_HANDLE handle, struct image *second,
 | 
				
			||||||
 | 
								      const char *altname );
 | 
				
			||||||
extern void efi_file_uninstall ( EFI_HANDLE handle );
 | 
					extern void efi_file_uninstall ( EFI_HANDLE handle );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _IPXE_EFI_FILE_H */
 | 
					#endif /* _IPXE_EFI_FILE_H */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								src/include/ipxe/efi/efi_shim.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/include/ipxe/efi/efi_shim.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#ifndef _IPXE_EFI_SHIM_H
 | 
				
			||||||
 | 
					#define _IPXE_EFI_SHIM_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * EFI shim
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct image *efi_shim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _IPXE_EFI_SHIM_H */
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/include/usr/shimmgmt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/include/usr/shimmgmt.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#ifndef _USR_SHIMMGMT_H
 | 
				
			||||||
 | 
					#define _USR_SHIMMGMT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * EFI shim management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <ipxe/image.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int shim ( struct image *image, const char *altname );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _USR_SHIMMGMT_H */
 | 
				
			||||||
@ -94,6 +94,7 @@ struct efi_file {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct efi_file efi_file_root;
 | 
					static struct efi_file efi_file_root;
 | 
				
			||||||
 | 
					static struct efi_file efi_file_second;
 | 
				
			||||||
static struct efi_file efi_file_initrd;
 | 
					static struct efi_file efi_file_initrd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -117,7 +118,15 @@ static void efi_file_free ( struct refcnt *refcnt ) {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static const char * efi_file_name ( struct efi_file *file ) {
 | 
					static const char * efi_file_name ( struct efi_file *file ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ( file == &efi_file_root ? "<root>" : file->name );
 | 
						if ( file == &efi_file_root ) {
 | 
				
			||||||
 | 
							return "<root>";
 | 
				
			||||||
 | 
						} else if ( file->image != NULL ) {
 | 
				
			||||||
 | 
							return file->image->name;
 | 
				
			||||||
 | 
						} else if ( file->name != NULL ) {
 | 
				
			||||||
 | 
							return file->name;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return "<UNKNOWN>";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -281,10 +290,11 @@ static size_t efi_file_read_initrd ( struct efi_file_reader *reader ) {
 | 
				
			|||||||
 * Open fixed file
 | 
					 * Open fixed file
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @v file		EFI file
 | 
					 * @v file		EFI file
 | 
				
			||||||
 | 
					 * @v wname		Filename
 | 
				
			||||||
 * @v new		New EFI file
 | 
					 * @v new		New EFI file
 | 
				
			||||||
 * @ret efirc		EFI status code
 | 
					 * @ret efirc		EFI status code
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static EFI_STATUS efi_file_open_fixed ( struct efi_file *file,
 | 
					static EFI_STATUS efi_file_open_fixed ( struct efi_file *file, const char *name,
 | 
				
			||||||
					EFI_FILE_PROTOCOL **new ) {
 | 
										EFI_FILE_PROTOCOL **new ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Increment reference count */
 | 
						/* Increment reference count */
 | 
				
			||||||
@ -293,7 +303,8 @@ static EFI_STATUS efi_file_open_fixed ( struct efi_file *file,
 | 
				
			|||||||
	/* Return opened file */
 | 
						/* Return opened file */
 | 
				
			||||||
	*new = &file->file;
 | 
						*new = &file->file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DBGC ( file, "EFIFILE %s opened\n", efi_file_name ( file ) );
 | 
						DBGC ( file, "EFIFILE %s opened via %s\n",
 | 
				
			||||||
 | 
						       efi_file_name ( file ), name );
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -310,6 +321,33 @@ static void efi_file_image ( struct efi_file *file, struct image *image ) {
 | 
				
			|||||||
	file->read = efi_file_read_image;
 | 
						file->read = efi_file_read_image;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Open dynamically allocated file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @v image		Image
 | 
				
			||||||
 | 
					 * @v new		New EFI file
 | 
				
			||||||
 | 
					 * @ret efirc		EFI status code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static EFI_STATUS efi_file_open_dynamic ( struct image *image,
 | 
				
			||||||
 | 
										  EFI_FILE_PROTOCOL **new ) {
 | 
				
			||||||
 | 
						struct efi_file *file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Allocate and initialise file */
 | 
				
			||||||
 | 
						file = zalloc ( sizeof ( *file ) );
 | 
				
			||||||
 | 
						if ( ! file )
 | 
				
			||||||
 | 
							return EFI_OUT_OF_RESOURCES;
 | 
				
			||||||
 | 
						ref_init ( &file->refcnt, efi_file_free );
 | 
				
			||||||
 | 
						memcpy ( &file->file, &efi_file_root.file,
 | 
				
			||||||
 | 
							 sizeof ( file->file ) );
 | 
				
			||||||
 | 
						memcpy ( &file->load, &efi_file_root.load,
 | 
				
			||||||
 | 
							 sizeof ( file->load ) );
 | 
				
			||||||
 | 
						efi_file_image ( file, image_get ( image ) );
 | 
				
			||||||
 | 
						*new = &file->file;
 | 
				
			||||||
 | 
						DBGC ( file, "EFIFILE %s opened\n", efi_file_name ( file ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Open file
 | 
					 * Open file
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -325,7 +363,6 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
 | 
				
			|||||||
		CHAR16 *wname, UINT64 mode, UINT64 attributes __unused ) {
 | 
							CHAR16 *wname, UINT64 mode, UINT64 attributes __unused ) {
 | 
				
			||||||
	struct efi_file *file = container_of ( this, struct efi_file, file );
 | 
						struct efi_file *file = container_of ( this, struct efi_file, file );
 | 
				
			||||||
	char buf[ wcslen ( wname ) + 1 /* NUL */ ];
 | 
						char buf[ wcslen ( wname ) + 1 /* NUL */ ];
 | 
				
			||||||
	struct efi_file *new_file;
 | 
					 | 
				
			||||||
	struct image *image;
 | 
						struct image *image;
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -341,7 +378,7 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Allow root directory itself to be opened */
 | 
						/* Allow root directory itself to be opened */
 | 
				
			||||||
	if ( ( name[0] == '\0' ) || ( name[0] == '.' ) )
 | 
						if ( ( name[0] == '\0' ) || ( name[0] == '.' ) )
 | 
				
			||||||
		return efi_file_open_fixed ( &efi_file_root, new );
 | 
							return efi_file_open_fixed ( &efi_file_root, name, new );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Fail unless opening from the root */
 | 
						/* Fail unless opening from the root */
 | 
				
			||||||
	if ( file != &efi_file_root ) {
 | 
						if ( file != &efi_file_root ) {
 | 
				
			||||||
@ -359,29 +396,22 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Allow magic initrd to be opened */
 | 
						/* Allow magic initrd to be opened */
 | 
				
			||||||
	if ( strcasecmp ( name, efi_file_initrd.name ) == 0 )
 | 
						if ( strcasecmp ( name, efi_file_initrd.name ) == 0 )
 | 
				
			||||||
		return efi_file_open_fixed ( &efi_file_initrd, new );
 | 
							return efi_file_open_fixed ( &efi_file_initrd, name, new );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Identify image */
 | 
						/* Allow registered images to be opened */
 | 
				
			||||||
	image = efi_file_find ( name );
 | 
						if ( ( image = efi_file_find ( name ) ) != NULL )
 | 
				
			||||||
	if ( ! image ) {
 | 
							return efi_file_open_dynamic ( image, new );
 | 
				
			||||||
		DBGC ( file, "EFIFILE %s does not exist\n", name );
 | 
					
 | 
				
			||||||
		return EFI_NOT_FOUND;
 | 
						/* Allow magic second stage to be opened */
 | 
				
			||||||
 | 
						if ( ( efi_file_second.image != NULL ) &&
 | 
				
			||||||
 | 
						     ( ( strcasecmp ( name, efi_file_second.image->name ) == 0 ) ||
 | 
				
			||||||
 | 
						       ( ( efi_file_second.name != NULL ) &&
 | 
				
			||||||
 | 
							 ( strcasecmp ( name, efi_file_second.name ) == 0 ) ) ) ) {
 | 
				
			||||||
 | 
							return efi_file_open_fixed ( &efi_file_second, name, new );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate and initialise file */
 | 
						DBGC ( file, "EFIFILE %s does not exist\n", name );
 | 
				
			||||||
	new_file = zalloc ( sizeof ( *new_file ) );
 | 
						return EFI_NOT_FOUND;
 | 
				
			||||||
	if ( ! new_file )
 | 
					 | 
				
			||||||
		return EFI_OUT_OF_RESOURCES;
 | 
					 | 
				
			||||||
	ref_init ( &file->refcnt, efi_file_free );
 | 
					 | 
				
			||||||
	memcpy ( &new_file->file, &efi_file_root.file,
 | 
					 | 
				
			||||||
		 sizeof ( new_file->file ) );
 | 
					 | 
				
			||||||
	memcpy ( &new_file->load, &efi_file_root.load,
 | 
					 | 
				
			||||||
		 sizeof ( new_file->load ) );
 | 
					 | 
				
			||||||
	efi_file_image ( new_file, image_get ( image ) );
 | 
					 | 
				
			||||||
	*new = &new_file->file;
 | 
					 | 
				
			||||||
	DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -752,6 +782,30 @@ static struct efi_file efi_file_root = {
 | 
				
			|||||||
	.name = "",
 | 
						.name = "",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Magic second stage file */
 | 
				
			||||||
 | 
					static struct efi_file efi_file_second = {
 | 
				
			||||||
 | 
						.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,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.load = {
 | 
				
			||||||
 | 
							.LoadFile = efi_file_load,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.image = NULL,
 | 
				
			||||||
 | 
						.name = NULL,
 | 
				
			||||||
 | 
						.read = efi_file_read_image,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Magic initrd file */
 | 
					/** Magic initrd file */
 | 
				
			||||||
static struct efi_file efi_file_initrd = {
 | 
					static struct efi_file efi_file_initrd = {
 | 
				
			||||||
	.refcnt = REF_INIT ( ref_no_free ),
 | 
						.refcnt = REF_INIT ( ref_no_free ),
 | 
				
			||||||
@ -808,7 +862,7 @@ efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused,
 | 
				
			|||||||
		       EFI_FILE_PROTOCOL **file ) {
 | 
							       EFI_FILE_PROTOCOL **file ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DBGC ( &efi_file_root, "EFIFILE open volume\n" );
 | 
						DBGC ( &efi_file_root, "EFIFILE open volume\n" );
 | 
				
			||||||
	return efi_file_open_fixed ( &efi_file_root, file );
 | 
						return efi_file_open_fixed ( &efi_file_root, "volume", file );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** EFI simple file system protocol */
 | 
					/** EFI simple file system protocol */
 | 
				
			||||||
@ -1012,9 +1066,12 @@ static int efi_file_path_install ( EFI_DEVICE_PATH_PROTOCOL *path,
 | 
				
			|||||||
 * Install EFI simple file system protocol
 | 
					 * Install EFI simple file system protocol
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @v handle		EFI handle
 | 
					 * @v handle		EFI handle
 | 
				
			||||||
 | 
					 * @v second		Second stage image, or NULL
 | 
				
			||||||
 | 
					 * @v altname		Second stage alternative filename, or NULL
 | 
				
			||||||
 * @ret rc		Return status code
 | 
					 * @ret rc		Return status code
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int efi_file_install ( EFI_HANDLE handle ) {
 | 
					int efi_file_install ( EFI_HANDLE handle, struct image *second,
 | 
				
			||||||
 | 
							       const char *altname ) {
 | 
				
			||||||
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
						EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
				
			||||||
	EFI_LOAD_FILE2_PROTOCOL *load;
 | 
						EFI_LOAD_FILE2_PROTOCOL *load;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
@ -1079,6 +1136,12 @@ int efi_file_install ( EFI_HANDLE handle ) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	assert ( diskio.diskio == &efi_disk_io_protocol );
 | 
						assert ( diskio.diskio == &efi_disk_io_protocol );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initialise magic second stage file, if any */
 | 
				
			||||||
 | 
						if ( second ) {
 | 
				
			||||||
 | 
							efi_file_second.image = image_get ( second );
 | 
				
			||||||
 | 
							efi_file_second.name = altname;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Install Linux initrd fixed device path file
 | 
						/* Install Linux initrd fixed device path file
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * Install the device path handle unconditionally, since we
 | 
						 * Install the device path handle unconditionally, since we
 | 
				
			||||||
@ -1097,6 +1160,9 @@ int efi_file_install ( EFI_HANDLE handle ) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	efi_file_path_install ( &efi_file_initrd_path.vendor.Header, NULL );
 | 
						efi_file_path_install ( &efi_file_initrd_path.vendor.Header, NULL );
 | 
				
			||||||
 err_initrd:
 | 
					 err_initrd:
 | 
				
			||||||
 | 
						image_put ( efi_file_second.image );
 | 
				
			||||||
 | 
						efi_file_second.image = NULL;
 | 
				
			||||||
 | 
						efi_file_second.name = NULL;
 | 
				
			||||||
	bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
 | 
						bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
 | 
				
			||||||
			    efi_image_handle, handle );
 | 
								    efi_image_handle, handle );
 | 
				
			||||||
 err_open:
 | 
					 err_open:
 | 
				
			||||||
@ -1125,6 +1191,11 @@ void efi_file_uninstall ( EFI_HANDLE handle ) {
 | 
				
			|||||||
	/* Uninstall Linux initrd fixed device path file */
 | 
						/* Uninstall Linux initrd fixed device path file */
 | 
				
			||||||
	efi_file_path_install ( &efi_file_initrd_path.vendor.Header, NULL );
 | 
						efi_file_path_install ( &efi_file_initrd_path.vendor.Header, NULL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Clear magic second stage, if any */
 | 
				
			||||||
 | 
						image_put ( efi_file_second.image );
 | 
				
			||||||
 | 
						efi_file_second.image = NULL;
 | 
				
			||||||
 | 
						efi_file_second.name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Close our own disk I/O protocol */
 | 
						/* Close our own disk I/O protocol */
 | 
				
			||||||
	bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
 | 
						bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
 | 
				
			||||||
			    efi_image_handle, handle );
 | 
								    efi_image_handle, handle );
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										85
									
								
								src/usr/shimmgmt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/usr/shimmgmt.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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 <string.h>
 | 
				
			||||||
 | 
					#include <strings.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <ipxe/image.h>
 | 
				
			||||||
 | 
					#include <ipxe/efi/efi.h>
 | 
				
			||||||
 | 
					#include <ipxe/efi/efi_shim.h>
 | 
				
			||||||
 | 
					#include <usr/shimmgmt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * EFI shim management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set shim image
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @v image		Shim image, or NULL to clear shim
 | 
				
			||||||
 | 
					 * @v altname		Second stage alternative name, or NULL to use default
 | 
				
			||||||
 | 
					 * @ret rc		Return status code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int shim ( struct image *image, const char *altname ) {
 | 
				
			||||||
 | 
						static wchar_t wbootpath[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
 | 
				
			||||||
 | 
						char bootpath[ sizeof ( wbootpath ) / sizeof ( wbootpath[0] ) ];
 | 
				
			||||||
 | 
						char *bootname;
 | 
				
			||||||
 | 
						char *sep;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Clear any existing shim */
 | 
				
			||||||
 | 
						image_put ( efi_shim );
 | 
				
			||||||
 | 
						efi_shim = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Do nothing more unless a shim is specified */
 | 
				
			||||||
 | 
						if ( ! image )
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Construct default second stage alternative name */
 | 
				
			||||||
 | 
						snprintf ( bootpath, sizeof ( bootpath ), "%ls", wbootpath );
 | 
				
			||||||
 | 
						sep = strrchr ( bootpath, '\\' );
 | 
				
			||||||
 | 
						assert ( sep != NULL );
 | 
				
			||||||
 | 
						bootname = ( sep + 1 );
 | 
				
			||||||
 | 
						assert ( strncasecmp ( bootname, "BOOT", 4 ) == 0 );
 | 
				
			||||||
 | 
						memcpy ( bootname, "GRUB", 4 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Use default second stage alternative name, if not specified */
 | 
				
			||||||
 | 
						if ( ! altname )
 | 
				
			||||||
 | 
							altname = bootname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Record second stage alternative name, if any */
 | 
				
			||||||
 | 
						if ( ( rc = image_set_cmdline ( image, altname ) ) != 0 )
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Record as shim */
 | 
				
			||||||
 | 
						efi_shim = image_get ( image );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DBGC ( image, "SHIM %s installed (altname %s)\n",
 | 
				
			||||||
 | 
						       image->name, image->cmdline );
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user