Skip to content

Commit

Permalink
[efi] Wrap any images loaded by our wrapped image
Browse files Browse the repository at this point in the history
Propagate our modified EFI system table to any images loaded by the
image that we wrap, thereby allowing us to observe boot services calls
made by all subsequent EFI images.

Also show details of intercepted ExitBootServices() calls.  When
wrapping is used, exiting boot services will almost certainly fail,
but this at least allows us to see when it happens.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Aug 29, 2014
1 parent 2cb95c9 commit 0cc2f42
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/image/efi_image.c
Expand Up @@ -227,7 +227,7 @@ static int efi_image_exec ( struct image *image ) {
efi_snp_release();

/* Wrap calls made by the loaded image (for debugging) */
efi_wrap ( handle, loaded.image );
efi_wrap ( handle );

/* Start the image */
if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
Expand Down
3 changes: 1 addition & 2 deletions src/include/ipxe/efi/efi_wrap.h
Expand Up @@ -9,8 +9,7 @@
FILE_LICENCE ( GPL2_OR_LATER );

#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/LoadedImage.h>

extern void efi_wrap ( EFI_HANDLE handle, EFI_LOADED_IMAGE_PROTOCOL *loaded );
extern void efi_wrap ( EFI_HANDLE handle );

#endif /* _IPXE_EFI_WRAP_H */
1 change: 1 addition & 0 deletions src/include/ipxe/errfile.h
Expand Up @@ -306,6 +306,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_xenbus ( ERRFILE_OTHER | 0x00430000 )
#define ERRFILE_xengrant ( ERRFILE_OTHER | 0x00440000 )
#define ERRFILE_efi_utils ( ERRFILE_OTHER | 0x00450000 )
#define ERRFILE_efi_wrap ( ERRFILE_OTHER | 0x00460000 )

/** @} */

Expand Down
88 changes: 67 additions & 21 deletions src/interface/efi/efi_wrap.c
Expand Up @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER );

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/LoadedImage.h>
#include <ipxe/efi/efi_wrap.h>
Expand Down Expand Up @@ -135,6 +136,28 @@ efi_locate_handle_wrapper ( EFI_LOCATE_SEARCH_TYPE search_type,
return efirc;
}

/**
* Wrap LocateDevicePath()
*
*/
static EFI_STATUS EFIAPI
efi_locate_device_path_wrapper ( EFI_GUID *protocol,
EFI_DEVICE_PATH_PROTOCOL **device_path,
EFI_HANDLE *device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
void *retaddr = __builtin_return_address ( 0 );
EFI_STATUS efirc;

DBGC ( colour, "LocateDevicePath ( %s, %s, ... ) ",
efi_guid_ntoa ( protocol ), efi_devpath_text ( *device_path ) );
efirc = bs->LocateDevicePath ( protocol, device_path, device );
DBGC ( colour, "= %s ( %p, ",
efi_status ( efirc ), efi_devpath_text ( *device_path ) );
DBGC ( colour, "%p %s ) -> %p\n",
*device, efi_handle_name ( *device ), retaddr );
return efirc;
}

/**
* Wrap LoadImage()
*
Expand All @@ -161,28 +184,29 @@ efi_load_image_wrapper ( BOOLEAN boot_policy, EFI_HANDLE parent_image_handle,
efi_handle_name ( *image_handle ) );
}
DBGC ( colour, ") -> %p\n", retaddr );

/* Wrap the new image */
if ( efirc == 0 )
efi_wrap ( *image_handle );

return efirc;
}

