summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2022-12-22 14:33:38 +0100
committerMichael Brown2022-12-22 14:34:28 +0100
commit099e4d39b355a10b0bc7d23bb0e96615bf06470b (patch)
tree0d92cb14109fe07f6055d5c67b256646629bfcc0
parent[efi] Allow passing a NULL device path to path utility functions (diff)
downloadipxe-099e4d39b355a10b0bc7d23bb0e96615bf06470b.tar.gz
ipxe-099e4d39b355a10b0bc7d23bb0e96615bf06470b.tar.xz
ipxe-099e4d39b355a10b0bc7d23bb0e96615bf06470b.zip
[efi] Expose efi_path_next() utility function
Provide a single central implementation of the logic for stepping through elements of an EFI device path. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/efi/efi_path.h2
-rw-r--r--src/interface/efi/efi_local.c20
-rw-r--r--src/interface/efi/efi_path.c34
3 files changed, 41 insertions, 15 deletions
diff --git a/src/include/ipxe/efi/efi_path.h b/src/include/ipxe/efi/efi_path.h
index 76ded728..18810a75 100644
--- a/src/include/ipxe/efi/efi_path.h
+++ b/src/include/ipxe/efi/efi_path.h
@@ -22,6 +22,8 @@ struct ib_srp_device;
struct usb_function;
extern EFI_DEVICE_PATH_PROTOCOL *
+efi_path_next ( EFI_DEVICE_PATH_PROTOCOL *path );
+extern EFI_DEVICE_PATH_PROTOCOL *
efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path );
extern size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path );
extern EFI_DEVICE_PATH_PROTOCOL * efi_paths ( EFI_DEVICE_PATH_PROTOCOL *first,
diff --git a/src/interface/efi/efi_local.c b/src/interface/efi/efi_local.c
index d8edb626..f54f5dae 100644
--- a/src/interface/efi/efi_local.c
+++ b/src/interface/efi/efi_local.c
@@ -419,14 +419,15 @@ static int efi_local_open_resolved ( struct efi_local *local,
* Open specified path
*
* @v local Local file
- * @v path Path to file
+ * @v filename Path to file relative to our own image
* @ret rc Return status code
*/
-static int efi_local_open_path ( struct efi_local *local, const char *path ) {
- FILEPATH_DEVICE_PATH *fp = container_of ( efi_loaded_image->FilePath,
- FILEPATH_DEVICE_PATH, Header);
- size_t fp_len = efi_path_len ( &fp->Header );
- char base[ fp_len / 2 /* Cannot exceed this length */ ];
+static int efi_local_open_path ( struct efi_local *local,
+ const char *filename ) {
+ EFI_DEVICE_PATH_PROTOCOL *path = efi_loaded_image->FilePath;
+ EFI_DEVICE_PATH_PROTOCOL *next;
+ FILEPATH_DEVICE_PATH *fp;
+ char base[ efi_path_len ( path ) / 2 /* Cannot exceed this length */ ];
size_t remaining = sizeof ( base );
size_t len;
char *resolved;
@@ -436,13 +437,12 @@ static int efi_local_open_path ( struct efi_local *local, const char *path ) {
/* Construct base path to our own image, if possible */
memset ( base, 0, sizeof ( base ) );
tmp = base;
- while ( fp && ( fp->Header.Type != END_DEVICE_PATH_TYPE ) ) {
+ for ( ; ( next = efi_path_next ( path ) ) ; path = next ) {
+ fp = container_of ( path, FILEPATH_DEVICE_PATH, Header );
len = snprintf ( tmp, remaining, "%ls", fp->PathName );
assert ( len < remaining );
tmp += len;
remaining -= len;
- fp = ( ( ( void * ) fp ) + ( ( fp->Header.Length[1] << 8 ) |
- fp->Header.Length[0] ) );
}
DBGC2 ( local, "LOCAL %p base path \"%s\"\n",
local, base );
@@ -454,7 +454,7 @@ static int efi_local_open_path ( struct efi_local *local, const char *path ) {
}
/* Resolve path */
- resolved = resolve_path ( base, path );
+ resolved = resolve_path ( base, filename );
if ( ! resolved ) {
rc = -ENOMEM;
goto err_resolve;
diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c
index 1a95a3b9..937d3c70 100644
--- a/src/interface/efi/efi_path.c
+++ b/src/interface/efi/efi_path.c
@@ -41,18 +41,42 @@
*/
/**
+ * Find next element in device path
+ *
+ * @v path Device path, or NULL
+ * @v next Next element in device path, or NULL if at end
+ */
+EFI_DEVICE_PATH_PROTOCOL * efi_path_next ( EFI_DEVICE_PATH_PROTOCOL *path ) {
+
+ /* Check for non-existent device path */
+ if ( ! path )
+ return NULL;
+
+ /* Check for end of device path */
+ if ( path->Type == END_DEVICE_PATH_TYPE )
+ return NULL;
+
+ /* Move to next component of the device path */
+ path = ( ( ( void * ) path ) +
+ /* There's this amazing new-fangled thing known as
+ * a UINT16, but who wants to use one of those? */
+ ( ( path->Length[1] << 8 ) | path->Length[0] ) );
+
+ return path;
+}
+
+/**
* Find end of device path
*
* @v path Device path, or NULL
* @ret path_end End of device path, or NULL
*/
EFI_DEVICE_PATH_PROTOCOL * efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
+ EFI_DEVICE_PATH_PROTOCOL *next;
- while ( path && ( path->Type != END_DEVICE_PATH_TYPE ) ) {
- path = ( ( ( void * ) path ) +
- /* There's this amazing new-fangled thing known as
- * a UINT16, but who wants to use one of those? */
- ( ( path->Length[1] << 8 ) | path->Length[0] ) );
+ /* Find end of device path */
+ while ( ( next = efi_path_next ( path ) ) != NULL ) {
+ path = next;
}
return path;