Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / interface / efi / efi_wrap.c
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 <errno.h>
32 #include <ipxe/efi/efi.h>
33 #include <ipxe/efi/Protocol/LoadedImage.h>
34 #include <ipxe/efi/efi_wrap.h>
35
36 /** EFI system table wrapper */
37 static EFI_SYSTEM_TABLE efi_systab_wrapper;
38
39 /** EFI boot services table wrapper */
40 static EFI_BOOT_SERVICES efi_bs_wrapper;
41
42 /** Colour for debug messages */
43 #define colour &efi_systab_wrapper
44
45 /**
46  * Convert EFI status code to text
47  *
48  * @v efirc             EFI status code
49  * @ret text            EFI status code text
50  */
51 static const char * efi_status ( EFI_STATUS efirc ) {
52         static char buf[ 19 /* "0xXXXXXXXXXXXXXXXX" + NUL */ ];
53
54         switch ( efirc ) {
55         case EFI_SUCCESS :                      return "0";
56         case EFI_LOAD_ERROR :                   return "LOAD_ERROR";
57         case EFI_INVALID_PARAMETER :            return "INVALID_PARAMETER";
58         case EFI_UNSUPPORTED :                  return "UNSUPPORTED";
59         case EFI_BAD_BUFFER_SIZE :              return "BAD_BUFFER_SIZE";
60         case EFI_BUFFER_TOO_SMALL :             return "BUFFER_TOO_SMALL";
61         case EFI_NOT_READY :                    return "NOT_READY";
62         case EFI_DEVICE_ERROR :                 return "DEVICE_ERROR";
63         case EFI_WRITE_PROTECTED :              return "WRITE_PROTECTED";
64         case EFI_OUT_OF_RESOURCES :             return "OUT_OF_RESOURCES";
65         case EFI_VOLUME_CORRUPTED :             return "VOLUME_CORRUPTED";
66         case EFI_VOLUME_FULL :                  return "VOLUME_FULL";
67         case EFI_NO_MEDIA :                     return "NO_MEDIA";
68         case EFI_MEDIA_CHANGED :                return "MEDIA_CHANGED";
69         case EFI_NOT_FOUND :                    return "NOT_FOUND";
70         case EFI_ACCESS_DENIED :                return "ACCESS_DENIED";
71         case EFI_NO_RESPONSE :                  return "NO_RESPONSE";
72         case EFI_NO_MAPPING :                   return "NO_MAPPING";
73         case EFI_TIMEOUT :                      return "TIMEOUT";
74         case EFI_NOT_STARTED :                  return "NOT_STARTED";
75         case EFI_ALREADY_STARTED :              return "ALREADY_STARTED";
76         case EFI_ABORTED :                      return "ABORTED";
77         case EFI_ICMP_ERROR :                   return "ICMP_ERROR";
78         case EFI_TFTP_ERROR :                   return "TFTP_ERROR";
79         case EFI_PROTOCOL_ERROR :               return "PROTOCOL_ERROR";
80         case EFI_INCOMPATIBLE_VERSION :         return "INCOMPATIBLE_VERSION";
81         case EFI_SECURITY_VIOLATION :           return "SECURITY_VIOLATION";
82         case EFI_CRC_ERROR :                    return "CRC_ERROR";
83         case EFI_END_OF_MEDIA :                 return "END_OF_MEDIA";
84         case EFI_END_OF_FILE :                  return "END_OF_FILE";
85         case EFI_INVALID_LANGUAGE :             return "INVALID_LANGUAGE";
86         case EFI_COMPROMISED_DATA :             return "COMPROMISED_DATA";
87         case EFI_WARN_UNKNOWN_GLYPH :           return "WARN_UNKNOWN_GLYPH";
88         case EFI_WARN_DELETE_FAILURE :          return "WARN_DELETE_FAILURE";
89         case EFI_WARN_WRITE_FAILURE :           return "WARN_WRITE_FAILURE";
90         case EFI_WARN_BUFFER_TOO_SMALL :        return "WARN_BUFFER_TOO_SMALL";
91         case EFI_WARN_STALE_DATA :              return "WARN_STALE_DATA";
92         default:
93                 snprintf ( buf, sizeof ( buf ), "%#lx",
94                            ( unsigned long ) efirc );
95                 return buf;
96         }
97 }
98
99 /**
100  * Wrap HandleProtocol()
101  *
102  */
103 static EFI_STATUS EFIAPI
104 efi_handle_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
105                               VOID **interface ) {
106         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
107         void *retaddr = __builtin_return_address ( 0 );
108         EFI_STATUS efirc;
109
110         DBGC ( colour, "HandleProtocol ( %p %s, %s, ... ) ", handle,
111                efi_handle_name ( handle ), efi_guid_ntoa ( protocol ) );
112         efirc = bs->HandleProtocol ( handle, protocol, interface );
113         DBGC ( colour, "= %s ( %p ) -> %p\n",
114                efi_status ( efirc ), *interface, retaddr );
115         return efirc;
116 }
117
118 /**
119  * Wrap LocateHandle()
120  *
121  */
122 static EFI_STATUS EFIAPI
123 efi_locate_handle_wrapper ( EFI_LOCATE_SEARCH_TYPE search_type,
124                             EFI_GUID *protocol, VOID *search_key,
125                             UINTN *buffer_size, EFI_HANDLE *buffer ) {
126         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
127         void *retaddr = __builtin_return_address ( 0 );
128         EFI_STATUS efirc;
129
130         DBGC ( colour, "LocateHandle ( %d, %s, ..., %zd, ... ) ", search_type,
131                efi_guid_ntoa ( protocol ), ( ( size_t ) *buffer_size ) );
132         efirc = bs->LocateHandle ( search_type, protocol, search_key,
133                                    buffer_size, buffer );
134         DBGC ( colour, "= %s ( %zd ) -> %p\n",
135                efi_status ( efirc ), ( ( size_t ) *buffer_size ), retaddr );
136         return efirc;
137 }
138
139 /**
140  * Wrap LocateDevicePath()
141  *
142  */
143 static EFI_STATUS EFIAPI
144 efi_locate_device_path_wrapper ( EFI_GUID *protocol,
145                                  EFI_DEVICE_PATH_PROTOCOL **device_path,
146                                  EFI_HANDLE *device ) {
147         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
148         void *retaddr = __builtin_return_address ( 0 );
149         EFI_STATUS efirc;
150
151         DBGC ( colour, "LocateDevicePath ( %s, %s, ... ) ",
152                efi_guid_ntoa ( protocol ), efi_devpath_text ( *device_path ) );
153         efirc = bs->LocateDevicePath ( protocol, device_path, device );
154         DBGC ( colour, "= %s ( %p, ",
155                efi_status ( efirc ), efi_devpath_text ( *device_path ) );
156         DBGC ( colour, "%p %s ) -> %p\n",
157                *device, efi_handle_name ( *device ), retaddr );
158         return efirc;
159 }
160
161 /**
162  * Wrap LoadImage()
163  *
164  */
165 static EFI_STATUS EFIAPI
166 efi_load_image_wrapper ( BOOLEAN boot_policy, EFI_HANDLE parent_image_handle,
167                          EFI_DEVICE_PATH_PROTOCOL *device_path,
168                          VOID *source_buffer, UINTN source_size,
169                          EFI_HANDLE *image_handle ) {
170         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
171         void *retaddr = __builtin_return_address ( 0 );
172         EFI_STATUS efirc;
173
174         DBGC ( colour, "LoadImage ( %d, %p %s, ", boot_policy,
175                parent_image_handle, efi_handle_name ( parent_image_handle ) );
176         DBGC ( colour, "%s, %p, %#llx, ... ) ",
177                efi_devpath_text ( device_path ), source_buffer,
178                ( ( unsigned long long ) source_size ) );
179         efirc = bs->LoadImage ( boot_policy, parent_image_handle, device_path,
180                                 source_buffer, source_size, image_handle );
181         DBGC ( colour, "= %s ( ", efi_status ( efirc ) );
182         if ( efirc == 0 ) {
183                 DBGC ( colour, "%p %s ", *image_handle,
184                        efi_handle_name ( *image_handle ) );
185         }
186         DBGC ( colour, ") -> %p\n", retaddr );
187
188         /* Wrap the new image */
189         if ( efirc == 0 )
190                 efi_wrap ( *image_handle );
191
192         return efirc;
193 }
194
195 /**
196  * Wrap ExitBootServices()
197  *
198  */
199 static EFI_STATUS EFIAPI
200 efi_exit_boot_services_wrapper ( EFI_HANDLE image_handle, UINTN map_key ) {
201         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
202         void *retaddr = __builtin_return_address ( 0 );
203         EFI_STATUS efirc;
204
205         DBGC ( colour, "ExitBootServices ( %p %s, %#llx ) ",
206                image_handle, efi_handle_name ( image_handle ),
207                ( ( unsigned long long ) map_key ) );
208         efirc = bs->ExitBootServices ( image_handle, map_key );
209         DBGC ( colour, "= %s -> %p\n", efi_status ( efirc ), retaddr );
210         return efirc;
211 }
212
213 /**
214  * Wrap OpenProtocol()
215  *
216  */
217 static EFI_STATUS EFIAPI
218 efi_open_protocol_wrapper ( EFI_HANDLE handle, EFI_GUID *protocol,
219                             VOID **interface, EFI_HANDLE agent_handle,
220                             EFI_HANDLE controller_handle, UINT32 attributes ) {
221         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
222         void *retaddr = __builtin_return_address ( 0 );
223         EFI_STATUS efirc;
224
225         DBGC ( colour, "OpenProtocol ( %p %s, %s, ..., ", handle,
226                efi_handle_name ( handle ), efi_guid_ntoa ( protocol ) );
227         DBGC ( colour, "%p %s, ", agent_handle,
228                efi_handle_name ( agent_handle ) );
229         DBGC ( colour, "%p %s, %#x ) ", controller_handle,
230                efi_handle_name ( controller_handle ), attributes );
231         efirc = bs->OpenProtocol ( handle, protocol, interface, agent_handle,
232                                    controller_handle, attributes );
233         DBGC ( colour, "= %s ( %p ) -> %p\n",
234                efi_status ( efirc ), *interface, retaddr );
235         return efirc;
236 }
237
238 /**
239  * Wrap LocateProtocol()
240  *
241  */
242 static EFI_STATUS EFIAPI
243 efi_locate_protocol_wrapper ( EFI_GUID *protocol, VOID *registration,
244                               VOID **interface ) {
245         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
246         void *retaddr = __builtin_return_address ( 0 );
247         EFI_STATUS efirc;
248
249         DBGC ( colour, "LocateProtocol ( %s, %p, ... ) ",
250                efi_guid_ntoa ( protocol ), registration );
251         efirc = bs->LocateProtocol ( protocol, registration, interface );
252         DBGC ( colour, "= %s ( %p ) -> %p\n",
253                efi_status ( efirc ), *interface, retaddr );
254         return efirc;
255 }
256
257 /**
258  * Wrap the calls made by a loaded image
259  *
260  * @v handle            Image handle
261  */
262  void efi_wrap ( EFI_HANDLE handle ) {
263         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
264         union {
265                 EFI_LOADED_IMAGE_PROTOCOL *image;
266                 void *intf;
267         } loaded;
268         EFI_STATUS efirc;
269         int rc;
270
271         /* Do nothing unless debugging is enabled */
272         if ( ! DBG_LOG )
273                 return;
274
275         /* Populate table wrappers */
276         memcpy ( &efi_systab_wrapper, efi_systab,
277                  sizeof ( efi_systab_wrapper ) );
278         memcpy ( &efi_bs_wrapper, bs, sizeof ( efi_bs_wrapper ) );
279         efi_systab_wrapper.BootServices = &efi_bs_wrapper;
280         efi_bs_wrapper.HandleProtocol   = efi_handle_protocol_wrapper;
281         efi_bs_wrapper.LocateHandle     = efi_locate_handle_wrapper;
282         efi_bs_wrapper.LocateDevicePath = efi_locate_device_path_wrapper;
283         efi_bs_wrapper.LoadImage        = efi_load_image_wrapper;
284         efi_bs_wrapper.ExitBootServices = efi_exit_boot_services_wrapper;
285         efi_bs_wrapper.OpenProtocol     = efi_open_protocol_wrapper;
286         efi_bs_wrapper.LocateProtocol   = efi_locate_protocol_wrapper;
287
288         /* Open loaded image protocol */
289         if ( ( efirc = bs->OpenProtocol ( handle,
290                                           &efi_loaded_image_protocol_guid,
291                                           &loaded.intf, efi_image_handle, NULL,
292                                           EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
293                 rc = -EEFI ( efirc );
294                 DBGC ( colour, "Could not get loaded image protocol for %p %s: "
295                        "%s\n", handle, efi_handle_name ( handle ),
296                        strerror ( rc ) );
297                 return;
298         }
299
300         /* Provide system table wrapper to image */
301         loaded.image->SystemTable = &efi_systab_wrapper;
302         DBGC ( colour, "Wrapped image %p %s at base %p has protocols:\n",
303                handle, efi_handle_name ( handle ), loaded.image->ImageBase );
304         DBGC_EFI_PROTOCOLS ( colour, handle );
305         DBGC ( colour, "Parent image %p %s\n", loaded.image->ParentHandle,
306                efi_handle_name ( loaded.image->ParentHandle ) );
307         DBGC ( colour, "Device %p %s ", loaded.image->DeviceHandle,
308                efi_handle_name ( loaded.image->DeviceHandle ) );
309         DBGC ( colour, "file %p %s\n", loaded.image->FilePath,
310                efi_devpath_text ( loaded.image->FilePath ) );
311
312         /* Close loaded image protocol */
313         bs->CloseProtocol ( handle, &efi_loaded_image_protocol_guid,
314                             efi_image_handle, NULL );
315 }