iPXE
Data Structures | Defines | Functions | Variables
efi_file.c File Reference

EFI file protocols. More...

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <wchar.h>
#include <ipxe/image.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/SimpleFileSystem.h>
#include <ipxe/efi/Protocol/BlockIo.h>
#include <ipxe/efi/Protocol/DiskIo.h>
#include <ipxe/efi/Guid/FileInfo.h>
#include <ipxe/efi/Guid/FileSystemInfo.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_file.h>

Go to the source code of this file.

Data Structures

struct  efi_file
 An image exposed as an EFI file. More...

Defines

#define EFI_MEDIA_ID_MAGIC   0x69505845
 EFI media ID.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static const char * efi_file_name (struct efi_file *file)
 Get EFI file name (for debugging)
static struct imageefi_file_find (const CHAR16 *wname)
 Find EFI file image.
static EFI_STATUS EFIAPI efi_file_open (EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, CHAR16 *wname, UINT64 mode __unused, UINT64 attributes __unused)
 Open file.
static EFI_STATUS EFIAPI efi_file_close (EFI_FILE_PROTOCOL *this)
 Close file.
static EFI_STATUS EFIAPI efi_file_delete (EFI_FILE_PROTOCOL *this)
 Close and delete file.
static EFI_STATUS efi_file_varlen (UINT64 *base, size_t base_len, const char *name, UINTN *len, VOID *data)
 Return variable-length data structure.
static EFI_STATUS efi_file_info (struct image *image, UINTN *len, VOID *data)
 Return file information structure.
static EFI_STATUS efi_file_read_dir (struct efi_file *file, UINTN *len, VOID *data)
 Read directory entry.
static EFI_STATUS EFIAPI efi_file_read (EFI_FILE_PROTOCOL *this, UINTN *len, VOID *data)
 Read from file.
static EFI_STATUS EFIAPI efi_file_write (EFI_FILE_PROTOCOL *this, UINTN *len, VOID *data __unused)
 Write to file.
static EFI_STATUS EFIAPI efi_file_set_position (EFI_FILE_PROTOCOL *this, UINT64 position)
 Set file position.
static EFI_STATUS EFIAPI efi_file_get_position (EFI_FILE_PROTOCOL *this, UINT64 *position)
 Get file position.
static EFI_STATUS EFIAPI efi_file_get_info (EFI_FILE_PROTOCOL *this, EFI_GUID *type, UINTN *len, VOID *data)
 Get file information.
static EFI_STATUS EFIAPI efi_file_set_info (EFI_FILE_PROTOCOL *this, EFI_GUID *type, UINTN len __unused, VOID *data __unused)
 Set file information.
static EFI_STATUS EFIAPI efi_file_flush (EFI_FILE_PROTOCOL *this)
 Flush file modified data.
static EFI_STATUS EFIAPI efi_file_open_volume (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused, EFI_FILE_PROTOCOL **file)
 Open root directory.
static EFI_STATUS EFIAPI efi_block_io_reset (EFI_BLOCK_IO_PROTOCOL *this __unused, BOOLEAN extended)
 Dummy block I/O reset.
static EFI_STATUS EFIAPI efi_block_io_read_blocks (EFI_BLOCK_IO_PROTOCOL *this __unused, UINT32 MediaId, EFI_LBA lba, UINTN len, VOID *data)
 Dummy block I/O read.
static EFI_STATUS EFIAPI efi_block_io_write_blocks (EFI_BLOCK_IO_PROTOCOL *this __unused, UINT32 MediaId, EFI_LBA lba, UINTN len, VOID *data)
 Dummy block I/O write.
static EFI_STATUS EFIAPI efi_block_io_flush_blocks (EFI_BLOCK_IO_PROTOCOL *this __unused)
 Dummy block I/O flush.
static EFI_STATUS EFIAPI efi_disk_io_read_disk (EFI_DISK_IO_PROTOCOL *this __unused, UINT32 MediaId, UINT64 offset, UINTN len, VOID *data)
 Dummy disk I/O read.
