mirror of
https://github.com/ipxe/ipxe.git
synced 2026-05-05 12:26:37 +02:00
[efi] Allow executing images even with no open network devices
We need a device handle from which to nominally load an EFI image. We currently rely on using the most recently opened network device's SNP device handle, in the same way that we use the most recently opened network device when loading a BIOS PXE NBP image. If there is no most recently opened network device, then we cannot execute an EFI image. We use three aspects of the SNP device handle: the handle itself (giving us something on which to install protocols), the associated device path (giving us a base path from which to construct the new image's file path), and the associated network device (giving us an interface for the PXE base code protocol installation). Make the network device optional by simply choosing not to install the PXE base code protocols when no network device is defined. This allows us to fall back to using our own loaded image's device handle and device path for the other two purposes. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
3df8f9c379
commit
910d9c5a98
@ -153,7 +153,9 @@ __weak int efi_fdt_uninstall ( void ) {
|
||||
static int efi_image_exec ( struct image *image ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
struct efi_snp_device *snpdev;
|
||||
EFI_DEVICE_PATH_PROTOCOL *path;
|
||||
struct net_device *netdev;
|
||||
EFI_DEVICE_PATH_PROTOCOL *devpath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *imgpath;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded;
|
||||
struct image *shim;
|
||||
struct image *exec;
|
||||
@ -167,13 +169,23 @@ static int efi_image_exec ( struct image *image ) {
|
||||
|
||||
/* Find an appropriate device handle to use */
|
||||
snpdev = last_opened_snpdev();
|
||||
if ( ! snpdev ) {
|
||||
DBGC ( image, "EFIIMAGE %s could not identify SNP device\n",
|
||||
image->name );
|
||||
rc = -ENODEV;
|
||||
goto err_no_snpdev;
|
||||
if ( snpdev ) {
|
||||
/* We have a netX: use this as the base device */
|
||||
device = snpdev->handle;
|
||||
devpath = snpdev->path;
|
||||
netdev = netdev_get ( snpdev->netdev );
|
||||
DBGC ( image, "EFIIMAGE %s using %s %s\n", image->name,
|
||||
netdev->name, efi_devpath_text ( devpath ) );
|
||||
} else {
|
||||
/* We have no netX: fall back to using our own loaded
|
||||
* image's device.
|
||||
*/
|
||||
device = efi_loaded_image->DeviceHandle;
|
||||
devpath = efi_loaded_image_path;
|
||||
netdev = NULL;
|
||||
DBGC ( image, "EFIIMAGE %s using %s\n",
|
||||
image->name, efi_devpath_text ( devpath ) );
|
||||
}
|
||||
device = snpdev->handle;
|
||||
|
||||
/* Use shim instead of directly executing image if applicable */
|
||||
shim = ( efi_can_load ( image ) ?
|
||||
@ -198,7 +210,8 @@ static int efi_image_exec ( struct image *image ) {
|
||||
}
|
||||
|
||||
/* Install PXE base code protocol */
|
||||
if ( ( rc = efi_pxe_install ( device, snpdev->netdev ) ) != 0 ){
|
||||
if ( ( netdev != NULL ) &&
|
||||
( rc = efi_pxe_install ( device, netdev ) ) != 0 ) {
|
||||
DBGC ( image, "EFIIMAGE %s could not install PXE protocol: "
|
||||
"%s\n", image->name, strerror ( rc ) );
|
||||
goto err_pxe_install;
|
||||
@ -219,8 +232,8 @@ static int efi_image_exec ( struct image *image ) {
|
||||
}
|
||||
|
||||
/* Create device path for image */
|
||||
path = efi_image_path ( exec, snpdev->path );
|
||||
if ( ! path ) {
|
||||
imgpath = efi_image_path ( exec, devpath );
|
||||
if ( ! imgpath ) {
|
||||
DBGC ( image, "EFIIMAGE %s could not create device path\n",
|
||||
image->name );
|
||||
rc = -ENOMEM;
|
||||
@ -251,7 +264,7 @@ static int efi_image_exec ( struct image *image ) {
|
||||
* therefore use the .rwdata field rather than .data.
|
||||
*/
|
||||
handle = NULL;
|
||||
if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
|
||||
if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, imgpath,
|
||||
exec->rwdata, exec->len,
|
||||
&handle ) ) != 0 ) {
|
||||
/* Not an EFI image */
|
||||
@ -302,9 +315,6 @@ static int efi_image_exec ( struct image *image ) {
|
||||
/* Reset console since image will probably use it */
|
||||
console_reset();
|
||||
|
||||
/* Assume that image may cause SNP device to be removed */
|
||||
snpdev = NULL;
|
||||
|
||||
/* Start the image */
|
||||
if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
|
||||
rc = -EEFI_START ( efirc );
|
||||
@ -349,20 +359,21 @@ static int efi_image_exec ( struct image *image ) {
|
||||
err_shim_install:
|
||||
free ( cmdline );
|
||||
err_cmdline:
|
||||
free ( path );
|
||||
free ( imgpath );
|
||||
err_image_path:
|
||||
efi_fdt_uninstall();
|
||||
err_fdt_install:
|
||||
efi_download_uninstall ( device );
|
||||
err_download_install:
|
||||
efi_pxe_uninstall ( device );
|
||||
if ( netdev )
|
||||
efi_pxe_uninstall ( device );
|
||||
err_pxe_install:
|
||||
efi_file_uninstall ( device );
|
||||
err_file_install:
|
||||
unregister_image ( image );
|
||||
err_register_image:
|
||||
image->flags ^= toggle;
|
||||
err_no_snpdev:
|
||||
netdev_put ( netdev );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user