iPXE
Functions
efi_file.h File Reference

EFI file protocols. More...

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int efi_file_install (EFI_HANDLE handle)
 Install EFI simple file system protocol.
void efi_file_uninstall (EFI_HANDLE handle)
 Uninstall EFI simple file system protocol.

Detailed Description

EFI file protocols.

Definition in file efi_file.h.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int efi_file_install ( EFI_HANDLE  handle)

Install EFI simple file system protocol.

Parameters:
handleEFI handle
Return values:
rcReturn status code

Definition at line 602 of file efi_file.c.

References assert, EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, DBGC_EFI_OPENERS, EEFI, efi_block_io_protocol_guid, efi_disk_io_protocol_guid, efi_image_handle, EFI_OPEN_PROTOCOL_BY_DRIVER, efi_simple_file_system_protocol_guid, efi_systab, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, NULL, EFI_BOOT_SERVICES::OpenProtocol, efi_file::pos, rc, strerror(), and EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces.

Referenced by efi_image_exec().

                                           {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        union {
                EFI_DISK_IO_PROTOCOL *diskio;
                void *interface;
        } diskio;
        EFI_STATUS efirc;
        int rc;

        /* Reset root directory state */
        efi_file_root.pos = 0;

        /* Install the simple file system protocol, block I/O
         * protocol, and disk I/O protocol.  We don't have a block
         * device, but large parts of the EDK2 codebase make the
         * assumption that file systems are normally attached to block
         * devices, and so we create a dummy block device on the same
         * handle just to keep things looking normal.
         */
        if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
                        &handle,
                        &efi_block_io_protocol_guid,
                        &efi_block_io_protocol,
                        &efi_disk_io_protocol_guid,
                        &efi_disk_io_protocol,
                        &efi_simple_file_system_protocol_guid,
                        &efi_simple_file_system_protocol, NULL ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( handle, "Could not install simple file system "
                       "protocols: %s\n", strerror ( rc ) );
                goto err_install;
        }

        /* The FAT filesystem driver has a bug: if a block device
         * contains no FAT filesystem but does have an
         * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance, the FAT driver
         * will assume that it must have previously installed the
         * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.  This causes the FAT
         * driver to claim control of our device, and to refuse to
         * stop driving it, which prevents us from later uninstalling
         * correctly.
         *
         * Work around this bug by opening the disk I/O protocol
         * ourselves, thereby preventing the FAT driver from opening
         * it.
         *
         * Note that the alternative approach of opening the block I/O
         * protocol (and thereby in theory preventing DiskIo from
         * attaching to the block I/O protocol) causes an endless loop
         * of calls to our DRIVER_STOP method when starting the EFI
         * shell.  I have no idea why this is.
         */
        if ( ( efirc = bs->OpenProtocol ( handle, &efi_disk_io_protocol_guid,
                                          &diskio.interface, efi_image_handle,
                                          handle,
                                          EFI_OPEN_PROTOCOL_BY_DRIVER ) ) != 0){
                rc = -EEFI ( efirc );
                DBGC ( handle, "Could not open disk I/O protocol: %s\n",
                       strerror ( rc ) );
                DBGC_EFI_OPENERS ( handle, handle, &efi_disk_io_protocol_guid );
                goto err_open;
        }
        assert ( diskio.diskio == &efi_disk_io_protocol );

        return 0;

        bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
                            efi_image_handle, handle );
 err_open:
        bs->UninstallMultipleProtocolInterfaces (
                        handle,
                        &efi_simple_file_system_protocol_guid,
                        &efi_simple_file_system_protocol,
                        &efi_disk_io_protocol_guid,
                        &efi_disk_io_protocol,
                        &efi_block_io_protocol_guid,
                        &efi_block_io_protocol, NULL );
 err_install:
        return rc;
}
void efi_file_uninstall ( EFI_HANDLE  handle)

Uninstall EFI simple file system protocol.

Parameters:
handleEFI handle

Definition at line 688 of file efi_file.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, EEFI, efi_block_io_protocol_guid, efi_disk_io_protocol_guid, efi_image_handle, efi_simple_file_system_protocol_guid, efi_systab, NULL, rc, strerror(), and EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces.

Referenced by efi_image_exec().

                                              {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        EFI_STATUS efirc;
        int rc;

        /* Close our own disk I/O protocol */
        bs->CloseProtocol ( handle, &efi_disk_io_protocol_guid,
                            efi_image_handle, handle );

        /* We must install the file system protocol first, since
         * otherwise the EDK2 code will attempt to helpfully uninstall
         * it when the block I/O protocol is uninstalled, leading to a
         * system lock-up.
         */
        if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
                        handle,
                        &efi_simple_file_system_protocol_guid,
                        &efi_simple_file_system_protocol,
                        &efi_disk_io_protocol_guid,
                        &efi_disk_io_protocol,
                        &efi_block_io_protocol_guid,
                        &efi_block_io_protocol, NULL ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( handle, "Could not uninstall simple file system "
                       "protocols: %s\n", strerror ( rc ) );
                /* Oh dear */
        }
}