[U-Boot] [PATCH 0/2] efi_loader: EFI_FILE_PROTOCOL

This patch series contains correction for the EFI_FILE_PROTOCOL.
The formation type EFI_FILE_SYSTEM_INFO in the service GetInfo() of the EFI_FILE_PROTOCOL is implemented.
Heinrich Schuchardt (2): efi_loader: use correct types in EFI_FILE_PROTOCOL efi_loader: implement EFI_FILE_SYSTEM_INFO
include/efi_api.h | 27 +++++++--- include/efi_loader.h | 2 + lib/efi_loader/efi_boottime.c | 5 +- lib/efi_loader/efi_file.c | 81 +++++++++++++++++++++++----- lib/efi_selftest/efi_selftest_block_device.c | 2 +- 5 files changed, 96 insertions(+), 21 deletions(-)

In the EFI_FILE_PROTOCOL buffer sizes and positions are passed as UINTN and not as u64.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- include/efi_api.h | 14 +++++---- lib/efi_loader/efi_boottime.c | 5 +-- lib/efi_loader/efi_file.c | 47 +++++++++++++++++++++------- lib/efi_selftest/efi_selftest_block_device.c | 2 +- 4 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/include/efi_api.h b/include/efi_api.h index c8a41a499d..43c8c891e7 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -837,17 +837,19 @@ struct efi_file_handle { efi_status_t (EFIAPI *close)(struct efi_file_handle *file); efi_status_t (EFIAPI *delete)(struct efi_file_handle *file); efi_status_t (EFIAPI *read)(struct efi_file_handle *file, - u64 *buffer_size, void *buffer); + efi_uintn_t *buffer_size, void *buffer); efi_status_t (EFIAPI *write)(struct efi_file_handle *file, - u64 *buffer_size, void *buffer); + efi_uintn_t *buffer_size, void *buffer); efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file, - u64 *pos); + efi_uintn_t *pos); efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file, - u64 pos); + efi_uintn_t pos); efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file, - efi_guid_t *info_type, u64 *buffer_size, void *buffer); + efi_guid_t *info_type, efi_uintn_t *buffer_size, + void *buffer); efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file, - efi_guid_t *info_type, u64 buffer_size, void *buffer); + efi_guid_t *info_type, efi_uintn_t buffer_size, + void *buffer); efi_status_t (EFIAPI *flush)(struct efi_file_handle *file); };
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d15a131e74..7a9449f59c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1513,7 +1513,7 @@ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, struct efi_file_info *info = NULL; struct efi_file_handle *f; static efi_status_t ret; - uint64_t bs; + efi_uintn_t bs;
f = efi_file_from_path(file_path); if (!f) @@ -1534,7 +1534,8 @@ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, if (ret) goto error;
- EFI_CALL(ret = f->read(f, &info->file_size, *buffer)); + bs = info->file_size; + EFI_CALL(ret = f->read(f, &bs, *buffer));
error: free(info); diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 52a4e7438e..1e2751f7cf 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -314,29 +314,41 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, }
static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file, - u64 *buffer_size, void *buffer) + efi_uintn_t *buffer_size, void *buffer) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; + u64 bs;
EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+ if (!buffer_size || !buffer) { + ret = EFI_INVALID_PARAMETER; + goto error; + } + if (set_blk_dev(fh)) { ret = EFI_DEVICE_ERROR; goto error; }
+ bs = *buffer_size; if (fh->isdir) - ret = dir_read(fh, buffer_size, buffer); + ret = dir_read(fh, &bs, buffer); else - ret = file_read(fh, buffer_size, buffer); + ret = file_read(fh, &bs, buffer); + if (bs <= SIZE_MAX) + *buffer_size = bs; + else + *buffer_size = SIZE_MAX;
error: return EFI_EXIT(ret); }
static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file, - u64 *buffer_size, void *buffer) + efi_uintn_t *buffer_size, + void *buffer) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; @@ -363,21 +375,27 @@ error: }
static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file, - u64 *pos) + efi_uintn_t *pos) { struct file_handle *fh = to_fh(file); + EFI_ENTRY("%p, %p", file, pos); - *pos = fh->offset; - return EFI_EXIT(EFI_SUCCESS); + + if (fh->offset <= SIZE_MAX) { + *pos = fh->offset; + return EFI_EXIT(EFI_SUCCESS); + } else { + return EFI_EXIT(EFI_DEVICE_ERROR); + } }
static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, - u64 pos) + efi_uintn_t pos) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS;
- EFI_ENTRY("%p, %llu", file, pos); + EFI_ENTRY("%p, %zu", file, pos);
if (fh->isdir) { if (pos != 0) { @@ -411,7 +429,9 @@ error: }
static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, - efi_guid_t *info_type, u64 *buffer_size, void *buffer) + efi_guid_t *info_type, + efi_uintn_t *buffer_size, + void *buffer) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; @@ -461,9 +481,12 @@ error: }
static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, - efi_guid_t *info_type, u64 buffer_size, void *buffer) + efi_guid_t *info_type, + efi_uintn_t buffer_size, + void *buffer) { - EFI_ENTRY("%p, %p, %llu, %p", file, info_type, buffer_size, buffer); + EFI_ENTRY("%p, %p, %zu, %p", file, info_type, buffer_size, buffer); + return EFI_EXIT(EFI_UNSUPPORTED); }
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index 9e4b93d9a6..b07b22465f 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -302,7 +302,7 @@ static int execute(void) struct efi_device_path *dp_partition; struct efi_simple_file_system_protocol *file_system; struct efi_file_handle *root, *file; - u64 buf_size; + efi_uintn_t buf_size; char buf[16] __aligned(ARCH_DMA_MINALIGN);
ret = boottime->connect_controller(disk_handle, NULL, NULL, 1);

