* [PATCH] efi_loader: fix a problem in loading an image from a short-path
@ 2022-04-28 4:50 AKASHI Takahiro
2022-04-29 10:57 ` Heinrich Schuchardt
0 siblings, 1 reply; 3+ messages in thread
From: AKASHI Takahiro @ 2022-04-28 4:50 UTC (permalink / raw)
To: xypron.glpk; +Cc: mark.kettenis, u-boot, AKASHI Takahiro
Booting from a short-form device path which starts with the first element
being a File Path Media Device Path failed because it doesn't contain
any valid device with simple file system protocol and efi_dp_find_obj()
in efi_load_image_from_path() will return NULL.
For instance,
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/\helloworld.efi
-> shortened version: /\helloworld.efi
With this patch applied, all the media devices with simple file system
protocol are enumerated and the boot manager attempts to boot temporarily
generated device paths one-by-one.
This new implementation is still a bit incompatible with the UEFI
specification in terms of:
* not creating real boot options
* not distinguishing removable media and fix media
(See section 3.1.3 "Boot Options".)
But it still gives us a closer and better solution than the current.
Fixes: commit 9cdf470274ff ("efi_loader: support booting via short-form device-path")
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
include/efi_loader.h | 3 ++
lib/efi_loader/efi_boottime.c | 87 +++++++++++++++++++++++++++++++----
lib/efi_loader/efi_file.c | 35 ++++++++++----
3 files changed, 107 insertions(+), 18 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h
index ba79a9afb404..9730c1375a55 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -661,6 +661,9 @@ void efi_signal_event(struct efi_event *event);
struct efi_simple_file_system_protocol *efi_simple_file_system(
struct blk_desc *desc, int part, struct efi_device_path *dp);
+/* open file from simple file system */
+struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v,
+ struct efi_device_path *fp);
/* open file from device-path: */
struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5bcb8253edba..39b0e8f7ade0 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1868,19 +1868,21 @@ out:
}
/**
- * efi_load_image_from_file() - load an image from file system
+ * __efi_load_image_from_file() - load an image from file system
*
* Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
* callers obligation to update the memory type as needed.
*
+ * @v: simple file system
* @file_path: the path of the image to load
* @buffer: buffer containing the loaded image
* @size: size of the loaded image
* Return: status code
*/
static
-efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
- void **buffer, efi_uintn_t *size)
+efi_status_t __efi_load_image_from_file(struct efi_simple_file_system_protocol *v,
+ struct efi_device_path *file_path,
+ void **buffer, efi_uintn_t *size)
{
struct efi_file_handle *f;
efi_status_t ret;
@@ -1888,7 +1890,11 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
efi_uintn_t bs;
/* Open file */
- f = efi_file_from_path(file_path);
+ if (v)
+ f = efi_file_from_fs(v, file_path);
+ else
+ /* file_path should have a device path */
+ f = efi_file_from_path(file_path);
if (!f)
return EFI_NOT_FOUND;
@@ -1921,6 +1927,64 @@ error:
return ret;
}
+/**
+ * efi_load_image_from_file() - load an image from file system
+ *
+ * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
+ * callers obligation to update the memory type as needed.
+ *
+ * @file_path: the path of the image to load
+ * @buffer: buffer containing the loaded image
+ * @size: size of the loaded image
+ * Return: status code
+ */
+static
+efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
+ void **buffer, efi_uintn_t *size)
+{
+ efi_uintn_t no_handles;
+ efi_handle_t *handles;
+ struct efi_handler *handler;
+ struct efi_simple_file_system_protocol *fs;
+ int i;
+ efi_status_t ret;
+
+ /* if a file_path contains a device path */
+ if (!EFI_DP_TYPE(file_path, MEDIA_DEVICE, FILE_PATH))
+ return __efi_load_image_from_file(NULL, file_path, buffer, size);
+
+ /* no explicit device specified */
+ ret = EFI_CALL(efi_locate_handle_buffer(
+ BY_PROTOCOL,
+ &efi_simple_file_system_protocol_guid,
+ NULL,
+ &no_handles,
+ &handles));
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (!no_handles)
+ return EFI_NOT_FOUND;
+
+ for (i = 0; i < no_handles; i++) {
+ ret = efi_search_protocol(handles[i],
+ &efi_simple_file_system_protocol_guid,
+ &handler);
+ if (ret != EFI_SUCCESS)
+ /* unlikely */
+ continue;
+
+ fs = handler->protocol_interface;
+ if (!fs)
+ continue;
+
+ ret = __efi_load_image_from_file(fs, file_path, buffer, size);
+ if (ret == EFI_SUCCESS)
+ return ret;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
/**
* efi_load_image_from_path() - load an image using a file path
*
@@ -1940,7 +2004,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
{
efi_handle_t device;
efi_status_t ret;
- struct efi_device_path *dp, *rem;
+ struct efi_device_path *rem;
struct efi_load_file_protocol *load_file_protocol = NULL;
efi_uintn_t buffer_size;
uint64_t addr, pages;
@@ -1950,12 +2014,15 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
*buffer = NULL;
*size = 0;
- dp = file_path;
- device = efi_dp_find_obj(dp, NULL, &rem);
- ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid,
- NULL);
+ /* try first for simple file system protocols */
+ ret = efi_load_image_from_file(file_path, buffer, size);
if (ret == EFI_SUCCESS)
- return efi_load_image_from_file(file_path, buffer, size);
+ return ret;
+
+ /* TODO: does this really make sense? */
+ device = efi_dp_find_obj(file_path, NULL, &rem);
+ if (!device)
+ return EFI_NOT_FOUND;
ret = efi_search_protocol(device, &efi_guid_load_file_protocol, NULL);
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 7a7077e6d032..2d6a432b168b 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -1083,16 +1083,16 @@ static const struct efi_file_handle efi_file_handle_protocol = {
/**
* efi_file_from_path() - open file via device path
*
- * @fp: device path
+ * @v: simple file system
+ * @fp: file path
* Return: EFI_FILE_PROTOCOL for the file or NULL
*/
-struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
+struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v,
+ struct efi_device_path *fp)
{
- struct efi_simple_file_system_protocol *v;
struct efi_file_handle *f;
efi_status_t ret;
- v = efi_fs_from_path(fp);
if (!v)
return NULL;
@@ -1100,10 +1100,6 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
if (ret != EFI_SUCCESS)
return NULL;
- /* Skip over device-path nodes before the file path. */
- while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
- fp = efi_dp_next(fp);
-
/*
* Step through the nodes of the directory path until the actual file
* node is reached which is the final node in the device path.
@@ -1138,6 +1134,29 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
return f;
}
+/**
+ * efi_file_from_path() - open file via device path
+ *
+ * @fp: device path
+ * Return: EFI_FILE_PROTOCOL for the file or NULL
+ */
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
+{
+ struct efi_simple_file_system_protocol *v;
+
+ v = efi_fs_from_path(fp);
+ if (!v)
+ return NULL;
+
+ /* Skip over device-path nodes before the file path. */
+ while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
+ fp = efi_dp_next(fp);
+ if (!fp)
+ return NULL;
+
+ return efi_file_from_fs(v, fp);
+}
+
static efi_status_t EFIAPI
efi_open_volume(struct efi_simple_file_system_protocol *this,
struct efi_file_handle **root)
--
2.33.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] efi_loader: fix a problem in loading an image from a short-path 2022-04-28 4:50 [PATCH] efi_loader: fix a problem in loading an image from a short-path AKASHI Takahiro @ 2022-04-29 10:57 ` Heinrich Schuchardt 2022-05-10 9:38 ` AKASHI Takahiro 0 siblings, 1 reply; 3+ messages in thread From: Heinrich Schuchardt @ 2022-04-29 10:57 UTC (permalink / raw) To: AKASHI Takahiro; +Cc: mark.kettenis, u-boot On 4/28/22 06:50, AKASHI Takahiro wrote: > Booting from a short-form device path which starts with the first element > being a File Path Media Device Path failed because it doesn't contain > any valid device with simple file system protocol and efi_dp_find_obj() > in efi_load_image_from_path() will return NULL. > For instance, > /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/\helloworld.efi > -> shortened version: /\helloworld.efi Thanks for enabling this. Please, enhance test/py/tests/test_efi_bootmgr to test booting from a filename only device path. > > With this patch applied, all the media devices with simple file system > protocol are enumerated and the boot manager attempts to boot temporarily > generated device paths one-by-one. > > This new implementation is still a bit incompatible with the UEFI > specification in terms of: > * not creating real boot options The UEFI specification has: "These new boot options must not be saved to non volatile storage, and may not be added to BootOrder." Is there really something missing? > * not distinguishing removable media and fix media struct blk_desc has field 'removable' which is mirrored in struct efi_disk_obj. mmc_bind() always sets removable to 1 irrespective of the device being eMMC or SD-card. I guess this would need to be fixed. > (See section 3.1.3 "Boot Options".) > > But it still gives us a closer and better solution than the current. > > Fixes: commit 9cdf470274ff ("efi_loader: support booting via short-form device-path") > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> > --- > include/efi_loader.h | 3 ++ > lib/efi_loader/efi_boottime.c | 87 +++++++++++++++++++++++++++++++---- > lib/efi_loader/efi_file.c | 35 ++++++++++---- > 3 files changed, 107 insertions(+), 18 deletions(-) > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index ba79a9afb404..9730c1375a55 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -661,6 +661,9 @@ void efi_signal_event(struct efi_event *event); > struct efi_simple_file_system_protocol *efi_simple_file_system( > struct blk_desc *desc, int part, struct efi_device_path *dp); > > +/* open file from simple file system */ > +struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v, > + struct efi_device_path *fp); > /* open file from device-path: */ > struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > index 5bcb8253edba..39b0e8f7ade0 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -1868,19 +1868,21 @@ out: > } > > /** > - * efi_load_image_from_file() - load an image from file system > + * __efi_load_image_from_file() - load an image from file system > * > * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the > * callers obligation to update the memory type as needed. > * > + * @v: simple file system Please, use a meaningful variable name. > * @file_path: the path of the image to load > * @buffer: buffer containing the loaded image > * @size: size of the loaded image > * Return: status code > */ > static > -efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > - void **buffer, efi_uintn_t *size) > +efi_status_t __efi_load_image_from_file(struct efi_simple_file_system_protocol *v, > + struct efi_device_path *file_path, > + void **buffer, efi_uintn_t *size) > { > struct efi_file_handle *f; > efi_status_t ret; > @@ -1888,7 +1890,11 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > efi_uintn_t bs; > > /* Open file */ > - f = efi_file_from_path(file_path); > + if (v) > + f = efi_file_from_fs(v, file_path); > + else > + /* file_path should have a device path */ > + f = efi_file_from_path(file_path); > if (!f) > return EFI_NOT_FOUND; > > @@ -1921,6 +1927,64 @@ error: > return ret; > } > > +/** > + * efi_load_image_from_file() - load an image from file system > + * > + * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the > + * callers obligation to update the memory type as needed. > + * > + * @file_path: the path of the image to load > + * @buffer: buffer containing the loaded image > + * @size: size of the loaded image > + * Return: status code > + */ > +static > +efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > + void **buffer, efi_uintn_t *size) > +{ > + efi_uintn_t no_handles; > + efi_handle_t *handles; > + struct efi_handler *handler; > + struct efi_simple_file_system_protocol *fs; > + int i; > + efi_status_t ret; > + > + /* if a file_path contains a device path */ > + if (!EFI_DP_TYPE(file_path, MEDIA_DEVICE, FILE_PATH)) > + return __efi_load_image_from_file(NULL, file_path, buffer, size); > + > + /* no explicit device specified */ > + ret = EFI_CALL(efi_locate_handle_buffer( > + BY_PROTOCOL, > + &efi_simple_file_system_protocol_guid, > + NULL, > + &no_handles, > + &handles)); > + if (ret != EFI_SUCCESS) > + return ret; > + if (!no_handles) > + return EFI_NOT_FOUND; > + > + for (i = 0; i < no_handles; i++) { > + ret = efi_search_protocol(handles[i], > + &efi_simple_file_system_protocol_guid, > + &handler); > + if (ret != EFI_SUCCESS) > + /* unlikely */ > + continue; > + > + fs = handler->protocol_interface; > + if (!fs) > + continue; > + > + ret = __efi_load_image_from_file(fs, file_path, buffer, size); > + if (ret == EFI_SUCCESS) > + return ret; > + } > + > + return EFI_NOT_FOUND; > +} > + > /** > * efi_load_image_from_path() - load an image using a file path > * > @@ -1940,7 +2004,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy, > { > efi_handle_t device; > efi_status_t ret; > - struct efi_device_path *dp, *rem; > + struct efi_device_path *rem; > struct efi_load_file_protocol *load_file_protocol = NULL; > efi_uintn_t buffer_size; > uint64_t addr, pages; > @@ -1950,12 +2014,15 @@ efi_status_t efi_load_image_from_path(bool boot_policy, > *buffer = NULL; > *size = 0; > > - dp = file_path; > - device = efi_dp_find_obj(dp, NULL, &rem); > - ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, > - NULL); > + /* try first for simple file system protocols */ > + ret = efi_load_image_from_file(file_path, buffer, size); > if (ret == EFI_SUCCESS) > - return efi_load_image_from_file(file_path, buffer, size); > + return ret; > + > + /* TODO: does this really make sense? */ > + device = efi_dp_find_obj(file_path, NULL, &rem); > + if (!device) > + return EFI_NOT_FOUND; > > ret = efi_search_protocol(device, &efi_guid_load_file_protocol, NULL); > if (ret == EFI_SUCCESS) { > diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c > index 7a7077e6d032..2d6a432b168b 100644 > --- a/lib/efi_loader/efi_file.c > +++ b/lib/efi_loader/efi_file.c > @@ -1083,16 +1083,16 @@ static const struct efi_file_handle efi_file_handle_protocol = { > /** > * efi_file_from_path() - open file via device path > * > - * @fp: device path > + * @v: simple file system > + * @fp: file path > * Return: EFI_FILE_PROTOCOL for the file or NULL > */ > -struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > +struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v, > + struct efi_device_path *fp) > { > - struct efi_simple_file_system_protocol *v; > struct efi_file_handle *f; > efi_status_t ret; > > - v = efi_fs_from_path(fp); > if (!v) > return NULL; > > @@ -1100,10 +1100,6 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > if (ret != EFI_SUCCESS) > return NULL; > > - /* Skip over device-path nodes before the file path. */ > - while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) > - fp = efi_dp_next(fp); > - > /* > * Step through the nodes of the directory path until the actual file > * node is reached which is the final node in the device path. > @@ -1138,6 +1134,29 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > return f; > } > > +/** > + * efi_file_from_path() - open file via device path > + * > + * @fp: device path 'fp' does not resonate 'device path'. How about using dp? > + * Return: EFI_FILE_PROTOCOL for the file or NULL > + */ > +struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > +{ > + struct efi_simple_file_system_protocol *v; Please, provide a meaningful variable name. Best regards Heinrich > + > + v = efi_fs_from_path(fp); > + if (!v) > + return NULL; > + > + /* Skip over device-path nodes before the file path. */ > + while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) > + fp = efi_dp_next(fp); > + if (!fp) > + return NULL; > + > + return efi_file_from_fs(v, fp); > +} > + > static efi_status_t EFIAPI > efi_open_volume(struct efi_simple_file_system_protocol *this, > struct efi_file_handle **root) ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] efi_loader: fix a problem in loading an image from a short-path 2022-04-29 10:57 ` Heinrich Schuchardt @ 2022-05-10 9:38 ` AKASHI Takahiro 0 siblings, 0 replies; 3+ messages in thread From: AKASHI Takahiro @ 2022-05-10 9:38 UTC (permalink / raw) To: Heinrich Schuchardt; +Cc: mark.kettenis, u-boot On Fri, Apr 29, 2022 at 12:57:15PM +0200, Heinrich Schuchardt wrote: > On 4/28/22 06:50, AKASHI Takahiro wrote: > > Booting from a short-form device path which starts with the first element > > being a File Path Media Device Path failed because it doesn't contain > > any valid device with simple file system protocol and efi_dp_find_obj() > > in efi_load_image_from_path() will return NULL. > > For instance, > > /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/\helloworld.efi > > -> shortened version: /\helloworld.efi > > Thanks for enabling this. > > Please, enhance test/py/tests/test_efi_bootmgr to test booting from a > filename only device path. Okay, but you should have added tests in your patch. > > > > With this patch applied, all the media devices with simple file system > > protocol are enumerated and the boot manager attempts to boot temporarily > > generated device paths one-by-one. > > > > This new implementation is still a bit incompatible with the UEFI > > specification in terms of: > > * not creating real boot options > > The UEFI specification has: > > "These new boot options must not be saved to non volatile storage, > and may not be added to BootOrder." > > Is there really something missing? When the boot manager attempts to boot a short-form File Path Media Device Path, it will enumerate all removable media devices, followed by all fixed media devices, creating boot options for each device. ^^^^^^^^^^^^^^^^^^^^^ > > * not distinguishing removable media and fix media > > struct blk_desc has field 'removable' which is mirrored in struct > efi_disk_obj. Instead of relying on such an internal structure, we can and should use a public interface, efi_block_io(->media.removable_media). > mmc_bind() always sets removable to 1 irrespective of the device being > eMMC or SD-card. I guess this would need to be fixed. > > > (See section 3.1.3 "Boot Options".) > > > > But it still gives us a closer and better solution than the current. > > > > Fixes: commit 9cdf470274ff ("efi_loader: support booting via short-form device-path") > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> > > --- > > include/efi_loader.h | 3 ++ > > lib/efi_loader/efi_boottime.c | 87 +++++++++++++++++++++++++++++++---- > > lib/efi_loader/efi_file.c | 35 ++++++++++---- > > 3 files changed, 107 insertions(+), 18 deletions(-) > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h > > index ba79a9afb404..9730c1375a55 100644 > > --- a/include/efi_loader.h > > +++ b/include/efi_loader.h > > @@ -661,6 +661,9 @@ void efi_signal_event(struct efi_event *event); > > struct efi_simple_file_system_protocol *efi_simple_file_system( > > struct blk_desc *desc, int part, struct efi_device_path *dp); > > > > +/* open file from simple file system */ > > +struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v, > > + struct efi_device_path *fp); > > /* open file from device-path: */ > > struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); > > > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > index 5bcb8253edba..39b0e8f7ade0 100644 > > --- a/lib/efi_loader/efi_boottime.c > > +++ b/lib/efi_loader/efi_boottime.c > > @@ -1868,19 +1868,21 @@ out: > > } > > > > /** > > - * efi_load_image_from_file() - load an image from file system > > + * __efi_load_image_from_file() - load an image from file system > > * > > * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the > > * callers obligation to update the memory type as needed. > > * > > + * @v: simple file system > > Please, use a meaningful variable name. I will fully re-write this patch. While efi boot manager should be responsible for handling a short-form device path starting with a file path, my current implementation is made in efi_load_image_from_path() hence LoadImage API. Instead, the logic of enumerating file_system_protocol devices will be added to try_load_entry()/efi_bootmgr_load(). -Takahiro Akashi > > * @file_path: the path of the image to load > > * @buffer: buffer containing the loaded image > > * @size: size of the loaded image > > * Return: status code > > */ > > static > > -efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > > - void **buffer, efi_uintn_t *size) > > +efi_status_t __efi_load_image_from_file(struct efi_simple_file_system_protocol *v, > > + struct efi_device_path *file_path, > > + void **buffer, efi_uintn_t *size) > > { > > struct efi_file_handle *f; > > efi_status_t ret; > > @@ -1888,7 +1890,11 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > > efi_uintn_t bs; > > > > /* Open file */ > > - f = efi_file_from_path(file_path); > > + if (v) > > + f = efi_file_from_fs(v, file_path); > > + else > > + /* file_path should have a device path */ > > + f = efi_file_from_path(file_path); > > if (!f) > > return EFI_NOT_FOUND; > > > > @@ -1921,6 +1927,64 @@ error: > > return ret; > > } > > > > +/** > > + * efi_load_image_from_file() - load an image from file system > > + * > > + * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the > > + * callers obligation to update the memory type as needed. > > + * > > + * @file_path: the path of the image to load > > + * @buffer: buffer containing the loaded image > > + * @size: size of the loaded image > > + * Return: status code > > + */ > > +static > > +efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, > > + void **buffer, efi_uintn_t *size) > > +{ > > + efi_uintn_t no_handles; > > + efi_handle_t *handles; > > + struct efi_handler *handler; > > + struct efi_simple_file_system_protocol *fs; > > + int i; > > + efi_status_t ret; > > + > > + /* if a file_path contains a device path */ > > + if (!EFI_DP_TYPE(file_path, MEDIA_DEVICE, FILE_PATH)) > > + return __efi_load_image_from_file(NULL, file_path, buffer, size); > > + > > + /* no explicit device specified */ > > + ret = EFI_CALL(efi_locate_handle_buffer( > > + BY_PROTOCOL, > > + &efi_simple_file_system_protocol_guid, > > + NULL, > > + &no_handles, > > + &handles)); > > + if (ret != EFI_SUCCESS) > > + return ret; > > + if (!no_handles) > > + return EFI_NOT_FOUND; > > + > > + for (i = 0; i < no_handles; i++) { > > + ret = efi_search_protocol(handles[i], > > + &efi_simple_file_system_protocol_guid, > > + &handler); > > + if (ret != EFI_SUCCESS) > > + /* unlikely */ > > + continue; > > + > > + fs = handler->protocol_interface; > > + if (!fs) > > + continue; > > + > > + ret = __efi_load_image_from_file(fs, file_path, buffer, size); > > + if (ret == EFI_SUCCESS) > > + return ret; > > + } > > + > > + return EFI_NOT_FOUND; > > +} > > + > > /** > > * efi_load_image_from_path() - load an image using a file path > > * > > @@ -1940,7 +2004,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy, > > { > > efi_handle_t device; > > efi_status_t ret; > > - struct efi_device_path *dp, *rem; > > + struct efi_device_path *rem; > > struct efi_load_file_protocol *load_file_protocol = NULL; > > efi_uintn_t buffer_size; > > uint64_t addr, pages; > > @@ -1950,12 +2014,15 @@ efi_status_t efi_load_image_from_path(bool boot_policy, > > *buffer = NULL; > > *size = 0; > > > > - dp = file_path; > > - device = efi_dp_find_obj(dp, NULL, &rem); > > - ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, > > - NULL); > > + /* try first for simple file system protocols */ > > + ret = efi_load_image_from_file(file_path, buffer, size); > > if (ret == EFI_SUCCESS) > > - return efi_load_image_from_file(file_path, buffer, size); > > + return ret; > > + > > + /* TODO: does this really make sense? */ > > + device = efi_dp_find_obj(file_path, NULL, &rem); > > + if (!device) > > + return EFI_NOT_FOUND; > > > > ret = efi_search_protocol(device, &efi_guid_load_file_protocol, NULL); > > if (ret == EFI_SUCCESS) { > > diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c > > index 7a7077e6d032..2d6a432b168b 100644 > > --- a/lib/efi_loader/efi_file.c > > +++ b/lib/efi_loader/efi_file.c > > @@ -1083,16 +1083,16 @@ static const struct efi_file_handle efi_file_handle_protocol = { > > /** > > * efi_file_from_path() - open file via device path > > * > > - * @fp: device path > > + * @v: simple file system > > + * @fp: file path > > * Return: EFI_FILE_PROTOCOL for the file or NULL > > */ > > -struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > > +struct efi_file_handle *efi_file_from_fs(struct efi_simple_file_system_protocol *v, > > + struct efi_device_path *fp) > > { > > - struct efi_simple_file_system_protocol *v; > > struct efi_file_handle *f; > > efi_status_t ret; > > > > - v = efi_fs_from_path(fp); > > if (!v) > > return NULL; > > > > @@ -1100,10 +1100,6 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > > if (ret != EFI_SUCCESS) > > return NULL; > > > > - /* Skip over device-path nodes before the file path. */ > > - while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) > > - fp = efi_dp_next(fp); > > - > > /* > > * Step through the nodes of the directory path until the actual file > > * node is reached which is the final node in the device path. > > @@ -1138,6 +1134,29 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > > return f; > > } > > > > +/** > > + * efi_file_from_path() - open file via device path > > + * > > + * @fp: device path > > 'fp' does not resonate 'device path'. How about using dp? > > > + * Return: EFI_FILE_PROTOCOL for the file or NULL > > + */ > > +struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) > > +{ > > + struct efi_simple_file_system_protocol *v; > > Please, provide a meaningful variable name. > > Best regards > > Heinrich > > > + > > + v = efi_fs_from_path(fp); > > + if (!v) > > + return NULL; > > + > > + /* Skip over device-path nodes before the file path. */ > > + while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) > > + fp = efi_dp_next(fp); > > + if (!fp) > > + return NULL; > > + > > + return efi_file_from_fs(v, fp); > > +} > > + > > static efi_status_t EFIAPI > > efi_open_volume(struct efi_simple_file_system_protocol *this, > > struct efi_file_handle **root) > ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-05-10 9:38 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-04-28 4:50 [PATCH] efi_loader: fix a problem in loading an image from a short-path AKASHI Takahiro 2022-04-29 10:57 ` Heinrich Schuchardt 2022-05-10 9:38 ` AKASHI Takahiro
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox