|
@@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
36
|
36
|
#include <ipxe/efi/efi.h>
|
37
|
37
|
#include <ipxe/efi/Protocol/SimpleFileSystem.h>
|
38
|
38
|
#include <ipxe/efi/Protocol/BlockIo.h>
|
|
39
|
+#include <ipxe/efi/Protocol/DiskIo.h>
|
39
|
40
|
#include <ipxe/efi/Guid/FileInfo.h>
|
40
|
41
|
#include <ipxe/efi/Guid/FileSystemInfo.h>
|
41
|
42
|
#include <ipxe/efi/efi_strings.h>
|
|
@@ -55,6 +56,10 @@ static EFI_GUID efi_file_system_info_id = EFI_FILE_SYSTEM_INFO_ID;
|
55
|
56
|
static EFI_GUID efi_block_io_protocol_guid
|
56
|
57
|
= EFI_BLOCK_IO_PROTOCOL_GUID;
|
57
|
58
|
|
|
59
|
+/** EFI disk I/O protocol GUID */
|
|
60
|
+static EFI_GUID efi_disk_io_protocol_guid
|
|
61
|
+ = EFI_DISK_IO_PROTOCOL_GUID;
|
|
62
|
+
|
58
|
63
|
/** EFI media ID */
|
59
|
64
|
#define EFI_MEDIA_ID_MAGIC 0x69505845
|
60
|
65
|
|
|
@@ -506,7 +511,7 @@ static EFI_STATUS EFIAPI
|
506
|
511
|
efi_block_io_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
|
507
|
512
|
UINT32 MediaId __unused, EFI_LBA lba __unused,
|
508
|
513
|
UINTN len __unused, VOID *data __unused ) {
|
509
|
|
- return EFI_DEVICE_ERROR;
|
|
514
|
+ return EFI_NO_MEDIA;
|
510
|
515
|
}
|
511
|
516
|
|
512
|
517
|
/** Dummy block I/O write */
|
|
@@ -514,7 +519,7 @@ static EFI_STATUS EFIAPI
|
514
|
519
|
efi_block_io_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused,
|
515
|
520
|
UINT32 MediaId __unused, EFI_LBA lba __unused,
|
516
|
521
|
UINTN len __unused, VOID *data __unused ) {
|
517
|
|
- return EFI_DEVICE_ERROR;
|
|
522
|
+ return EFI_NO_MEDIA;
|
518
|
523
|
}
|
519
|
524
|
|
520
|
525
|
/** Dummy block I/O flush */
|
|
@@ -541,6 +546,29 @@ static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = {
|
541
|
546
|
.FlushBlocks = efi_block_io_flush_blocks,
|
542
|
547
|
};
|
543
|
548
|
|
|
549
|
+/** Dummy disk I/O read */
|
|
550
|
+static EFI_STATUS EFIAPI
|
|
551
|
+efi_disk_io_read_disk ( EFI_DISK_IO_PROTOCOL *this __unused,
|
|
552
|
+ UINT32 MediaId __unused, UINT64 offset __unused,
|
|
553
|
+ UINTN len __unused, VOID *data __unused ) {
|
|
554
|
+ return EFI_NO_MEDIA;
|
|
555
|
+}
|
|
556
|
+
|
|
557
|
+/** Dummy disk I/O write */
|
|
558
|
+static EFI_STATUS EFIAPI
|
|
559
|
+efi_disk_io_write_disk ( EFI_DISK_IO_PROTOCOL *this __unused,
|
|
560
|
+ UINT32 MediaId __unused, UINT64 offset __unused,
|
|
561
|
+ UINTN len __unused, VOID *data __unused ) {
|
|
562
|
+ return EFI_NO_MEDIA;
|
|
563
|
+}
|
|
564
|
+
|
|
565
|
+/** Dummy EFI disk I/O protocol */
|
|
566
|
+static EFI_DISK_IO_PROTOCOL efi_disk_io_protocol = {
|
|
567
|
+ .Revision = EFI_DISK_IO_PROTOCOL_REVISION,
|
|
568
|
+ .ReadDisk = efi_disk_io_read_disk,
|
|
569
|
+ .WriteDisk = efi_disk_io_write_disk,
|
|
570
|
+};
|
|
571
|
+
|
544
|
572
|
/**
|
545
|
573
|
* Install EFI simple file system protocol
|
546
|
574
|
*
|
|
@@ -549,29 +577,79 @@ static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = {
|
549
|
577
|
*/
|
550
|
578
|
int efi_file_install ( EFI_HANDLE *handle ) {
|
551
|
579
|
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
|
580
|
+ union {
|
|
581
|
+ EFI_DISK_IO_PROTOCOL *diskio;
|
|
582
|
+ void *interface;
|
|
583
|
+ } diskio;
|
552
|
584
|
EFI_STATUS efirc;
|
553
|
585
|
int rc;
|
554
|
586
|
|
555
|
|
- /* Install the simple file system protocol and the block I/O
|
556
|
|
- * protocol. We don't have a block device, but large parts of
|
557
|
|
- * the EDK2 codebase make the assumption that file systems are
|
558
|
|
- * normally attached to block devices, and so we create a
|
559
|
|
- * dummy block device on the same handle just to keep things
|
560
|
|
- * looking normal.
|
|
587
|
+ /* Install the simple file system protocol, block I/O
|
|
588
|
+ * protocol, and disk I/O protocol. We don't have a block
|
|
589
|
+ * device, but large parts of the EDK2 codebase make the
|
|
590
|
+ * assumption that file systems are normally attached to block
|
|
591
|
+ * devices, and so we create a dummy block device on the same
|
|
592
|
+ * handle just to keep things looking normal.
|
561
|
593
|
*/
|
562
|
594
|
if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
563
|
595
|
handle,
|
564
|
596
|
&efi_block_io_protocol_guid,
|
565
|
597
|
&efi_block_io_protocol,
|
|
598
|
+ &efi_disk_io_protocol_guid,
|
|
599
|
+ &efi_disk_io_protocol,
|
566
|
600
|
&efi_simple_file_system_protocol_guid,
|
567
|
601
|
&efi_simple_file_system_protocol, NULL ) ) != 0 ) {
|
568
|
602
|
rc = -EEFI ( efirc );
|
569
|
|
- DBGC ( handle, "Could not install simple file system protocol: "
|
570
|
|
- "%s\n", strerror ( rc ) );
|
571
|
|
- return rc;
|
|
603
|
+ DBGC ( handle, "Could not install simple file system "
|
|
604
|
+ "protocols: %s\n", strerror ( rc ) );
|
|
605
|
+ goto err_install;
|
|
606
|
+ }
|
|
607
|
+
|
|
608
|
+ /* The FAT filesystem driver has a bug: if a block device
|
|
609
|
+ * contains no FAT filesystem but does have an
|
|
610
|
+ * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance, the FAT driver
|
|
611
|
+ * will assume that it must have previously installed the
|
|
612
|
+ * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This causes the FAT
|
|
613
|
+ * driver to claim control of our device, and to refuse to
|
|
614
|
+ * stop driving it, which prevents us from later uninstalling
|
|
615
|
+ * correctly.
|
|
616
|
+ *
|
|
617
|
+ * Work around this bug by opening the disk I/O protocol
|
|
618
|
+ * ourselves, thereby preventing the FAT driver from opening
|
|
619
|
+ * it.
|
|
620
|
+ *
|
|
621
|
+ * Note that the alternative approach of opening the block I/O
|
|
622
|
+ * protocol (and thereby in theory preventing DiskIo from
|
|
623
|
+ * attaching to the block I/O protocol) causes an endless loop
|
|
624
|
+ * of calls to our DRIVER_STOP method when starting the EFI
|
|
625
|
+ * shell. I have no idea why this is.
|
|
626
|
+ */
|
|
627
|
+ if ( ( efirc = bs->OpenProtocol ( *handle, &efi_disk_io_protocol_guid,
|
|
628
|
+ &diskio.interface, efi_image_handle,
|
|
629
|
+ *handle,
|
|
630
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER ) ) != 0){
|
|
631
|
+ rc = -EEFI ( efirc );
|
|
632
|
+ DBGC ( handle, "Could not open disk I/O protocol: %s\n",
|
|
633
|
+ strerror ( rc ) );
|
|
634
|
+ goto err_open;
|
572
|
635
|
}
|
|
636
|
+ assert ( diskio.diskio == &efi_disk_io_protocol );
|
573
|
637
|
|
574
|
638
|
return 0;
|
|
639
|
+
|
|
640
|
+ bs->CloseProtocol ( *handle, &efi_disk_io_protocol_guid,
|
|
641
|
+ efi_image_handle, *handle );
|
|
642
|
+ err_open:
|
|
643
|
+ bs->UninstallMultipleProtocolInterfaces (
|
|
644
|
+ *handle,
|
|
645
|
+ &efi_simple_file_system_protocol_guid,
|
|
646
|
+ &efi_simple_file_system_protocol,
|
|
647
|
+ &efi_disk_io_protocol_guid,
|
|
648
|
+ &efi_disk_io_protocol,
|
|
649
|
+ &efi_block_io_protocol_guid,
|
|
650
|
+ &efi_block_io_protocol, NULL );
|
|
651
|
+ err_install:
|
|
652
|
+ return rc;
|
575
|
653
|
}
|
576
|
654
|
|
577
|
655
|
/**
|
|
@@ -581,16 +659,29 @@ int efi_file_install ( EFI_HANDLE *handle ) {
|
581
|
659
|
*/
|
582
|
660
|
void efi_file_uninstall ( EFI_HANDLE handle ) {
|
583
|
661
|
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
|
662
|
+ EFI_STATUS efirc;
|
|
663
|
+ int rc;
|
|
664
|
+
|
|
665
|
+ /* Close our own disk I/O protocol */
|
|
666
|
+ bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
|
|
667
|
+ efi_image_handle, handle );
|
584
|
668
|
|
585
|
669
|
/* We must install the file system protocol first, since
|
586
|
670
|
* otherwise the EDK2 code will attempt to helpfully uninstall
|
587
|
671
|
* it when the block I/O protocol is uninstalled, leading to a
|
588
|
672
|
* system lock-up.
|
589
|
673
|
*/
|
590
|
|
- bs->UninstallMultipleProtocolInterfaces (
|
|
674
|
+ if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
591
|
675
|
handle,
|
592
|
676
|
&efi_simple_file_system_protocol_guid,
|
593
|
677
|
&efi_simple_file_system_protocol,
|
|
678
|
+ &efi_disk_io_protocol_guid,
|
|
679
|
+ &efi_disk_io_protocol,
|
594
|
680
|
&efi_block_io_protocol_guid,
|
595
|
|
- &efi_block_io_protocol, NULL );
|
|
681
|
+ &efi_block_io_protocol, NULL ) ) != 0 ) {
|
|
682
|
+ rc = -EEFI ( efirc );
|
|
683
|
+ DBGC ( handle, "Could not uninstall simple file system "
|
|
684
|
+ "protocols: %s\n", strerror ( rc ) );
|
|
685
|
+ /* Oh dear */
|
|
686
|
+ }
|
596
|
687
|
}
|