Implement the information type EFI_FILE_SYSTEM_INFO in the service GetInfo() of the EFI_FILE_PROTOCOL.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- include/efi_api.h | 13 +++++++++++++ include/efi_loader.h | 2 ++ lib/efi_loader/efi_file.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+)
diff --git a/include/efi_api.h b/include/efi_api.h index 43c8c891e7..16da736113 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -868,6 +868,10 @@ struct efi_simple_file_system_protocol { EFI_GUID(0x9576e92, 0x6d3f, 0x11d2, \ 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_FILE_SYSTEM_INFO_GUID \ + EFI_GUID(0x09576e93, 0x6d3f, 0x11d2, \ + 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + #define EFI_FILE_MODE_READ 0x0000000000000001 #define EFI_FILE_MODE_WRITE 0x0000000000000002 #define EFI_FILE_MODE_CREATE 0x8000000000000000 @@ -891,6 +895,15 @@ struct efi_file_info { s16 file_name[0]; };
+struct efi_file_system_info { + u64 size; + u8 read_only; + u64 volume_size; + u64 free_space; + u32 block_size; + u16 volume_label[0]; +}; + #define EFI_DRIVER_BINDING_PROTOCOL_GUID \ EFI_GUID(0x18a031ab, 0xb443, 0x4d1a,\ 0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71) diff --git a/include/efi_loader.h b/include/efi_loader.h index ee553c667f..ab20773947 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -112,6 +112,8 @@ extern const efi_guid_t efi_guid_loaded_image; extern const efi_guid_t efi_guid_device_path_to_text_protocol; extern const efi_guid_t efi_simple_file_system_protocol_guid; extern const efi_guid_t efi_file_info_guid; +/* GUID for file system information */ +extern const efi_guid_t efi_file_system_info_guid; extern const efi_guid_t efi_guid_device_path_utilities_protocol;
extern unsigned int __efi_runtime_start, __efi_runtime_stop; diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 1e2751f7cf..37a999d0b2 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -12,6 +12,9 @@ #include <malloc.h> #include <fs.h>
+/* GUID for file system information */ +const efi_guid_t efi_file_system_info_guid = EFI_FILE_SYSTEM_INFO_GUID; + struct file_system { struct efi_simple_file_system_protocol base; struct efi_device_path *dp; @@ -472,6 +475,37 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, info->attribute |= EFI_FILE_DIRECTORY;
ascii2unicode((u16 *)info->file_name, filename); + } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { + struct efi_file_system_info *info = buffer; + disk_partition_t part; + efi_uintn_t required_size; + int r; + + if (fh->fs->part >= 1) + r = part_get_info(fh->fs->desc, fh->fs->part, &part); + else + r = part_get_info_whole_disk(fh->fs->desc, &part); + if (r < 0) { + ret = EFI_DEVICE_ERROR; + goto error; + } + required_size = sizeof(info) + 2 * + (strlen((const char *)part.name) + 1); + if (*buffer_size < required_size) { + *buffer_size = required_size; + ret = EFI_BUFFER_TOO_SMALL; + goto error; + } + + memset(info, 0, required_size); + + info->size = required_size; + info->read_only = true; + info->volume_size = part.size * part.blksz; + info->free_space = 0; + info->block_size = part.blksz; + ascii2unicode((u16 *)info->volume_label, + (const char *)part.name); } else { ret = EFI_UNSUPPORTED; }
participants (1)
-
Heinrich Schuchardt