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