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