/**
* Wrap LocateDevicePath()
* Wrap ExitBootServices()
*
*/
static EFI_STATUS EFIAPI
efi_locate_device_path_wrapper ( EFI_GUID *protocol,
EFI_DEVICE_PATH_PROTOCOL **device_path,
EFI_HANDLE *device ) {
efi_exit_boot_services_wrapper ( EFI_HANDLE image_handle, UINTN map_key ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
void *retaddr = __builtin_return_address ( 0 );
EFI_STATUS efirc;

DBGC ( colour, "LocateDevicePath ( %s, %s, ... ) ",
efi_guid_ntoa ( protocol ), efi_devpath_text ( *device_path ) );
efirc = bs->LocateDevicePath ( protocol, device_path, device );
DBGC ( colour, "= %s ( %p, ",
efi_status ( efirc ), efi_devpath_text ( *device_path ) );
DBGC ( colour, "%p %s ) -> %p\n",
*device, efi_handle_name ( *device ), retaddr );
DBGC ( colour, "ExitBootServices ( %p %s, %#llx ) ",
image_handle, efi_handle_name ( image_handle ),
( ( unsigned long long ) map_key ) );
efirc = bs->ExitBootServices ( image_handle, map_key );
DBGC ( colour, "= %s -> %p\n", efi_status ( efirc ), retaddr );
return efirc;
}

Expand Down Expand Up @@ -234,10 +258,15 @@ efi_locate_protocol_wrapper ( EFI_GUID *protocol, VOID *registration,
* Wrap the calls made by a loaded image
*
* @v handle Image handle
* @v loaded Loaded image protocol
*/
void efi_wrap ( EFI_HANDLE handle, EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
void efi_wrap ( EFI_HANDLE handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_LOADED_IMAGE_PROTOCOL *image;
void *intf;
} loaded;
EFI_STATUS efirc;
int rc;

/* Do nothing unless debugging is enabled */
if ( ! DBG_LOG )
Expand All @@ -252,18 +281,35 @@ void efi_wrap ( EFI_HANDLE handle, EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
efi_bs_wrapper.LocateHandle = efi_locate_handle_wrapper;
efi_bs_wrapper.LocateDevicePath = efi_locate_device_path_wrapper;
efi_bs_wrapper.LoadImage = efi_load_image_wrapper;
efi_bs_wrapper.ExitBootServices = efi_exit_boot_services_wrapper;
efi_bs_wrapper.OpenProtocol = efi_open_protocol_wrapper;
efi_bs_wrapper.LocateProtocol = efi_locate_protocol_wrapper;

/* Open loaded image protocol */
if ( ( efirc = bs->OpenProtocol ( handle,
&efi_loaded_image_protocol_guid,
&loaded.intf, efi_image_handle, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
rc = -EEFI ( efirc );
DBGC ( colour, "Could not get loaded image protocol for %p %s: "
"%s\n", handle, efi_handle_name ( handle ),
strerror ( rc ) );
return;
}

/* Provide system table wrapper to image */
loaded->SystemTable = &efi_systab_wrapper;
loaded.image->SystemTable = &efi_systab_wrapper;
DBGC ( colour, "Wrapped image %p %s at base %p has protocols:\n",
handle, efi_handle_name ( handle ), loaded->ImageBase );
handle, efi_handle_name ( handle ), loaded.image->ImageBase );
DBGC_EFI_PROTOCOLS ( colour, handle );
DBGC ( colour, "Parent image %p %s\n", loaded->ParentHandle,
efi_handle_name ( loaded->ParentHandle ) );
DBGC ( colour, "Device %p %s ", loaded->DeviceHandle,
efi_handle_name ( loaded->DeviceHandle ) );
DBGC ( colour, "file %p %s\n", loaded->FilePath,
efi_devpath_text ( loaded->FilePath ) );
DBGC ( colour, "Parent image %p %s\n", loaded.image->ParentHandle,
efi_handle_name ( loaded.image->ParentHandle ) );
DBGC ( colour, "Device %p %s ", loaded.image->DeviceHandle,
efi_handle_name ( loaded.image->DeviceHandle ) );
DBGC ( colour, "file %p %s\n", loaded.image->FilePath,
efi_devpath_text ( loaded.image->FilePath ) );

/* Close loaded image protocol */
bs->CloseProtocol ( handle, &efi_loaded_image_protocol_guid,
efi_image_handle, NULL );
}

0 comments on commit 0cc2f42

Please sign in to comment.