static EFI_STATUS EFIAPI efi_disk_io_write_disk (EFI_DISK_IO_PROTOCOL *this __unused, UINT32 MediaId, UINT64 offset, UINTN len, VOID *data)
 Dummy disk I/O write.
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.

Variables

static struct efi_file efi_file_root
 Root directory.
static
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 
efi_simple_file_system_protocol
 EFI simple file system protocol.
static EFI_BLOCK_IO_MEDIA efi_block_io_media
 Dummy block I/O media.
static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol
 Dummy EFI block I/O protocol.
static EFI_DISK_IO_PROTOCOL efi_disk_io_protocol
 Dummy EFI disk I/O protocol.

Detailed Description

EFI file protocols.

Definition in file efi_file.c.


Define Documentation

#define EFI_MEDIA_ID_MAGIC   0x69505845

EFI media ID.

Definition at line 51 of file efi_file.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static const char* efi_file_name ( struct efi_file file) [static]

Get EFI file name (for debugging)

Parameters:
fileEFI file
Return values:
nameName

Definition at line 71 of file efi_file.c.

References efi_file::image, and image::name.

Referenced by efi_file_close(), efi_file_delete(), efi_file_flush(), efi_file_get_info(), efi_file_open(), efi_file_read(), efi_file_set_info(), efi_file_set_position(), and efi_file_write().

                                                            {

        return ( file->image ? file->image->name : "<root>" );
}
static struct image* efi_file_find ( const CHAR16 wname) [static, read]

Find EFI file image.

Parameters:
wnameFilename
Return values:
imageImage, or NULL

Definition at line 82 of file efi_file.c.

References images, image::list, list_for_each_entry, image::name, name, NULL, snprintf(), strcasecmp(), and wcslen().

Referenced by efi_file_open().

                                                            {
        char name[ wcslen ( wname ) + 1 /* NUL */ ];
        struct image *image;

        /* Find image */
        snprintf ( name, sizeof ( name ), "%ls", wname );
        list_for_each_entry ( image, &images, list ) {
                if ( strcasecmp ( image->name, name ) == 0 )
                        return image;
        }

        return NULL;

}
static EFI_STATUS EFIAPI efi_file_open ( EFI_FILE_PROTOCOL this,
EFI_FILE_PROTOCOL **  new,
CHAR16 wname,
UINT64 mode  __unused,
UINT64 attributes  __unused 
) [static]

Open file.

Parameters:
thisEFI file
Return values:
newNew EFI file
Parameters:
wnameFilename
modeFile mode
attributesFile attributes (for newly-created files)
Return values:
efircEFI status code

Definition at line 108 of file efi_file.c.

References container_of, DBGC, efi_file_find(), EFI_FILE_MODE_READ, efi_file_name(), efi_file_root, EFI_NOT_FOUND, EFI_WRITE_PROTECTED, efi_file::file, efi_file::image, image_get(), memcpy(), image::name, and zalloc().

                                             {
        struct efi_file *file = container_of ( this, struct efi_file, file );
        struct efi_file *new_file;
        struct image *image;

        /* Initial '\' indicates opening from the root directory */
        while ( *wname == L'\\' ) {
                file = &efi_file_root;
                wname++;
        }

        /* Allow root directory itself to be opened */
        if ( ( wname[0] == L'\0' ) || ( wname[0] == L'.' ) ) {
                *new = &efi_file_root.file;
                return 0;
        }

        /* Fail unless opening from the root */
        if ( file->image ) {
                DBGC ( file, "EFIFILE %s is not a directory\n",
                       efi_file_name ( file ) );
                return EFI_NOT_FOUND;
        }

        /* Identify image */
        image = efi_file_find ( wname );
        if ( ! image ) {
                DBGC ( file, "EFIFILE \"%ls\" does not exist\n", wname );
                return EFI_NOT_FOUND;
        }

        /* Fail unless opening read-only */
        if ( mode != EFI_FILE_MODE_READ ) {
                DBGC ( file, "EFIFILE %s cannot be opened in mode %#08llx\n",
                       image->name, mode );
                return EFI_WRITE_PROTECTED;
        }

        /* Allocate and initialise file */
        new_file = zalloc ( sizeof ( *new_file ) );
        memcpy ( &new_file->file, &efi_file_root.file,
                 sizeof ( new_file->file ) );
        new_file->image = image_get ( image );
        *new = &new_file->file;
        DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) );

        return 0;
}
static EFI_STATUS EFIAPI efi_file_close ( EFI_FILE_PROTOCOL this) [static]

