[U-Boot] [PATCH 3/4] efi_loader: correct reading of directories

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Sep 7 23:59:49 UTC 2019


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 at gmx.de>
---
 lib/efi_loader/efi_file.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 9f78b82241..74ad878217 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);
--
2.20.1



More information about the U-Boot mailing list