Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

efi_wrap.c 11KB

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