Close file.

Parameters:
thisEFI file
Return values:
efircEFI status code

Definition at line 165 of file efi_file.c.

References container_of, DBGC, efi_file_name(), efi_file::file, free, efi_file::image, and image_put().

Referenced by efi_file_delete().

                                                                    {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        /* Do nothing if this is the root */
        if ( ! file->image )
                return 0;

        /* Close file */
        DBGC ( file, "EFIFILE %s closed\n", efi_file_name ( file ) );
        image_put ( file->image );
        free ( file );

        return 0;
}
static EFI_STATUS EFIAPI efi_file_delete ( EFI_FILE_PROTOCOL this) [static]

Close and delete file.

Parameters:
thisEFI file
Return values:
efircEFI status code

Definition at line 186 of file efi_file.c.

References container_of, DBGC, efi_file_close(), efi_file_name(), EFI_WARN_DELETE_FAILURE, and efi_file::file.

                                                                     {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        DBGC ( file, "EFIFILE %s cannot be deleted\n", efi_file_name ( file ) );

        /* Close file */
        efi_file_close ( this );

        /* Warn of failure to delete */
        return EFI_WARN_DELETE_FAILURE;
}
static EFI_STATUS efi_file_varlen ( UINT64 base,
size_t  base_len,
const char *  name,
UINTN len,
VOID data 
) [static]

Return variable-length data structure.

Parameters:
baseBase data structure (starting with UINT64)
base_lenLength of base data structure
nameName to append to base data structure
lenLength of data buffer
dataData buffer
Return values:
efircEFI status code

Definition at line 208 of file efi_file.c.

References base, EFI_BUFFER_TOO_SMALL, efi_snprintf(), memcpy(), and strlen().

Referenced by efi_file_get_info(), and efi_file_info().

                                                                               {
        size_t name_len;

        /* Calculate structure length */
        name_len = strlen ( name );
        *base = ( base_len + ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
        if ( *len < *base ) {
                *len = *base;
                return EFI_BUFFER_TOO_SMALL;
        }

        /* Copy data to buffer */
        *len = *base;
        memcpy ( data, base, base_len );
        efi_snprintf ( ( data + base_len ), ( name_len + 1 /* NUL */ ),
                       "%s", name );

        return 0;
}
static EFI_STATUS efi_file_info ( struct image image,
UINTN len,
VOID data 
) [static]

Return file information structure.

Parameters:
imageImage, or NULL for the root directory
lenLength of data buffer
dataData buffer
Return values:
efircEFI status code

Definition at line 237 of file efi_file.c.

References EFI_FILE_INFO::Attribute, EFI_FILE_DIRECTORY, EFI_FILE_READ_ONLY, efi_file_varlen(), EFI_FILE_INFO::FileSize, info, image::len, memset(), image::name, name, EFI_FILE_INFO::PhysicalSize, EFI_FILE_INFO::Size, and SIZE_OF_EFI_FILE_INFO.

Referenced by efi_file_get_info(), and efi_file_read_dir().

                                               {
        EFI_FILE_INFO info;
        const char *name;

        /* Populate file information */
        memset ( &info, 0, sizeof ( info ) );
        if ( image ) {
                info.FileSize = image->len;
                info.PhysicalSize = image->len;
                info.Attribute = EFI_FILE_READ_ONLY;
                name = image->name;
        } else {
                info.Attribute = ( EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY );
                name = "";
        }

        return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, name,
                                 len, data );
}
static EFI_STATUS efi_file_read_dir ( struct efi_file file,
UINTN len,
VOID data 
) [static]

Read directory entry.

Parameters:
fileEFI file
lenLength to read
dataData buffer
Return values:
efircEFI status code

Definition at line 266 of file efi_file.c.

References efi_file_info(), for_each_image, index, and efi_file::pos.

