選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

efi_file.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * Copyright (C) 2013 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. FILE_LICENCE ( GPL2_OR_LATER );
  20. /**
  21. * @file
  22. *
  23. * EFI file protocols
  24. *
  25. */
  26. #include <stddef.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #include <wchar.h>
  32. #include <ipxe/image.h>
  33. #include <ipxe/efi/efi.h>
  34. #include <ipxe/efi/Protocol/SimpleFileSystem.h>
  35. #include <ipxe/efi/Protocol/BlockIo.h>
  36. #include <ipxe/efi/Protocol/DiskIo.h>
  37. #include <ipxe/efi/Guid/FileInfo.h>
  38. #include <ipxe/efi/Guid/FileSystemInfo.h>
  39. #include <ipxe/efi/efi_strings.h>
  40. #include <ipxe/efi/efi_file.h>
  41. /** EFI simple file system protocol GUID */
  42. static EFI_GUID efi_simple_file_system_protocol_guid
  43. = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
  44. /** EFI file information GUID */
  45. static EFI_GUID efi_file_info_id = EFI_FILE_INFO_ID;
  46. /** EFI file system information GUID */
  47. static EFI_GUID efi_file_system_info_id = EFI_FILE_SYSTEM_INFO_ID;
  48. /** EFI block I/O protocol GUID */
  49. static EFI_GUID efi_block_io_protocol_guid
  50. = EFI_BLOCK_IO_PROTOCOL_GUID;
  51. /** EFI disk I/O protocol GUID */
  52. static EFI_GUID efi_disk_io_protocol_guid
  53. = EFI_DISK_IO_PROTOCOL_GUID;
  54. /** EFI media ID */
  55. #define EFI_MEDIA_ID_MAGIC 0x69505845
  56. /** An image exposed as an EFI file */
  57. struct efi_file {
  58. /** EFI file protocol */
  59. EFI_FILE_PROTOCOL file;
  60. /** Image */
  61. struct image *image;
  62. /** Current file position */
  63. size_t pos;
  64. };
  65. static struct efi_file efi_file_root;
  66. /**
  67. * Get EFI file name (for debugging)
  68. *
  69. * @v file EFI file
  70. * @ret name Name
  71. */
  72. static const char * efi_file_name ( struct efi_file *file ) {
  73. return ( file->image ? file->image->name : "<root>" );
  74. }
  75. /**
  76. * Open file
  77. *
  78. * @v this EFI file
  79. * @ret new New EFI file
  80. * @v wname Filename
  81. * @v mode File mode
  82. * @v attributes File attributes (for newly-created files)
  83. * @ret efirc EFI status code
  84. */
  85. static EFI_STATUS EFIAPI
  86. efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
  87. CHAR16 *wname, UINT64 mode __unused,
  88. UINT64 attributes __unused ) {
  89. struct efi_file *file = container_of ( this, struct efi_file, file );
  90. char name[ wcslen ( wname ) + 1 /* NUL */ ];
  91. struct efi_file *new_file;
  92. struct image *image;
  93. /* Initial '\' indicates opening from the root directory */
  94. while ( *wname == L'\\' ) {
  95. file = &efi_file_root;
  96. wname++;
  97. }
  98. /* Allow root directory itself to be opened */
  99. if ( ( wname[0] == L'\0' ) || ( wname[0] == L'.' ) ) {
  100. *new = &efi_file_root.file;
  101. return 0;
  102. }
  103. /* Fail unless opening from the root */
  104. if ( file->image ) {
  105. DBGC ( file, "EFIFILE %s is not a directory\n",
  106. efi_file_name ( file ) );
  107. return EFI_NOT_FOUND;
  108. }
  109. /* Identify image */
  110. snprintf ( name, sizeof ( name ), "%ls", wname );
  111. image = find_image ( name );
  112. if ( ! image ) {
  113. DBGC ( file, "EFIFILE \"%s\" does not exist\n", name );
  114. return EFI_NOT_FOUND;
  115. }
  116. /* Fail unless opening read-only */
  117. if ( mode != EFI_FILE_MODE_READ ) {
  118. DBGC ( file, "EFIFILE %s cannot be opened in mode %#08llx\n",
  119. image->name, mode );
  120. return EFI_WRITE_PROTECTED;
  121. }
  122. /* Allocate and initialise file */
  123. new_file = zalloc ( sizeof ( *new_file ) );
  124. memcpy ( &new_file->file, &efi_file_root.file,
  125. sizeof ( new_file->file ) );
  126. new_file->image = image_get ( image );
  127. *new = &new_file->file;
  128. DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) );
  129. return 0;
  130. }
  131. /**
  132. * Close file
  133. *
  134. * @v this EFI file
  135. * @ret efirc EFI status code
  136. */
  137. static EFI_STATUS EFIAPI efi_file_close ( EFI_FILE_PROTOCOL *this ) {
  138. struct efi_file *file = container_of ( this, struct efi_file, file );
  139. /* Do nothing if this is the root */
  140. if ( ! file->image )
  141. return 0;
  142. /* Close file */
  143. DBGC ( file, "EFIFILE %s closed\n", efi_file_name ( file ) );
  144. image_put ( file->image );
  145. free ( file );
  146. return 0;
  147. }
  148. /**
  149. * Close and delete file
  150. *
  151. * @v this EFI file
  152. * @ret efirc EFI status code
  153. */
  154. static EFI_STATUS EFIAPI efi_file_delete ( EFI_FILE_PROTOCOL *this ) {
  155. struct efi_file *file = container_of ( this, struct efi_file, file );
  156. DBGC ( file, "EFIFILE %s cannot be deleted\n", efi_file_name ( file ) );
  157. /* Close file */
  158. efi_file_close ( this );
  159. /* Warn of failure to delete */
  160. return EFI_WARN_DELETE_FAILURE;
  161. }
  162. /**
  163. * Return variable-length data structure
  164. *
  165. * @v base Base data structure (starting with UINT64)
  166. * @v base_len Length of base data structure
  167. * @v name Name to append to base data structure
  168. * @v len Length of data buffer
  169. * @v data Data buffer
  170. * @ret efirc EFI status code
  171. */
  172. static EFI_STATUS efi_file_varlen ( UINT64 *base, size_t base_len,
  173. const char *name, UINTN *len, VOID *data ) {
  174. size_t name_len;
  175. /* Calculate structure length */
  176. name_len = strlen ( name );
  177. *base = ( base_len + ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
  178. if ( *len < *base ) {
  179. *len = *base;
  180. return EFI_BUFFER_TOO_SMALL;
  181. }
  182. /* Copy data to buffer */
  183. *len = *base;
  184. memcpy ( data, base, base_len );
  185. efi_snprintf ( ( data + base_len ), ( name_len + 1 /* NUL */ ),
  186. "%s", name );
  187. return 0;
  188. }
  189. /**
  190. * Return file information structure
  191. *
  192. * @v image Image, or NULL for the root directory
  193. * @v len Length of data buffer
  194. * @v data Data buffer
  195. * @ret efirc EFI status code
  196. */
  197. static EFI_STATUS efi_file_info ( struct image *image, UINTN *len,
  198. VOID *data ) {
  199. EFI_FILE_INFO info;
  200. const char *name;
  201. /* Populate file information */
  202. memset ( &info, 0, sizeof ( info ) );
  203. if ( image ) {
  204. info.FileSize = image->len;
  205. info.PhysicalSize = image->len;
  206. info.Attribute = EFI_FILE_READ_ONLY;
  207. name = image->name;
  208. } else {
  209. info.Attribute = ( EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY );
  210. name = "";
  211. }
  212. return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, name,
  213. len, data );
  214. }
  215. /**
  216. * Read directory entry
  217. *
  218. * @v file EFI file
  219. * @v len Length to read
  220. * @v data Data buffer
  221. * @ret efirc EFI status code
  222. */
  223. static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len,
  224. VOID *data ) {
  225. EFI_STATUS efirc;
  226. struct image *image;
  227. unsigned int index;
  228. /* Construct directory entry at current position */
  229. index = file->pos;
  230. for_each_image ( image ) {
  231. if ( index-- == 0 ) {
  232. efirc = efi_file_info ( image, len, data );
  233. if ( efirc == 0 )
  234. file->pos++;
  235. return efirc;
  236. }
  237. }
  238. /* No more entries */
  239. *len = 0;
  240. return 0;
  241. }
  242. /**
  243. * Read from file
  244. *
  245. * @v this EFI file
  246. * @v len Length to read
  247. * @v data Data buffer
  248. * @ret efirc EFI status code
  249. */
  250. static EFI_STATUS EFIAPI efi_file_read ( EFI_FILE_PROTOCOL *this,
  251. UINTN *len, VOID *data ) {
  252. struct efi_file *file = container_of ( this, struct efi_file, file );
  253. size_t remaining;
  254. /* If this is the root directory, then construct a directory entry */
  255. if ( ! file->image )
  256. return efi_file_read_dir ( file, len, data );
  257. /* Read from the file */
  258. remaining = ( file->image->len - file->pos );
  259. if ( *len > remaining )
  260. *len = remaining;
  261. DBGC ( file, "EFIFILE %s read [%#08zx,%#08zx)\n",
  262. efi_file_name ( file ), file->pos,
  263. ( ( size_t ) ( file->pos + *len ) ) );
  264. copy_from_user ( data, file->image->data, file->pos, *len );
  265. file->pos += *len;
  266. return 0;
  267. }
  268. /**
  269. * Write to file
  270. *
  271. * @v this EFI file
  272. * @v len Length to write
  273. * @v data Data buffer
  274. * @ret efirc EFI status code
  275. */
  276. static EFI_STATUS EFIAPI efi_file_write ( EFI_FILE_PROTOCOL *this,
  277. UINTN *len, VOID *data __unused ) {
  278. struct efi_file *file = container_of ( this, struct efi_file, file );
  279. DBGC ( file, "EFIFILE %s cannot write [%#08zx, %#08zx)\n",
  280. efi_file_name ( file ), file->pos,
  281. ( ( size_t ) ( file->pos + *len ) ) );
  282. return EFI_WRITE_PROTECTED;
  283. }
  284. /**
  285. * Set file position
  286. *
  287. * @v this EFI file
  288. * @v position New file position
  289. * @ret efirc EFI status code
  290. */
  291. static EFI_STATUS EFIAPI efi_file_set_position ( EFI_FILE_PROTOCOL *this,
  292. UINT64 position ) {
  293. struct efi_file *file = container_of ( this, struct efi_file, file );
  294. /* If this is the root directory, reset to the start */
  295. if ( ! file->image ) {
  296. DBGC ( file, "EFIFILE root directory rewound\n" );
  297. file->pos = 0;
  298. return 0;
  299. }
  300. /* Check for the magic end-of-file value */
  301. if ( position == 0xffffffffffffffffULL )
  302. position = file->image->len;
  303. /* Fail if we attempt to seek past the end of the file (since
  304. * we do not support writes).
  305. */
  306. if ( position > file->image->len ) {
  307. DBGC ( file, "EFIFILE %s cannot seek to %#08llx of %#08zx\n",
  308. efi_file_name ( file ), position, file->image->len );
  309. return EFI_UNSUPPORTED;
  310. }
  311. /* Set position */
  312. file->pos = position;
  313. DBGC ( file, "EFIFILE %s position set to %#08zx\n",
  314. efi_file_name ( file ), file->pos );
  315. return 0;
  316. }
  317. /**
  318. * Get file position
  319. *
  320. * @v this EFI file
  321. * @ret position New file position
  322. * @ret efirc EFI status code
  323. */
  324. static EFI_STATUS EFIAPI efi_file_get_position ( EFI_FILE_PROTOCOL *this,
  325. UINT64 *position ) {
  326. struct efi_file *file = container_of ( this, struct efi_file, file );
  327. *position = file->pos;
  328. return 0;
  329. }
  330. /**
  331. * Get file information
  332. *
  333. * @v this EFI file
  334. * @v type Type of information
  335. * @v len Buffer size
  336. * @v data Buffer
  337. * @ret efirc EFI status code
  338. */
  339. static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL *this,
  340. EFI_GUID *type,
  341. UINTN *len, VOID *data ) {
  342. struct efi_file *file = container_of ( this, struct efi_file, file );
  343. EFI_FILE_SYSTEM_INFO fsinfo;
  344. struct image *image;
  345. /* Determine information to return */
  346. if ( memcmp ( type, &efi_file_info_id, sizeof ( *type ) ) == 0 ) {
  347. /* Get file information */
  348. DBGC ( file, "EFIFILE %s get file information\n",
  349. efi_file_name ( file ) );
  350. return efi_file_info ( file->image, len, data );
  351. } else if ( memcmp ( type, &efi_file_system_info_id,
  352. sizeof ( *type ) ) == 0 ) {
  353. /* Get file system information */
  354. DBGC ( file, "EFIFILE %s get file system information\n",
  355. efi_file_name ( file ) );
  356. memset ( &fsinfo, 0, sizeof ( fsinfo ) );
  357. fsinfo.ReadOnly = 1;
  358. for_each_image ( image )
  359. fsinfo.VolumeSize += image->len;
  360. return efi_file_varlen ( &fsinfo.Size,
  361. SIZE_OF_EFI_FILE_SYSTEM_INFO, "iPXE",
  362. len, data );
  363. } else {
  364. DBGC ( file, "EFIFILE %s cannot get information of type %s\n",
  365. efi_file_name ( file ), efi_guid_ntoa ( type ) );
  366. return EFI_UNSUPPORTED;
  367. }
  368. }
  369. /**
  370. * Set file information
  371. *
  372. * @v this EFI file
  373. * @v type Type of information
  374. * @v len Buffer size
  375. * @v data Buffer
  376. * @ret efirc EFI status code
  377. */
  378. static EFI_STATUS EFIAPI
  379. efi_file_set_info ( EFI_FILE_PROTOCOL *this, EFI_GUID *type,
  380. UINTN len __unused, VOID *data __unused ) {
  381. struct efi_file *file = container_of ( this, struct efi_file, file );
  382. DBGC ( file, "EFIFILE %s cannot set information of type %s\n",
  383. efi_file_name ( file ), efi_guid_ntoa ( type ) );
  384. return EFI_WRITE_PROTECTED;
  385. }
  386. /**
  387. * Flush file modified data
  388. *
  389. * @v this EFI file
  390. * @v type Type of information
  391. * @v len Buffer size
  392. * @v data Buffer
  393. * @ret efirc EFI status code
  394. */
  395. static EFI_STATUS EFIAPI efi_file_flush ( EFI_FILE_PROTOCOL *this ) {
  396. struct efi_file *file = container_of ( this, struct efi_file, file );
  397. DBGC ( file, "EFIFILE %s flushed\n", efi_file_name ( file ) );
  398. return 0;
  399. }
  400. /** Root directory */
  401. static struct efi_file efi_file_root = {
  402. .file = {
  403. .Revision = EFI_FILE_PROTOCOL_REVISION,
  404. .Open = efi_file_open,
  405. .Close = efi_file_close,
  406. .Delete = efi_file_delete,
  407. .Read = efi_file_read,
  408. .Write = efi_file_write,
  409. .GetPosition = efi_file_get_position,
  410. .SetPosition = efi_file_set_position,
  411. .GetInfo = efi_file_get_info,
  412. .SetInfo = efi_file_set_info,
  413. .Flush = efi_file_flush,
  414. },
  415. .image = NULL,
  416. };
  417. /**
  418. * Open root directory
  419. *
  420. * @v filesystem EFI simple file system
  421. * @ret file EFI file handle
  422. * @ret efirc EFI status code
  423. */
  424. static EFI_STATUS EFIAPI
  425. efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused,
  426. EFI_FILE_PROTOCOL **file ) {
  427. *file = &efi_file_root.file;
  428. return 0;
  429. }
  430. /** EFI simple file system protocol */
  431. static EFI_SIMPLE_FILE_SYSTEM_PROTOCOL efi_simple_file_system_protocol = {
  432. .Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
  433. .OpenVolume = efi_file_open_volume,
  434. };
  435. /** Dummy block I/O reset */
  436. static EFI_STATUS EFIAPI
  437. efi_block_io_reset ( EFI_BLOCK_IO_PROTOCOL *this __unused,
  438. BOOLEAN extended __unused ) {
  439. return 0;
  440. }
  441. /** Dummy block I/O read */
  442. static EFI_STATUS EFIAPI
  443. efi_block_io_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
  444. UINT32 MediaId __unused, EFI_LBA lba __unused,
  445. UINTN len __unused, VOID *data __unused ) {
  446. return EFI_NO_MEDIA;
  447. }
  448. /** Dummy block I/O write */
  449. static EFI_STATUS EFIAPI
  450. efi_block_io_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
  451. UINT32 MediaId __unused, EFI_LBA lba __unused,
  452. UINTN len __unused, VOID *data __unused ) {
  453. return EFI_NO_MEDIA;
  454. }
  455. /** Dummy block I/O flush */
  456. static EFI_STATUS EFIAPI
  457. efi_block_io_flush_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused ) {
  458. return 0;
  459. }
  460. /** Dummy block I/O media */
  461. static EFI_BLOCK_IO_MEDIA efi_block_io_media = {
  462. .MediaId = EFI_MEDIA_ID_MAGIC,
  463. .MediaPresent = 1,
  464. .ReadOnly = 1,
  465. .BlockSize = 1,
  466. };
  467. /** Dummy EFI block I/O protocol */
  468. static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = {
  469. .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION,
  470. .Media = &efi_block_io_media,
  471. .Reset = efi_block_io_reset,
  472. .ReadBlocks = efi_block_io_read_blocks,
  473. .WriteBlocks = efi_block_io_write_blocks,
  474. .FlushBlocks = efi_block_io_flush_blocks,
  475. };
  476. /** Dummy disk I/O read */
  477. static EFI_STATUS EFIAPI
  478. efi_disk_io_read_disk ( EFI_DISK_IO_PROTOCOL *this __unused,
  479. UINT32 MediaId __unused, UINT64 offset __unused,
  480. UINTN len __unused, VOID *data __unused ) {
  481. return EFI_NO_MEDIA;
  482. }
  483. /** Dummy disk I/O write */
  484. static EFI_STATUS EFIAPI
  485. efi_disk_io_write_disk ( EFI_DISK_IO_PROTOCOL *this __unused,
  486. UINT32 MediaId __unused, UINT64 offset __unused,
  487. UINTN len __unused, VOID *data __unused ) {
  488. return EFI_NO_MEDIA;
  489. }
  490. /** Dummy EFI disk I/O protocol */
  491. static EFI_DISK_IO_PROTOCOL efi_disk_io_protocol = {
  492. .Revision = EFI_DISK_IO_PROTOCOL_REVISION,
  493. .ReadDisk = efi_disk_io_read_disk,
  494. .WriteDisk = efi_disk_io_write_disk,
  495. };
  496. /**
  497. * Install EFI simple file system protocol
  498. *
  499. * @v handle EFI handle
  500. * @ret rc Return status code
  501. */
  502. int efi_file_install ( EFI_HANDLE handle ) {
  503. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  504. union {
  505. EFI_DISK_IO_PROTOCOL *diskio;
  506. void *interface;
  507. } diskio;
  508. EFI_STATUS efirc;
  509. int rc;
  510. /* Install the simple file system protocol, block I/O
  511. * protocol, and disk I/O protocol. We don't have a block
  512. * device, but large parts of the EDK2 codebase make the
  513. * assumption that file systems are normally attached to block
  514. * devices, and so we create a dummy block device on the same
  515. * handle just to keep things looking normal.
  516. */
  517. if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
  518. &handle,
  519. &efi_block_io_protocol_guid,
  520. &efi_block_io_protocol,
  521. &efi_disk_io_protocol_guid,
  522. &efi_disk_io_protocol,
  523. &efi_simple_file_system_protocol_guid,
  524. &efi_simple_file_system_protocol, NULL ) ) != 0 ) {
  525. rc = -EEFI ( efirc );
  526. DBGC ( handle, "Could not install simple file system "
  527. "protocols: %s\n", strerror ( rc ) );
  528. goto err_install;
  529. }
  530. /* The FAT filesystem driver has a bug: if a block device
  531. * contains no FAT filesystem but does have an
  532. * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance, the FAT driver
  533. * will assume that it must have previously installed the
  534. * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This causes the FAT
  535. * driver to claim control of our device, and to refuse to
  536. * stop driving it, which prevents us from later uninstalling
  537. * correctly.
  538. *
  539. * Work around this bug by opening the disk I/O protocol
  540. * ourselves, thereby preventing the FAT driver from opening
  541. * it.
  542. *
  543. * Note that the alternative approach of opening the block I/O
  544. * protocol (and thereby in theory preventing DiskIo from
  545. * attaching to the block I/O protocol) causes an endless loop
  546. * of calls to our DRIVER_STOP method when starting the EFI
  547. * shell. I have no idea why this is.
  548. */
  549. if ( ( efirc = bs->OpenProtocol ( handle, &efi_disk_io_protocol_guid,
  550. &diskio.interface, efi_image_handle,
  551. handle,
  552. EFI_OPEN_PROTOCOL_BY_DRIVER ) ) != 0){
  553. rc = -EEFI ( efirc );
  554. DBGC ( handle, "Could not open disk I/O protocol: %s\n",
  555. strerror ( rc ) );
  556. DBGC_EFI_OPENERS ( handle, handle, &efi_disk_io_protocol_guid );
  557. goto err_open;
  558. }
  559. assert ( diskio.diskio == &efi_disk_io_protocol );
  560. return 0;
  561. bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
  562. efi_image_handle, handle );
  563. err_open:
  564. bs->UninstallMultipleProtocolInterfaces (
  565. handle,
  566. &efi_simple_file_system_protocol_guid,
  567. &efi_simple_file_system_protocol,
  568. &efi_disk_io_protocol_guid,
  569. &efi_disk_io_protocol,
  570. &efi_block_io_protocol_guid,
  571. &efi_block_io_protocol, NULL );
  572. err_install:
  573. return rc;
  574. }
  575. /**
  576. * Uninstall EFI simple file system protocol
  577. *
  578. * @v handle EFI handle
  579. */
  580. void efi_file_uninstall ( EFI_HANDLE handle ) {
  581. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  582. EFI_STATUS efirc;
  583. int rc;
  584. /* Close our own disk I/O protocol */
  585. bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
  586. efi_image_handle, handle );
  587. /* We must install the file system protocol first, since
  588. * otherwise the EDK2 code will attempt to helpfully uninstall
  589. * it when the block I/O protocol is uninstalled, leading to a
  590. * system lock-up.
  591. */
  592. if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
  593. handle,
  594. &efi_simple_file_system_protocol_guid,
  595. &efi_simple_file_system_protocol,
  596. &efi_disk_io_protocol_guid,
  597. &efi_disk_io_protocol,
  598. &efi_block_io_protocol_guid,
  599. &efi_block_io_protocol, NULL ) ) != 0 ) {
  600. rc = -EEFI ( efirc );
  601. DBGC ( handle, "Could not uninstall simple file system "
  602. "protocols: %s\n", strerror ( rc ) );
  603. /* Oh dear */
  604. }
  605. }