|  | @@ -0,0 +1,237 @@
 | 
		
	
		
			
			|  | 1 | +/*
 | 
		
	
		
			
			|  | 2 | + * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
 | 
		
	
		
			
			|  | 3 | + *
 | 
		
	
		
			
			|  | 4 | + * This program is free software; you can redistribute it and/or
 | 
		
	
		
			
			|  | 5 | + * modify it under the terms of the GNU General Public License as
 | 
		
	
		
			
			|  | 6 | + * published by the Free Software Foundation; either version 2 of the
 | 
		
	
		
			
			|  | 7 | + * License, or any later version.
 | 
		
	
		
			
			|  | 8 | + *
 | 
		
	
		
			
			|  | 9 | + * This program is distributed in the hope that it will be useful, but
 | 
		
	
		
			
			|  | 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
		
	
		
			
			|  | 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
		
	
		
			
			|  | 12 | + * General Public License for more details.
 | 
		
	
		
			
			|  | 13 | + *
 | 
		
	
		
			
			|  | 14 | + * You should have received a copy of the GNU General Public License
 | 
		
	
		
			
			|  | 15 | + * along with this program; if not, write to the Free Software
 | 
		
	
		
			
			|  | 16 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
		
	
		
			
			|  | 17 | + * 02110-1301, USA.
 | 
		
	
		
			
			|  | 18 | + */
 | 
		
	
		
			
			|  | 19 | +
 | 
		
	
		
			
			|  | 20 | +FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			|  | 21 | +
 | 
		
	
		
			
			|  | 22 | +/**
 | 
		
	
		
			
			|  | 23 | + * @file
 | 
		
	
		
			
			|  | 24 | + *
 | 
		
	
		
			
			|  | 25 | + * EFI image wrapping
 | 
		
	
		
			
			|  | 26 | + *
 | 
		
	
		
			
			|  | 27 | + */
 | 
		
	
		
			
			|  | 28 | +
 | 
		
	
		
			
			|  | 29 | +#include <string.h>
 | 
		
	
		
			
			|  | 30 | +#include <stdio.h>
 | 
		
	
		
			
			|  | 31 | +#include <ipxe/efi/efi.h>
 | 
		
	
		
			
			|  | 32 | +#include <ipxe/efi/Protocol/LoadedImage.h>
 | 
		
	
		
			
			|  | 33 | +#include <ipxe/efi/efi_wrap.h>
 | 
		
	
		
			
			|  | 34 | +
 | 
		
	
		
			
			|  | 35 | +/** EFI system table wrapper */
 | 
		
	
		
			
			|  | 36 | +static EFI_SYSTEM_TABLE efi_systab_wrapper;
 | 
		
	
		
			
			|  | 37 | +
 | 
		
	
		
			
			|  | 38 | +/** EFI boot services table wrapper */
 | 
		
	
		
			
			|  | 39 | +static EFI_BOOT_SERVICES efi_bs_wrapper;
 | 
		
	
		
			
			|  | 40 | +
 | 
		
	
		
			
			|  | 41 | +/** Colour for debug messages */
 | 
		
	
		
			
			|  | 42 | +#define colour &efi_systab_wrapper
 | 
		
	
		
			
			|  | 43 | +
 | 
		
	
		
			
			|  | 44 | +/**
 | 
		
	
		
			
			|  | 45 | + * Convert EFI status code to text
 | 
		
	
		
			
			|  | 46 | + *
 | 
		
	
		
			
			|  | 47 | + * @v efirc		EFI status code
 | 
		
	
		
			
			|  | 48 | + * @ret text		EFI status code text
 | 
		
	
		
			
			|  | 49 | + */
 | 
		
	
		
			
			|  | 50 | +static const char * efi_status ( EFI_STATUS efirc ) {
 | 
		
	
		
			
			|  | 51 | +	static char buf[ 19 /* "0xXXXXXXXXXXXXXXXX" + NUL */ ];
 | 
		
	
		
			
			|  | 52 | +
 | 
		
	
		
			
			|  | 53 | +	switch ( efirc ) {
 | 
		
	
		
			
			|  | 54 | +	case EFI_SUCCESS :			return "0";
 | 
		
	
		
			
			|  | 55 | +	case EFI_LOAD_ERROR :			return "LOAD_ERROR";
 | 
		
	
		
			
			|  | 56 | +	case EFI_INVALID_PARAMETER :		return "INVALID_PARAMETER";
 | 
		
	
		
			
			|  | 57 | +	case EFI_UNSUPPORTED :			return "UNSUPPORTED";
 | 
		
	
		
			
			|  | 58 | +	case EFI_BAD_BUFFER_SIZE :		return "BAD_BUFFER_SIZE";
 | 
		
	
		
			
			|  | 59 | +	case EFI_BUFFER_TOO_SMALL :		return "BUFFER_TOO_SMALL";
 | 
		
	
		
			
			|  | 60 | +	case EFI_NOT_READY :			return "NOT_READY";
 | 
		
	
		
			
			|  | 61 | +	case EFI_DEVICE_ERROR :			return "DEVICE_ERROR";
 | 
		
	
		
			
			|  | 62 | +	case EFI_WRITE_PROTECTED :		return "WRITE_PROTECTED";
 | 
		
	
		
			
			|  | 63 | +	case EFI_OUT_OF_RESOURCES :		return "OUT_OF_RESOURCES";
 | 
		
	
		
			
			|  | 64 | +	case EFI_VOLUME_CORRUPTED :		return "VOLUME_CORRUPTED";
 | 
		
	
		
			
			|  | 65 | +	case EFI_VOLUME_FULL :			return "VOLUME_FULL";
 | 
		
	
		
			
			|  | 66 | +	case EFI_NO_MEDIA :			return "NO_MEDIA";
 | 
		
	
		
			
			|  | 67 | +	case EFI_MEDIA_CHANGED :		return "MEDIA_CHANGED";
 | 
		
	
		
			
			|  | 68 | +	case EFI_NOT_FOUND :			return "NOT_FOUND";
 | 
		
	
		
			
			|  | 69 | +	case EFI_ACCESS_DENIED :		return "ACCESS_DENIED";
 | 
		
	
		
			
			|  | 70 | +	case EFI_NO_RESPONSE :			return "NO_RESPONSE";
 | 
		
	
		
			
			|  | 71 | +	case EFI_NO_MAPPING :			return "NO_MAPPING";
 | 
		
	
		
			
			|  | 72 | +	case EFI_TIMEOUT :			return "TIMEOUT";
 | 
		
	
		
			
			|  | 73 | +	case EFI_NOT_STARTED :			return "NOT_STARTED";
 | 
		
	
		
			
			|  | 74 | +	case EFI_ALREADY_STARTED :		return "ALREADY_STARTED";
 | 
		
	
		
			
			|  | 75 | +	case EFI_ABORTED :			return "ABORTED";
 | 
		
	
		
			
			|  | 76 | +	case EFI_ICMP_ERROR :			return "ICMP_ERROR";
 | 
		
	
		
			
			|  | 77 | +	case EFI_TFTP_ERROR :			return "TFTP_ERROR";
 | 
		
	
		
			
			|  | 78 | +	case EFI_PROTOCOL_ERROR :		return "PROTOCOL_ERROR";
 | 
		
	
		
			
			|  | 79 | +	case EFI_INCOMPATIBLE_VERSION :		return "INCOMPATIBLE_VERSION";
 | 
		
	
		
			
			|  | 80 | +	case EFI_SECURITY_VIOLATION :		return "SECURITY_VIOLATION";
 | 
		
	
		
			
			|  | 81 | +	case EFI_CRC_ERROR :			return "CRC_ERROR";
 | 
		
	
		
			
			|  | 82 | +	case EFI_END_OF_MEDIA :			return "END_OF_MEDIA";
 | 
		
	
		
			
			|  | 83 | +	case EFI_END_OF_FILE :			return "END_OF_FILE";
 | 
		
	
		
			
			|  | 84 | +	case EFI_INVALID_LANGUAGE :		return "INVALID_LANGUAGE";
 | 
		
	
		
			
			|  | 85 | +	case EFI_COMPROMISED_DATA :		return "COMPROMISED_DATA";
 | 
		
	
		
			
			|  | 86 | +	case EFI_WARN_UNKNOWN_GLYPH :		return "WARN_UNKNOWN_GLYPH";
 | 
		
	
		
			
			|  | 87 | +	case EFI_WARN_DELETE_FAILURE :		return "WARN_DELETE_FAILURE";
 | 
		
	
		
			
			|  | 88 | +	case EFI_WARN_WRITE_FAILURE :		return "WARN_WRITE_FAILURE";
 | 
		
	
		
			
			|  | 89 | +	case EFI_WARN_BUFFER_TOO_SMALL :	return "WARN_BUFFER_TOO_SMALL";
 | 
		
	
		
			
			|  | 90 | +	case EFI_WARN_STALE_DATA :		return "WARN_STALE_DATA";
 | 
		
	
		
			
			|  | 91 | +	default:
 | 
		
	
		
			
			|  | 92 | +		snprintf ( buf, sizeof ( buf ), "%#lx",
 | 
		
	
		
			
			|  | 93 | +			   ( unsigned long ) efirc );
 | 
		
	
		
			
			|  | 94 | +		return buf;
 | 
		
	
		
			
			|  | 95 | +	}
 | 
		
	
		
			
			|  | 96 | +}
 | 
		
	
		
			
			|  | 97 | +
 | 
		
	
		
			
			|  | 98 | +/**
 | 
		
	
		
			
			|  | 99 | + * Wrap HandleProtocol()
 | 
		
	
		
			
			|  | 100 | + *
 | 
		
	
		
			
			|  | 101 | + */
 | 
		
	
		
			
			|  | 102 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 103 | +efi_handle_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
 | 
		
	
		
			
			|  | 104 | +			      VOID **interface ) {
 | 
		
	
		
			
			|  | 105 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 106 | +	void *retaddr = __builtin_return_address ( 0 );
 | 
		
	
		
			
			|  | 107 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 108 | +
 | 
		
	
		
			
			|  | 109 | +	DBGC ( colour, "HandleProtocol ( %p %s, %s, ... ) ", handle,
 | 
		
	
		
			
			|  | 110 | +	       efi_handle_devpath_text ( handle ), efi_guid_ntoa ( protocol ) );
 | 
		
	
		
			
			|  | 111 | +	efirc = bs->HandleProtocol ( handle, protocol, interface );
 | 
		
	
		
			
			|  | 112 | +	DBGC ( colour, "= %s ( %p ) -> %p\n",
 | 
		
	
		
			
			|  | 113 | +	       efi_status ( efirc ), *interface, retaddr );
 | 
		
	
		
			
			|  | 114 | +	return efirc;
 | 
		
	
		
			
			|  | 115 | +}
 | 
		
	
		
			
			|  | 116 | +
 | 
		
	
		
			
			|  | 117 | +/**
 | 
		
	
		
			
			|  | 118 | + * Wrap LocateHandle()
 | 
		
	
		
			
			|  | 119 | + *
 | 
		
	
		
			
			|  | 120 | + */
 | 
		
	
		
			
			|  | 121 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 122 | +efi_locate_handle_wrapper ( EFI_LOCATE_SEARCH_TYPE search_type,
 | 
		
	
		
			
			|  | 123 | +			    EFI_GUID *protocol, VOID *search_key,
 | 
		
	
		
			
			|  | 124 | +			    UINTN *buffer_size, EFI_HANDLE *buffer ) {
 | 
		
	
		
			
			|  | 125 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 126 | +	void *retaddr = __builtin_return_address ( 0 );
 | 
		
	
		
			
			|  | 127 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 128 | +
 | 
		
	
		
			
			|  | 129 | +	DBGC ( colour, "LocateHandle ( %d, %s, ..., %zd, ... ) ", search_type,
 | 
		
	
		
			
			|  | 130 | +	       efi_guid_ntoa ( protocol ), ( ( size_t ) *buffer_size ) );
 | 
		
	
		
			
			|  | 131 | +	efirc = bs->LocateHandle ( search_type, protocol, search_key,
 | 
		
	
		
			
			|  | 132 | +				   buffer_size, buffer );
 | 
		
	
		
			
			|  | 133 | +	DBGC ( colour, "= %s ( %zd ) -> %p\n",
 | 
		
	
		
			
			|  | 134 | +	       efi_status ( efirc ), ( ( size_t ) *buffer_size ), retaddr );
 | 
		
	
		
			
			|  | 135 | +	return efirc;
 | 
		
	
		
			
			|  | 136 | +}
 | 
		
	
		
			
			|  | 137 | +
 | 
		
	
		
			
			|  | 138 | +/**
 | 
		
	
		
			
			|  | 139 | + * Wrap LocateDevicePath()
 | 
		
	
		
			
			|  | 140 | + *
 | 
		
	
		
			
			|  | 141 | + */
 | 
		
	
		
			
			|  | 142 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 143 | +efi_locate_device_path_wrapper ( EFI_GUID *protocol,
 | 
		
	
		
			
			|  | 144 | +				 EFI_DEVICE_PATH_PROTOCOL **device_path,
 | 
		
	
		
			
			|  | 145 | +				 EFI_HANDLE *device ) {
 | 
		
	
		
			
			|  | 146 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 147 | +	void *retaddr = __builtin_return_address ( 0 );
 | 
		
	
		
			
			|  | 148 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 149 | +
 | 
		
	
		
			
			|  | 150 | +	DBGC ( colour, "LocateDevicePath ( %s, %s, ... ) ",
 | 
		
	
		
			
			|  | 151 | +	       efi_guid_ntoa ( protocol ), efi_devpath_text ( *device_path ) );
 | 
		
	
		
			
			|  | 152 | +	efirc = bs->LocateDevicePath ( protocol, device_path, device );
 | 
		
	
		
			
			|  | 153 | +	DBGC ( colour, "= %s ( %p, ",
 | 
		
	
		
			
			|  | 154 | +	       efi_status ( efirc ), efi_devpath_text ( *device_path ) );
 | 
		
	
		
			
			|  | 155 | +	DBGC ( colour, "%p %s ) -> %p\n",
 | 
		
	
		
			
			|  | 156 | +	       *device, efi_handle_devpath_text ( *device ), retaddr );
 | 
		
	
		
			
			|  | 157 | +	return efirc;
 | 
		
	
		
			
			|  | 158 | +}
 | 
		
	
		
			
			|  | 159 | +
 | 
		
	
		
			
			|  | 160 | +/**
 | 
		
	
		
			
			|  | 161 | + * Wrap OpenProtocol()
 | 
		
	
		
			
			|  | 162 | + *
 | 
		
	
		
			
			|  | 163 | + */
 | 
		
	
		
			
			|  | 164 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 165 | +efi_open_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
 | 
		
	
		
			
			|  | 166 | +			    VOID **interface, EFI_HANDLE agent_handle,
 | 
		
	
		
			
			|  | 167 | +			    EFI_HANDLE controller_handle, UINT32 attributes ) {
 | 
		
	
		
			
			|  | 168 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 169 | +	void *retaddr = __builtin_return_address ( 0 );
 | 
		
	
		
			
			|  | 170 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 171 | +
 | 
		
	
		
			
			|  | 172 | +	DBGC ( colour, "OpenProtocol ( %p %s, %s, ..., ", handle,
 | 
		
	
		
			
			|  | 173 | +	       efi_handle_devpath_text ( handle ), efi_guid_ntoa ( protocol ) );
 | 
		
	
		
			
			|  | 174 | +	DBGC ( colour, "%p %s, ", agent_handle,
 | 
		
	
		
			
			|  | 175 | +	       efi_handle_devpath_text ( agent_handle ) );
 | 
		
	
		
			
			|  | 176 | +	DBGC ( colour, "%p %s, %#x ) ", controller_handle,
 | 
		
	
		
			
			|  | 177 | +	       efi_handle_devpath_text ( controller_handle ), attributes );
 | 
		
	
		
			
			|  | 178 | +	efirc = bs->OpenProtocol ( handle, protocol, interface, agent_handle,
 | 
		
	
		
			
			|  | 179 | +				   controller_handle, attributes );
 | 
		
	
		
			
			|  | 180 | +	DBGC ( colour, "= %s ( %p ) -> %p\n",
 | 
		
	
		
			
			|  | 181 | +	       efi_status ( efirc ), *interface, retaddr );
 | 
		
	
		
			
			|  | 182 | +	return efirc;
 | 
		
	
		
			
			|  | 183 | +}
 | 
		
	
		
			
			|  | 184 | +
 | 
		
	
		
			
			|  | 185 | +/**
 | 
		
	
		
			
			|  | 186 | + * Wrap LocateProtocol()
 | 
		
	
		
			
			|  | 187 | + *
 | 
		
	
		
			
			|  | 188 | + */
 | 
		
	
		
			
			|  | 189 | +static EFI_STATUS EFIAPI
 | 
		
	
		
			
			|  | 190 | +efi_locate_protocol_wrapper ( EFI_GUID *protocol, VOID *registration,
 | 
		
	
		
			
			|  | 191 | +			      VOID **interface ) {
 | 
		
	
		
			
			|  | 192 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 193 | +	void *retaddr = __builtin_return_address ( 0 );
 | 
		
	
		
			
			|  | 194 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 195 | +
 | 
		
	
		
			
			|  | 196 | +	DBGC ( colour, "LocateProtocol ( %s, %p, ... ) ",
 | 
		
	
		
			
			|  | 197 | +	       efi_guid_ntoa ( protocol ), registration );
 | 
		
	
		
			
			|  | 198 | +	efirc = bs->LocateProtocol ( protocol, registration, interface );
 | 
		
	
		
			
			|  | 199 | +	DBGC ( colour, "= %s ( %p ) -> %p\n",
 | 
		
	
		
			
			|  | 200 | +	       efi_status ( efirc ), *interface, retaddr );
 | 
		
	
		
			
			|  | 201 | +	return efirc;
 | 
		
	
		
			
			|  | 202 | +}
 | 
		
	
		
			
			|  | 203 | +
 | 
		
	
		
			
			|  | 204 | +/**
 | 
		
	
		
			
			|  | 205 | + * Wrap the calls made by a loaded image
 | 
		
	
		
			
			|  | 206 | + *
 | 
		
	
		
			
			|  | 207 | + * @v handle		Image handle
 | 
		
	
		
			
			|  | 208 | + * @v loaded		Loaded image protocol
 | 
		
	
		
			
			|  | 209 | + */
 | 
		
	
		
			
			|  | 210 | +void efi_wrap ( EFI_HANDLE handle, EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
 | 
		
	
		
			
			|  | 211 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 212 | +
 | 
		
	
		
			
			|  | 213 | +	/* Do nothing unless debugging is enabled */
 | 
		
	
		
			
			|  | 214 | +	if ( ! DBG_LOG )
 | 
		
	
		
			
			|  | 215 | +		return;
 | 
		
	
		
			
			|  | 216 | +
 | 
		
	
		
			
			|  | 217 | +	/* Populate table wrappers */
 | 
		
	
		
			
			|  | 218 | +	memcpy ( &efi_systab_wrapper, efi_systab,
 | 
		
	
		
			
			|  | 219 | +		 sizeof ( efi_systab_wrapper ) );
 | 
		
	
		
			
			|  | 220 | +	memcpy ( &efi_bs_wrapper, bs, sizeof ( efi_bs_wrapper ) );
 | 
		
	
		
			
			|  | 221 | +	efi_systab_wrapper.BootServices	= &efi_bs_wrapper;
 | 
		
	
		
			
			|  | 222 | +	efi_bs_wrapper.HandleProtocol	= efi_handle_protocol_wrapper;
 | 
		
	
		
			
			|  | 223 | +	efi_bs_wrapper.LocateHandle	= efi_locate_handle_wrapper;
 | 
		
	
		
			
			|  | 224 | +	efi_bs_wrapper.LocateDevicePath	= efi_locate_device_path_wrapper;
 | 
		
	
		
			
			|  | 225 | +	efi_bs_wrapper.OpenProtocol	= efi_open_protocol_wrapper;
 | 
		
	
		
			
			|  | 226 | +	efi_bs_wrapper.LocateProtocol	= efi_locate_protocol_wrapper;
 | 
		
	
		
			
			|  | 227 | +
 | 
		
	
		
			
			|  | 228 | +	/* Provide system table wrapper to image */
 | 
		
	
		
			
			|  | 229 | +	loaded->SystemTable = &efi_systab_wrapper;
 | 
		
	
		
			
			|  | 230 | +	DBGC ( colour, "Wrapped image %p %s at base %p\n", handle,
 | 
		
	
		
			
			|  | 231 | +	       efi_handle_devpath_text ( handle ), loaded->ImageBase );
 | 
		
	
		
			
			|  | 232 | +	DBGC ( colour, "Parent image %p %s\n", loaded->ParentHandle,
 | 
		
	
		
			
			|  | 233 | +	       efi_handle_devpath_text ( loaded->ParentHandle ) );
 | 
		
	
		
			
			|  | 234 | +	DBGC ( colour, "Device %p %s ", loaded->DeviceHandle,
 | 
		
	
		
			
			|  | 235 | +	       efi_handle_devpath_text ( loaded->DeviceHandle ) );
 | 
		
	
		
			
			|  | 236 | +	DBGC ( colour, "file %s\n", efi_devpath_text ( loaded->FilePath ) );
 | 
		
	
		
			
			|  | 237 | +}
 |