Referenced by efi_file_read().

                                                   {
        EFI_STATUS efirc;
        struct image *image;
        unsigned int index;

        /* Construct directory entry at current position */
        index = file->pos;
        for_each_image ( image ) {
                if ( index-- == 0 ) {
                        efirc = efi_file_info ( image, len, data );
                        if ( efirc == 0 )
                                file->pos++;
                        return efirc;
                }
        }

        /* No more entries */
        *len = 0;
        return 0;
}
static EFI_STATUS EFIAPI efi_file_read ( EFI_FILE_PROTOCOL this,
UINTN len,
VOID data 
) [static]

Read from file.

Parameters:
thisEFI file
lenLength to read
dataData buffer
Return values:
efircEFI status code

Definition at line 296 of file efi_file.c.

References container_of, copy_from_user(), image::data, DBGC, efi_file_name(), efi_file_read_dir(), efi_file::file, efi_file::image, image::len, len, and efi_file::pos.

                                                                  {
        struct efi_file *file = container_of ( this, struct efi_file, file );
        size_t remaining;

        /* If this is the root directory, then construct a directory entry */
        if ( ! file->image )
                return efi_file_read_dir ( file, len, data );

        /* Read from the file */
        remaining = ( file->image->len - file->pos );
        if ( *len > remaining )
                *len = remaining;
        DBGC ( file, "EFIFILE %s read [%#08zx,%#08zx)\n",
               efi_file_name ( file ), file->pos,
               ( ( size_t ) ( file->pos + *len ) ) );
        copy_from_user ( data, file->image->data, file->pos, *len );
        file->pos += *len;
        return 0;
}
static EFI_STATUS EFIAPI efi_file_write ( EFI_FILE_PROTOCOL this,
UINTN len,
VOID *data  __unused 
) [static]

Write to file.

Parameters:
thisEFI file
lenLength to write
dataData buffer
Return values:
efircEFI status code

Definition at line 325 of file efi_file.c.

References container_of, DBGC, efi_file_name(), EFI_WRITE_PROTECTED, efi_file::file, and efi_file::pos.

                                                                            {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        DBGC ( file, "EFIFILE %s cannot write [%#08zx, %#08zx)\n",
               efi_file_name ( file ), file->pos,
               ( ( size_t ) ( file->pos + *len ) ) );
        return EFI_WRITE_PROTECTED;
}
static EFI_STATUS EFIAPI efi_file_set_position ( EFI_FILE_PROTOCOL this,
UINT64  position 
) [static]

Set file position.

Parameters:
thisEFI file
positionNew file position
Return values:
efircEFI status code

Definition at line 342 of file efi_file.c.

References container_of, DBGC, efi_file_name(), EFI_UNSUPPORTED, efi_file::file, efi_file::image, image::len, and efi_file::pos.

                                                                   {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        /* If this is the root directory, reset to the start */
        if ( ! file->image ) {
                DBGC ( file, "EFIFILE root directory rewound\n" );
                file->pos = 0;
                return 0;
        }

        /* Check for the magic end-of-file value */
        if ( position == 0xffffffffffffffffULL )
                position = file->image->len;

        /* Fail if we attempt to seek past the end of the file (since
         * we do not support writes).
         */
        if ( position > file->image->len ) {
                DBGC ( file, "EFIFILE %s cannot seek to %#08llx of %#08zx\n",
                       efi_file_name ( file ), position, file->image->len );
                return EFI_UNSUPPORTED;
        }

        /* Set position */
        file->pos = position;
        DBGC ( file, "EFIFILE %s position set to %#08zx\n",
               efi_file_name ( file ), file->pos );

        return 0;
}
static EFI_STATUS EFIAPI efi_file_get_position ( EFI_FILE_PROTOCOL this,
UINT64 position 
) [static]

Get file position.

Parameters:
thisEFI file
Return values:
positionNew file position
efircEFI status code

Definition at line 381 of file efi_file.c.

References container_of, efi_file::file, and efi_file::pos.

                                                                    {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        *position = file->pos;
        return 0;
}
static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL this,
EFI_GUID type,
UINTN len,
VOID data 
) [static]

Get file information.

