aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-02-01 23:54:19 +0000
committerMichael Brown <mcb30@ipxe.org>2023-02-01 23:54:19 +0000
commit6f250be279311d461f78bb17eb8b5b70ad90dd0a (patch)
tree07c07d85835367e6844965aba420ccc6811a5ac3 /src
parentb6304f298499001a55045618e9fbf763b59b7321 (diff)
downloadipxe-6f250be279311d461f78bb17eb8b5b70ad90dd0a.zip
ipxe-6f250be279311d461f78bb17eb8b5b70ad90dd0a.tar.gz
ipxe-6f250be279311d461f78bb17eb8b5b70ad90dd0a.tar.bz2
[efi] Allow autoexec script to be located alongside iPXE binaryautoexecpath
Try loading the autoexec.ipxe script first from the directory containing the iPXE binary (based on the relative file path provided to us via EFI_LOADED_IMAGE_PROTOCOL), then fall back to trying the root directory. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src')
-rw-r--r--src/include/ipxe/efi/efi_autoexec.h3
-rw-r--r--src/interface/efi/efi_autoexec.c85
-rw-r--r--src/interface/efi/efiprefix.c9
3 files changed, 75 insertions, 22 deletions
diff --git a/src/include/ipxe/efi/efi_autoexec.h b/src/include/ipxe/efi/efi_autoexec.h
index 1f93b41..08ddf58 100644
--- a/src/include/ipxe/efi/efi_autoexec.h
+++ b/src/include/ipxe/efi/efi_autoexec.h
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
-extern int efi_autoexec_load ( EFI_HANDLE device );
+extern int efi_autoexec_load ( EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *path );
#endif /* _IPXE_EFI_AUTOEXEC_H */
diff --git a/src/interface/efi/efi_autoexec.c b/src/interface/efi/efi_autoexec.c
index 79d4a4c..fb12cef 100644
--- a/src/interface/efi/efi_autoexec.c
+++ b/src/interface/efi/efi_autoexec.c
@@ -54,12 +54,14 @@ static void *efi_autoexec;
static size_t efi_autoexec_len;
/**
- * Load autoexec script from filesystem
+ * Load autoexec script from path within filesystem
*
* @v device Device handle
+ * @v path Relative path to image, or NULL to load from root
* @ret rc Return status code
*/
-static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
+static int efi_autoexec_filesystem ( EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *path ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
void *interface;
@@ -70,13 +72,58 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
CHAR16 name[ sizeof ( efi_autoexec_wname ) /
sizeof ( efi_autoexec_wname[0] ) ];
} info;
+ FILEPATH_DEVICE_PATH *filepath;
EFI_FILE_PROTOCOL *root;
EFI_FILE_PROTOCOL *file;
UINTN size;
VOID *data;
+ unsigned int dirlen;
+ size_t len;
+ CHAR16 *wname;
EFI_STATUS efirc;
int rc;
+ /* Identify directory */
+ if ( path ) {
+
+ /* Check relative device path is a file path */
+ if ( ! ( ( path->Type == MEDIA_DEVICE_PATH ) &&
+ ( path->SubType == MEDIA_FILEPATH_DP ) ) ) {
+ DBGC ( device, "EFI %s image path ",
+ efi_handle_name ( device ) );
+ DBGC ( device, " \"%s\" is not a file path\n",
+ efi_devpath_text ( path ) );
+ rc = -ENOTTY;
+ goto err_not_filepath;
+ }
+ filepath = container_of ( path, FILEPATH_DEVICE_PATH, Header );
+
+ /* Find length of containing directory */
+ dirlen = ( ( ( ( path->Length[1] << 8 ) | path->Length[0] )
+ - offsetof ( typeof ( *filepath ), PathName ) )
+ / sizeof ( filepath->PathName[0] ) );
+ for ( ; dirlen ; dirlen-- ) {
+ if ( filepath->PathName[ dirlen - 1 ] == L'\\' )
+ break;
+ }
+
+ } else {
+
+ /* Use root directory */
+ filepath = NULL;
+ dirlen = 0;
+ }
+
+ /* Allocate filename */
+ len = ( ( dirlen * sizeof ( wname[0] ) ) + sizeof ( efi_autoexec_wname ) );
+ wname = malloc ( len );
+ if ( ! wname ) {
+ rc = -ENOMEM;
+ goto err_wname;
+ }
+ memcpy ( wname, filepath->PathName, ( dirlen * sizeof ( wname[0] ) ) );
+ memcpy ( &wname[dirlen], efi_autoexec_wname, sizeof ( efi_autoexec_wname ) );
+
/* Open simple file system protocol */
if ( ( efirc = bs->OpenProtocol ( device,
&efi_simple_file_system_protocol_guid,
@@ -98,12 +145,11 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
}
/* Open autoexec script */
- if ( ( efirc = root->Open ( root, &file, efi_autoexec_wname,
+ if ( ( efirc = root->Open ( root, &file, wname,
EFI_FILE_MODE_READ, 0 ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( device, "EFI %s has no %ls: %s\n",
- efi_handle_name ( device ), efi_autoexec_wname,
- strerror ( rc ) );
+ efi_handle_name ( device ), wname, strerror ( rc ) );
goto err_open;
}
@@ -113,8 +159,7 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
&info ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not get %ls info: %s\n",
- efi_handle_name ( device ), efi_autoexec_wname,
- strerror ( rc ) );
+ efi_handle_name ( device ), wname, strerror ( rc ) );
goto err_getinfo;
}
size = info.info.FileSize;
@@ -123,7 +168,7 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
if ( ! size ) {
rc = -EINVAL;
DBGC ( device, "EFI %s has zero-length %ls\n",
- efi_handle_name ( device ), efi_autoexec_wname );
+ efi_handle_name ( device ), wname );
goto err_empty;
}
@@ -132,8 +177,7 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
&data ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not allocate %ls: %s\n",
- efi_handle_name ( device ), efi_autoexec_wname,
- strerror ( rc ) );
+ efi_handle_name ( device ), wname, strerror ( rc ) );
goto err_alloc;
}
@@ -141,8 +185,7 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not read %ls: %s\n",
- efi_handle_name ( device ), efi_autoexec_wname,
- strerror ( rc ) );
+ efi_handle_name ( device ), wname, strerror ( rc ) );
goto err_read;
}
@@ -150,8 +193,7 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
efi_autoexec = data;
efi_autoexec_len = size;
data = NULL;
- DBGC ( device, "EFI %s found %ls\n",
- efi_handle_name ( device ), efi_autoexec_wname );
+ DBGC ( device, "EFI %s found %ls\n", efi_handle_name ( device ), wname );
/* Success */
rc = 0;
@@ -169,6 +211,9 @@ static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
bs->CloseProtocol ( device, &efi_simple_file_system_protocol_guid,
efi_image_handle, device );
err_filesystem:
+ free ( wname );
+ err_wname:
+ err_not_filepath:
return rc;
}
@@ -345,17 +390,23 @@ static int efi_autoexec_tftp ( EFI_HANDLE device ) {
* Load autoexec script
*
* @v device Device handle
+ * @v path Image path within device handle
* @ret rc Return status code
*/
-int efi_autoexec_load ( EFI_HANDLE device ) {
+int efi_autoexec_load ( EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *path ) {
int rc;
/* Sanity check */
assert ( efi_autoexec == NULL );
assert ( efi_autoexec_len == 0 );
- /* Try loading from file system, if supported */
- if ( ( rc = efi_autoexec_filesystem ( device ) ) == 0 )
+ /* Try loading from file system loaded image directory, if supported */
+ if ( ( rc = efi_autoexec_filesystem ( device, path ) ) == 0 )
+ return 0;
+
+ /* Try loading from file system root directory, if supported */
+ if ( ( rc = efi_autoexec_filesystem ( device, NULL ) ) == 0 )
return 0;
/* Try loading via TFTP, if supported */
diff --git a/src/interface/efi/efiprefix.c b/src/interface/efi/efiprefix.c
index bdc36d9..2611606 100644
--- a/src/interface/efi/efiprefix.c
+++ b/src/interface/efi/efiprefix.c
@@ -78,16 +78,17 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
*/
static void efi_init_application ( void ) {
EFI_HANDLE device = efi_loaded_image->DeviceHandle;
- EFI_DEVICE_PATH_PROTOCOL *path = efi_loaded_image_path;
+ EFI_DEVICE_PATH_PROTOCOL *devpath = efi_loaded_image_path;
+ EFI_DEVICE_PATH_PROTOCOL *filepath = efi_loaded_image->FilePath;
/* Identify autoboot device, if any */
- efi_set_autoboot_ll_addr ( device, path );
+ efi_set_autoboot_ll_addr ( device, devpath );
/* Store cached DHCP packet, if any */
- efi_cachedhcp_record ( device, path );
+ efi_cachedhcp_record ( device, devpath );
/* Load autoexec script, if any */
- efi_autoexec_load ( device );
+ efi_autoexec_load ( device, filepath );
}
/** EFI application initialisation function */