Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

efi_file.c 19KB

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