Parameters:
thisEFI file
typeType of information
lenBuffer size
dataBuffer
Return values:
efircEFI status code

Definition at line 398 of file efi_file.c.

References container_of, DBGC, efi_file_info(), efi_file_info_id, efi_file_name(), efi_file_system_info_id, efi_file_varlen(), efi_guid_ntoa(), EFI_UNSUPPORTED, efi_file::file, for_each_image, efi_file::image, image::len, memcmp(), memset(), EFI_FILE_SYSTEM_INFO::ReadOnly, EFI_FILE_SYSTEM_INFO::Size, SIZE_OF_EFI_FILE_SYSTEM_INFO, and EFI_FILE_SYSTEM_INFO::VolumeSize.

                                                                      {
        struct efi_file *file = container_of ( this, struct efi_file, file );
        EFI_FILE_SYSTEM_INFO fsinfo;
        struct image *image;

        /* Determine information to return */
        if ( memcmp ( type, &efi_file_info_id, sizeof ( *type ) ) == 0 ) {

                /* Get file information */
                DBGC ( file, "EFIFILE %s get file information\n",
                       efi_file_name ( file ) );
                return efi_file_info ( file->image, len, data );

        } else if ( memcmp ( type, &efi_file_system_info_id,
                             sizeof ( *type ) ) == 0 ) {

                /* Get file system information */
                DBGC ( file, "EFIFILE %s get file system information\n",
                       efi_file_name ( file ) );
                memset ( &fsinfo, 0, sizeof ( fsinfo ) );
                fsinfo.ReadOnly = 1;
                for_each_image ( image )
                        fsinfo.VolumeSize += image->len;
                return efi_file_varlen ( &fsinfo.Size,
                                         SIZE_OF_EFI_FILE_SYSTEM_INFO, "iPXE",
                                         len, data );
        } else {

                DBGC ( file, "EFIFILE %s cannot get information of type %s\n",
                       efi_file_name ( file ), efi_guid_ntoa ( type ) );
                return EFI_UNSUPPORTED;
        }
}
static EFI_STATUS EFIAPI efi_file_set_info ( EFI_FILE_PROTOCOL this,
EFI_GUID type,
UINTN len  __unused,
VOID *data  __unused 
) [static]

Set file information.

Parameters:
thisEFI file
typeType of information
lenBuffer size
dataBuffer
Return values:
efircEFI status code

Definition at line 444 of file efi_file.c.

References container_of, DBGC, efi_file_name(), efi_guid_ntoa(), EFI_WRITE_PROTECTED, and efi_file::file.

                                                              {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        DBGC ( file, "EFIFILE %s cannot set information of type %s\n",
               efi_file_name ( file ), efi_guid_ntoa ( type ) );
        return EFI_WRITE_PROTECTED;
}
static EFI_STATUS EFIAPI efi_file_flush ( EFI_FILE_PROTOCOL this) [static]

Flush file modified data.

Parameters:
thisEFI file
typeType of information
lenBuffer size
dataBuffer
Return values:
efircEFI status code

Definition at line 462 of file efi_file.c.

References container_of, DBGC, efi_file_name(), and efi_file::file.

                                                                    {
        struct efi_file *file = container_of ( this, struct efi_file, file );

        DBGC ( file, "EFIFILE %s flushed\n", efi_file_name ( file ) );
        return 0;
}

Open root directory.

Parameters:
filesystemEFI simple file system
Return values:
fileEFI file handle
efircEFI status code

Definition at line 495 of file efi_file.c.

References DBGC, and efi_file::file.

                                                  {

        DBGC ( &efi_file_root, "EFIFILE open volume\n" );
        *file = &efi_file_root.file;
        return 0;
}
static EFI_STATUS EFIAPI efi_block_io_reset ( EFI_BLOCK_IO_PROTOCOL *this  __unused,
BOOLEAN  extended 
) [static]

Dummy block I/O reset.

Definition at line 511 of file efi_file.c.

References DBGC.

                                                                              {

        DBGC ( &efi_file_root, "EFIFILE block %sreset\n",
               ( extended ? "extended " : "" ) );
        return 0;
}
static EFI_STATUS EFIAPI efi_block_io_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this  __unused,
UINT32  MediaId,
EFI_LBA  lba,
UINTN  len,
VOID data 
) [static]

