[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>
pull/844/head
Michael Brown 2022-12-22 13:33:38 +00:00
parent 0f3ace92c6
commit 099e4d39b3
3 changed files with 41 additions and 15 deletions

View File

@ -21,6 +21,8 @@ struct fcp_description;
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 );

View File

@ -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;

View File

@ -40,6 +40,31 @@
*
*/
/**
* 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
*
@ -47,12 +72,11 @@
* @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;