[efi] Allow for autoexec scripts that are not located in a filesystem

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/574/head
Michael Brown 2022-01-17 16:11:56 +00:00
parent e814d33900
commit ec746c0001
1 changed files with 41 additions and 21 deletions

View File

@ -39,10 +39,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/ */
/** Autoexec script filename */ /** Autoexec script filename */
#define AUTOEXEC_FILENAME L"autoexec.ipxe" static wchar_t efi_autoexec_wname[] = L"autoexec.ipxe";
/** Autoexec script image name */ /** Autoexec script image name */
#define AUTOEXEC_NAME "autoexec.ipxe" static char efi_autoexec_name[] = "autoexec.ipxe";
/** Autoexec script (if any) */ /** Autoexec script (if any) */
static void *efi_autoexec; static void *efi_autoexec;
@ -51,21 +51,21 @@ static void *efi_autoexec;
static size_t efi_autoexec_len; static size_t efi_autoexec_len;
/** /**
* Load autoexec script * Load autoexec script from filesystem
* *
* @v device Device handle * @v device Device handle
* @ret rc Return status code * @ret rc Return status code
*/ */
int efi_autoexec_load ( EFI_HANDLE device ) { static int efi_autoexec_filesystem ( EFI_HANDLE device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
static wchar_t name[] = AUTOEXEC_FILENAME;
union { union {
void *interface; void *interface;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
} u; } u;
struct { struct {
EFI_FILE_INFO info; EFI_FILE_INFO info;
CHAR16 name[ sizeof ( name ) / sizeof ( name[0] ) ]; CHAR16 name[ sizeof ( efi_autoexec_wname ) /
sizeof ( efi_autoexec_wname[0] ) ];
} info; } info;
EFI_FILE_PROTOCOL *root; EFI_FILE_PROTOCOL *root;
EFI_FILE_PROTOCOL *file; EFI_FILE_PROTOCOL *file;
@ -74,10 +74,6 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
EFI_STATUS efirc; EFI_STATUS efirc;
int rc; int rc;
/* Sanity check */
assert ( efi_autoexec == NULL );
assert ( efi_autoexec_len == 0 );
/* Open simple file system protocol */ /* Open simple file system protocol */
if ( ( efirc = bs->OpenProtocol ( device, if ( ( efirc = bs->OpenProtocol ( device,
&efi_simple_file_system_protocol_guid, &efi_simple_file_system_protocol_guid,
@ -99,11 +95,12 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
} }
/* Open autoexec script */ /* Open autoexec script */
if ( ( efirc = root->Open ( root, &file, name, if ( ( efirc = root->Open ( root, &file, efi_autoexec_wname,
EFI_FILE_MODE_READ, 0 ) ) != 0 ) { EFI_FILE_MODE_READ, 0 ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( device, "EFI %s has no %ls: %s\n", DBGC ( device, "EFI %s has no %ls: %s\n",
efi_handle_name ( device ), name, strerror ( rc ) ); efi_handle_name ( device ), efi_autoexec_wname,
strerror ( rc ) );
goto err_open; goto err_open;
} }
@ -113,7 +110,8 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
&info ) ) != 0 ) { &info ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not get %ls info: %s\n", DBGC ( device, "EFI %s could not get %ls info: %s\n",
efi_handle_name ( device ), name, strerror ( rc ) ); efi_handle_name ( device ), efi_autoexec_wname,
strerror ( rc ) );
goto err_getinfo; goto err_getinfo;
} }
size = info.info.FileSize; size = info.info.FileSize;
@ -122,7 +120,7 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
if ( ! size ) { if ( ! size ) {
rc = -EINVAL; rc = -EINVAL;
DBGC ( device, "EFI %s has zero-length %ls\n", DBGC ( device, "EFI %s has zero-length %ls\n",
efi_handle_name ( device ), name ); efi_handle_name ( device ), efi_autoexec_wname );
goto err_empty; goto err_empty;
} }
@ -131,7 +129,8 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
&data ) ) != 0 ) { &data ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not allocate %ls: %s\n", DBGC ( device, "EFI %s could not allocate %ls: %s\n",
efi_handle_name ( device ), name, strerror ( rc ) ); efi_handle_name ( device ), efi_autoexec_wname,
strerror ( rc ) );
goto err_alloc; goto err_alloc;
} }
@ -139,7 +138,8 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) { if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( device, "EFI %s could not read %ls: %s\n", DBGC ( device, "EFI %s could not read %ls: %s\n",
efi_handle_name ( device ), name, strerror ( rc ) ); efi_handle_name ( device ), efi_autoexec_wname,
strerror ( rc ) );
goto err_read; goto err_read;
} }
@ -148,7 +148,7 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
efi_autoexec_len = size; efi_autoexec_len = size;
data = NULL; data = NULL;
DBGC ( device, "EFI %s found %ls\n", DBGC ( device, "EFI %s found %ls\n",
efi_handle_name ( device ), name ); efi_handle_name ( device ), efi_autoexec_wname );
/* Success */ /* Success */
rc = 0; rc = 0;
@ -169,6 +169,26 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
return rc; return rc;
} }
/**
* Load autoexec script
*
* @v device Device handle
* @ret rc Return status code
*/
int efi_autoexec_load ( EFI_HANDLE device ) {
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 )
return 0;
return -ENOENT;
}
/** /**
* Register autoexec script * Register autoexec script
* *
@ -176,7 +196,6 @@ int efi_autoexec_load ( EFI_HANDLE device ) {
static void efi_autoexec_startup ( void ) { static void efi_autoexec_startup ( void ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE device = efi_loaded_image->DeviceHandle; EFI_HANDLE device = efi_loaded_image->DeviceHandle;
const char *name = AUTOEXEC_NAME;
struct image *image; struct image *image;
/* Do nothing if we have no autoexec script */ /* Do nothing if we have no autoexec script */
@ -184,15 +203,16 @@ static void efi_autoexec_startup ( void ) {
return; return;
/* Create autoexec image */ /* Create autoexec image */
image = image_memory ( name, virt_to_user ( efi_autoexec ), image = image_memory ( efi_autoexec_name,
virt_to_user ( efi_autoexec ),
efi_autoexec_len ); efi_autoexec_len );
if ( ! image ) { if ( ! image ) {
DBGC ( device, "EFI %s could not create %s\n", DBGC ( device, "EFI %s could not create %s\n",
efi_handle_name ( device ), name ); efi_handle_name ( device ), efi_autoexec_name );
return; return;
} }
DBGC ( device, "EFI %s registered %s\n", DBGC ( device, "EFI %s registered %s\n",
efi_handle_name ( device ), name ); efi_handle_name ( device ), efi_autoexec_name );
/* Free temporary copy */ /* Free temporary copy */
bs->FreePool ( efi_autoexec ); bs->FreePool ( efi_autoexec );