diff options
author | Heinrich Schuchardt | 2019-09-07 22:34:07 +0200 |
---|---|---|
committer | Heinrich Schuchardt | 2019-09-09 15:21:08 +0200 |
commit | 83a74ad14370b75051cabfc2eab01fd8556f3bdb (patch) | |
tree | bbbb1f4d57e019c0780df6d8f8162f25f76b0744 /lib | |
parent | 87c4840610e037018b9df30b1a31896b0bd284a9 (diff) |
efi_loader: correct reading of directories
EFI_FILE_PROTOCOL.Read() is used both to read files and directories.
When reaching the end of a directory we always have to return buffer size
zero irrespective of the incoming buffer size. (The described scenario for
a Shim quirk cannot arise because every directory has at least '.' and '..'
as entries.)
Even when the buffer_size is too small multiple times we have to keep a
reference to our last read directory entry.
When we return to the start of the directory via SetPosition() we must
remove the reference to a previously kept directory entry.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_file.c | 23 |
1 files changed, 5 insertions, 18 deletions
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 9f78b822419..74ad878217a 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -338,7 +338,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, { struct efi_file_info *info = buffer; struct fs_dirent *dent; - unsigned int required_size; + u64 required_size; u16 *dst; if (!fh->dirs) { @@ -346,6 +346,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, fh->dirs = fs_opendir(fh->path); if (!fh->dirs) return EFI_DEVICE_ERROR; + fh->dent = NULL; } /* @@ -356,28 +357,13 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, */ if (fh->dent) { dent = fh->dent; - fh->dent = NULL; } else { dent = fs_readdir(fh->dirs); } - if (!dent) { - /* no more files in directory: */ - /* workaround shim.efi bug/quirk.. as find_boot_csv() - * loops through directory contents, it initially calls - * read w/ zero length buffer to find out how much mem - * to allocate for the EFI_FILE_INFO, then allocates, - * and then calls a 2nd time. If we return size of - * zero the first time, it happily passes that to - * AllocateZeroPool(), and when that returns NULL it - * thinks it is EFI_OUT_OF_RESOURCES. So on first - * call return a non-zero size: - */ - if (*buffer_size == 0) - *buffer_size = sizeof(*info); - else - *buffer_size = 0; + /* no more files in directory */ + *buffer_size = 0; return EFI_SUCCESS; } @@ -389,6 +375,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, fh->dent = dent; return EFI_BUFFER_TOO_SMALL; } + fh->dent = NULL; *buffer_size = required_size; memset(info, 0, required_size); |