Dummy block I/O read.

Definition at line 520 of file efi_file.c.

References DBGC, and EFI_NO_MEDIA.

                                                                {

        DBGC ( &efi_file_root, "EFIFILE block read ID %#08x LBA %#08llx -> "
               "%p+%zx\n", MediaId, ( ( unsigned long long ) lba ),
               data, ( ( size_t ) len ) );
        return EFI_NO_MEDIA;
}
static EFI_STATUS EFIAPI efi_block_io_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this  __unused,
UINT32  MediaId,
EFI_LBA  lba,
UINTN  len,
VOID data 
) [static]

Dummy block I/O write.

Definition at line 531 of file efi_file.c.

References DBGC, and EFI_NO_MEDIA.

                                         {

        DBGC ( &efi_file_root, "EFIFILE block write ID %#08x LBA %#08llx <- "
               "%p+%zx\n", MediaId, ( ( unsigned long long ) lba ),
               data, ( ( size_t ) len ) );
        return EFI_NO_MEDIA;
}

Dummy block I/O flush.

Definition at line 543 of file efi_file.c.

References DBGC.

                                                                   {

        DBGC ( &efi_file_root, "EFIFILE block flush\n" );
        return 0;
}
static EFI_STATUS EFIAPI efi_disk_io_read_disk ( EFI_DISK_IO_PROTOCOL *this  __unused,
UINT32  MediaId,
UINT64  offset,
UINTN  len,
VOID data 
) [static]

Dummy disk I/O read.

Definition at line 569 of file efi_file.c.

References DBGC, and EFI_NO_MEDIA.

                                                               {

        DBGC ( &efi_file_root, "EFIFILE disk read ID %#08x offset %#08llx -> "
               "%p+%zx\n", MediaId, ( ( unsigned long long ) offset ),
               data, ( ( size_t ) len ) );
        return EFI_NO_MEDIA;
}
static EFI_STATUS EFIAPI efi_disk_io_write_disk ( EFI_DISK_IO_PROTOCOL *this  __unused,
UINT32  MediaId,
UINT64  offset,
UINTN  len,
VOID data 
) [static]

Dummy disk I/O write.

Definition at line 580 of file efi_file.c.

References DBGC, and EFI_NO_MEDIA.

                                                                {

        DBGC ( &efi_file_root, "EFIFILE disk write ID %#08x offset %#08llx <- "
               "%p+%zx\n", MediaId, ( ( unsigned long long ) offset ),
               data, ( ( size_t ) len ) );
        return EFI_NO_MEDIA;
}
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 */
        }
}

Variable Documentation

static struct efi_file efi_file_root [static]
Initial value:
 {
        .file = {
                .Revision = EFI_FILE_PROTOCOL_REVISION,
                .Open = efi_file_open,
                .Close = efi_file_close,
                .Delete = efi_file_delete,
                .Read = efi_file_read,
                .Write = efi_file_write,
                .GetPosition = efi_file_get_position,
                .SetPosition = efi_file_set_position,
                .GetInfo = efi_file_get_info,
                .SetInfo = efi_file_set_info,
                .Flush = efi_file_flush,
        },
        .image = NULL,
}

Root directory.

Definition at line 63 of file efi_file.c.

Referenced by efi_file_open().

Initial value:

EFI simple file system protocol.

Definition at line 504 of file efi_file.c.

Initial value:
 {
        .MediaId = EFI_MEDIA_ID_MAGIC,
        .MediaPresent = TRUE,
        .ReadOnly = TRUE,
        .BlockSize = 1,
}

Dummy block I/O media.

Definition at line 550 of file efi_file.c.

Initial value:

Dummy EFI block I/O protocol.

Definition at line 558 of file efi_file.c.

Initial value:
 {
        .Revision = EFI_DISK_IO_PROTOCOL_REVISION,
        .ReadDisk = efi_disk_io_read_disk,
        .WriteDisk = efi_disk_io_write_disk,
}

Dummy EFI disk I/O protocol.

Definition at line 590 of file efi_file.c.