Module Name:    src
Committed By:   jmcneill
Date:           Wed Jul 15 00:51:40 UTC 2020

Modified Files:
        src/sys/stand/efiboot: efiboot.h efidev.c efifile.c

Log Message:
Fixup OpenSimpleReadFile usage:
 - The "EFI_DEVICE_PATH **FilePath" parameter can change, so do not free
   the output. This was causing crashes on U-Boot when attempting to load
   boot.cfg, even if it didn't exist.
 - Allocate the SIMPLE_READ_FILE in advance and store a pointer to it in
   struct open_file.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/stand/efiboot/efiboot.h
cvs rdiff -u -r1.1 -r1.2 src/sys/stand/efiboot/efidev.c
cvs rdiff -u -r1.4 -r1.5 src/sys/stand/efiboot/efifile.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/stand/efiboot/efiboot.h
diff -u src/sys/stand/efiboot/efiboot.h:1.12 src/sys/stand/efiboot/efiboot.h:1.13
--- src/sys/stand/efiboot/efiboot.h:1.12	Fri Jun 26 03:23:04 2020
+++ src/sys/stand/efiboot/efiboot.h	Wed Jul 15 00:51:40 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: efiboot.h,v 1.12 2020/06/26 03:23:04 thorpej Exp $	*/
+/*	$NetBSD: efiboot.h,v 1.13 2020/07/15 00:51:40 jmcneill Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -82,7 +82,8 @@ int ucs2_to_utf8(const CHAR16 *, char **
 int utf8_to_ucs2(const char *, CHAR16 **, size_t *);
 
 /* efidev.c */
-int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
+int efi_device_path_depth(EFI_DEVICE_PATH *, int);
+int efi_device_path_count(EFI_DEVICE_PATH *);
 int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
 
 /* efinet.c */

Index: src/sys/stand/efiboot/efidev.c
diff -u src/sys/stand/efiboot/efidev.c:1.1 src/sys/stand/efiboot/efidev.c:1.2
--- src/sys/stand/efiboot/efidev.c:1.1	Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/efidev.c	Wed Jul 15 00:51:40 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: efidev.c,v 1.1 2018/08/26 21:28:18 jmcneill Exp $	*/
+/*	$NetBSD: efidev.c,v 1.2 2020/07/15 00:51:40 jmcneill Exp $	*/
 /*	$OpenBSD: efiboot.c,v 1.28 2017/11/25 19:02:07 patrick Exp $	*/
 
 /*
@@ -37,6 +37,19 @@ efi_device_path_depth(EFI_DEVICE_PATH *d
 }
 
 int
+efi_device_path_count(EFI_DEVICE_PATH *dp)
+{
+	int	count;
+
+	for (count = 0; ; dp = NextDevicePathNode(dp), count++) {
+		if (IsDevicePathEnd(dp))
+			break;
+	}
+
+	return (count);
+}
+
+int
 efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn)
 {
 	int	 i, cmp;

Index: src/sys/stand/efiboot/efifile.c
diff -u src/sys/stand/efiboot/efifile.c:1.4 src/sys/stand/efiboot/efifile.c:1.5
--- src/sys/stand/efiboot/efifile.c:1.4	Sat Jun 27 17:23:08 2020
+++ src/sys/stand/efiboot/efifile.c	Wed Jul 15 00:51:40 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: efifile.c,v 1.4 2020/06/27 17:23:08 jmcneill Exp $ */
+/* $NetBSD: efifile.c,v 1.5 2020/07/15 00:51:40 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -67,9 +67,9 @@ efi_file_system_probe(void)
 int
 efi_file_open(struct open_file *f, ...)
 {
-	EFI_DEVICE_PATH *dp;
-	SIMPLE_READ_FILE srf;
-	EFI_HANDLE device, file;
+	EFI_DEVICE_PATH *file_dp, *dp;
+	SIMPLE_READ_FILE *srf;
+	EFI_HANDLE device;
 	EFI_STATUS status;
 	UINTN vol;
 	const char *fname, *path;
@@ -86,30 +86,37 @@ efi_file_open(struct open_file *f, ...)
 	if (rv != 0)
 		return rv;
 
-	device = efi_vol[vol];
-
 	upath = NULL;
 	rv = utf8_to_ucs2(path, &upath, &len);
 	if (rv != 0)
 		return rv;
 
-	dp = FileDevicePath(device, upath);
+	file_dp = FileDevicePath(efi_vol[vol], upath);
 	FreePool(upath);
-	if (dp == NULL)
+	if (file_dp == NULL)
 		return EINVAL;
 
-	status = OpenSimpleReadFile(TRUE, NULL, 0, &dp, &file, &srf);
-	FreePool(dp);
-	if (EFI_ERROR(status))
+	srf = AllocatePool(sizeof(*srf));
+	if (srf == NULL)
+		return ENOMEM;
+
+	dp = file_dp;
+	status = OpenSimpleReadFile(FALSE, NULL, 0, &dp, &device, srf);
+	FreePool(file_dp);
+	if (EFI_ERROR(status)) {
+		FreePool(srf);
 		return status == EFI_NOT_FOUND ? ENOENT : EIO;
+	}
 
 	for (n = 0; n < ndevs; n++)
 		if (strcmp(DEV_NAME(&devsw[n]), "efifile") == 0) {
 			f->f_dev = &devsw[n];
 			break;
 		}
-	if (n == ndevs)
+	if (n == ndevs) {
+		FreePool(srf);
 		return ENXIO;
+	}
 	f->f_devdata = f;
 	f->f_fsdata = srf;
 	f->f_flags = F_NODEV | F_READ;
@@ -120,9 +127,10 @@ efi_file_open(struct open_file *f, ...)
 int
 efi_file_close(struct open_file *f)
 {
-	SIMPLE_READ_FILE srf = f->f_fsdata;
+	SIMPLE_READ_FILE *srf = f->f_fsdata;
 
-	CloseSimpleReadFile(srf);
+	CloseSimpleReadFile(*srf);
+	FreePool(srf);
 
 	return 0;
 }
@@ -131,7 +139,7 @@ int
 efi_file_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
 {
 	struct open_file *f = devdata;
-	SIMPLE_READ_FILE srf = f->f_fsdata;
+	SIMPLE_READ_FILE *srf = f->f_fsdata;
 	EFI_STATUS status;
 	UINTN len;
 
@@ -139,7 +147,7 @@ efi_file_strategy(void *devdata, int rw,
 		return EROFS;
 
 	len = size;
-	status = ReadSimpleReadFile(srf, f->f_offset, &len, buf);
+	status = ReadSimpleReadFile(*srf, f->f_offset, &len, buf);
 	if (EFI_ERROR(status))
 		return EIO;
 	*rsize = len;
@@ -153,7 +161,9 @@ efi_file_path(EFI_DEVICE_PATH *dp, const
 	UINTN vol;
 	int depth;
 
-	depth = efi_device_path_depth(dp, END_DEVICE_PATH_TYPE);
+	depth = efi_device_path_count(dp);
+	if (depth == 0)
+		return ENODEV;
 
 	for (vol = 0; vol < efi_nvol; vol++) {
 		if (efi_device_path_ncmp(dp, DevicePathFromHandle(efi_vol[vol]), depth) == 0)

Reply via email to