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