mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-19 21:51:31 +00:00
Pull request for EFI sub-system in U-Boot v2019.04-rc2
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAlxq+mUACgkQxIHbvCwF GsRxKQ/+NXcGaWEzxgIWj1HMVQsbf4lM+gXva2K60Ar/e10up2I8ARrnAnje//fi YSg98vdNS1HPoJ1H1oaC54NJgsiYyH1kdb0uxwGXrEAagB/6EWIWVuPaKTSAjXPa 8pb+I4xdZCPxIYtzczaSCeqjFoSwMovLxbQnkLWIjqrYoI4Skx1970/UoGt4EBlJ LI9RecTODPPmQQvC44y9Ao3fh6/qldJsJfNLMlQbr9+1OYfr1xBTLn2ry/LITzTm w+1OArjoRHyehEup/mx9eAXbX2b2ljp9x1J/Hazwn5CjHFP86Q9JYdisU42rJZHb 1m6uZZNxME2GdAQTI3YcmME0w1fIUMaTL3oNoOfKDLkYaj5QQOcLLAYY5+j8x1F+ hPhSutyIZ7DBT/oIODte+BboARkTRvGYgv842Sq3HtTMfL7uXdowABQ/XkdzuAYb d/NxMQxSti+Xk5mzmIcRJULBAZPs/SFNQjsTNmh64+rTDIYNzNRgj8XiQp4UkNVK 7+9CQ8R6qS6MF/KBF6FqGrVQ7cprrdFpvgejEL5qwhcQeTtJWsUi+oe1zRj4l7ip JRs22/HjTiytxe5wqPyoxQav+tKjj87jRfFqRuxqG1kfzRzcEhjbZhHrduC1jae4 Gtg+tEjhi0fu1l3p3Jrtx79mhy9kU6YKZ8ZGfu1qWbT6RTromdI= =BbQI -----END PGP SIGNATURE----- Merge tag 'efi-2019-04-rc2' of https://github.com/xypron2/u-boot The patches fix multiple errors. Mentionable are: - EFI unit tests (bootefi selftest) can run on i386. - `make tests` executes the Unicode unit tests. The LoadImage patch is preparing for further rework to be delivered in v2019.07.
This commit is contained in:
commit
beff8e34b2
16 changed files with 869 additions and 227 deletions
|
@ -9,6 +9,12 @@ Boot services
|
||||||
.. kernel-doc:: lib/efi_loader/efi_boottime.c
|
.. kernel-doc:: lib/efi_loader/efi_boottime.c
|
||||||
:internal:
|
:internal:
|
||||||
|
|
||||||
|
Image relocation
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. kernel-doc:: lib/efi_loader/efi_image_loader.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
Runtime services
|
Runtime services
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
@ -133,20 +133,6 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t efi_do_enter(
|
|
||||||
efi_handle_t image_handle, struct efi_system_table *st,
|
|
||||||
EFIAPI efi_status_t (*entry)(
|
|
||||||
efi_handle_t image_handle,
|
|
||||||
struct efi_system_table *st))
|
|
||||||
{
|
|
||||||
efi_status_t ret = EFI_LOAD_ERROR;
|
|
||||||
|
|
||||||
if (entry)
|
|
||||||
ret = entry(image_handle, st);
|
|
||||||
st->boottime->exit(image_handle, ret, 0, NULL);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
|
* efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
|
||||||
*
|
*
|
||||||
|
@ -266,9 +252,6 @@ static efi_status_t do_bootefi_exec(void *efi,
|
||||||
struct efi_loaded_image_obj *image_obj = NULL;
|
struct efi_loaded_image_obj *image_obj = NULL;
|
||||||
struct efi_loaded_image *loaded_image_info = NULL;
|
struct efi_loaded_image *loaded_image_info = NULL;
|
||||||
|
|
||||||
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
|
|
||||||
struct efi_system_table *st);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special case for efi payload not loaded from disk, such as
|
* Special case for efi payload not loaded from disk, such as
|
||||||
* 'bootefi hello' or for example payload loaded directly into
|
* 'bootefi hello' or for example payload loaded directly into
|
||||||
|
@ -300,11 +283,9 @@ static efi_status_t do_bootefi_exec(void *efi,
|
||||||
goto err_prepare;
|
goto err_prepare;
|
||||||
|
|
||||||
/* Load the EFI payload */
|
/* Load the EFI payload */
|
||||||
entry = efi_load_pe(image_obj, efi, loaded_image_info);
|
ret = efi_load_pe(image_obj, efi, loaded_image_info);
|
||||||
if (!entry) {
|
if (ret != EFI_SUCCESS)
|
||||||
ret = EFI_LOAD_ERROR;
|
|
||||||
goto err_prepare;
|
goto err_prepare;
|
||||||
}
|
|
||||||
|
|
||||||
if (memdp) {
|
if (memdp) {
|
||||||
struct efi_device_path_memory *mdp = (void *)memdp;
|
struct efi_device_path_memory *mdp = (void *)memdp;
|
||||||
|
@ -319,14 +300,8 @@ static efi_status_t do_bootefi_exec(void *efi,
|
||||||
"{ro,boot}(blob)0000000000000000");
|
"{ro,boot}(blob)0000000000000000");
|
||||||
|
|
||||||
/* Call our payload! */
|
/* Call our payload! */
|
||||||
debug("%s: Jumping to 0x%p\n", __func__, entry);
|
debug("%s: Jumping to 0x%p\n", __func__, image_obj->entry);
|
||||||
|
ret = EFI_CALL(efi_start_image(&image_obj->header, NULL, NULL));
|
||||||
if (setjmp(&image_obj->exit_jmp)) {
|
|
||||||
ret = image_obj->exit_status;
|
|
||||||
goto err_prepare;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = efi_do_enter(&image_obj->header, &systab, entry);
|
|
||||||
|
|
||||||
err_prepare:
|
err_prepare:
|
||||||
/* image has returned, loaded-image obj goes *poof*: */
|
/* image has returned, loaded-image obj goes *poof*: */
|
||||||
|
@ -343,38 +318,46 @@ err_add_protocol:
|
||||||
/**
|
/**
|
||||||
* bootefi_test_prepare() - prepare to run an EFI test
|
* bootefi_test_prepare() - prepare to run an EFI test
|
||||||
*
|
*
|
||||||
* This sets things up so we can call EFI functions. This involves preparing
|
* Prepare to run a test as if it were provided by a loaded image.
|
||||||
* the 'gd' pointer and setting up the load ed image data structures.
|
|
||||||
*
|
*
|
||||||
* @image_objp: loaded_image_infop: Pointer to a struct which will hold the
|
* @image_objp: pointer to be set to the loaded image handle
|
||||||
* loaded image object. This struct will be inited by this function before
|
* @loaded_image_infop: pointer to be set to the loaded image protocol
|
||||||
* use.
|
* @path: dummy file path used to construct the device path
|
||||||
* @loaded_image_infop: Pointer to a struct which will hold the loaded image
|
* set in the loaded image protocol
|
||||||
* info. This struct will be inited by this function before use.
|
* @load_options_path: name of a U-Boot environment variable. Its value is
|
||||||
* @path: File path to the test being run (often just the test name with a
|
* set as load options in the loaded image protocol.
|
||||||
* backslash before it
|
* Return: status code
|
||||||
* @test_func: Address of the test function that is being run
|
|
||||||
* @load_options_path: U-Boot environment variable to use as load options
|
|
||||||
* @return 0 if OK, -ve on error
|
|
||||||
*/
|
*/
|
||||||
static efi_status_t bootefi_test_prepare
|
static efi_status_t bootefi_test_prepare
|
||||||
(struct efi_loaded_image_obj **image_objp,
|
(struct efi_loaded_image_obj **image_objp,
|
||||||
struct efi_loaded_image **loaded_image_infop, const char *path,
|
struct efi_loaded_image **loaded_image_infop, const char *path,
|
||||||
ulong test_func, const char *load_options_path)
|
const char *load_options_path)
|
||||||
{
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
/* Construct a dummy device path */
|
/* Construct a dummy device path */
|
||||||
bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
|
bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
|
||||||
(uintptr_t)test_func,
|
|
||||||
(uintptr_t)test_func);
|
|
||||||
if (!bootefi_device_path)
|
if (!bootefi_device_path)
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
bootefi_image_path = efi_dp_from_file(NULL, 0, path);
|
|
||||||
if (!bootefi_image_path)
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
|
|
||||||
return bootefi_run_prepare(load_options_path, bootefi_device_path,
|
bootefi_image_path = efi_dp_from_file(NULL, 0, path);
|
||||||
bootefi_image_path, image_objp,
|
if (!bootefi_image_path) {
|
||||||
loaded_image_infop);
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bootefi_run_prepare(load_options_path, bootefi_device_path,
|
||||||
|
bootefi_image_path, image_objp,
|
||||||
|
loaded_image_infop);
|
||||||
|
if (ret == EFI_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
efi_free_pool(bootefi_image_path);
|
||||||
|
bootefi_image_path = NULL;
|
||||||
|
failure:
|
||||||
|
efi_free_pool(bootefi_device_path);
|
||||||
|
bootefi_device_path = NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
|
#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
|
||||||
|
@ -456,13 +439,13 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
struct efi_loaded_image_obj *image_obj;
|
struct efi_loaded_image_obj *image_obj;
|
||||||
struct efi_loaded_image *loaded_image_info;
|
struct efi_loaded_image *loaded_image_info;
|
||||||
|
|
||||||
if (bootefi_test_prepare(&image_obj, &loaded_image_info,
|
r = bootefi_test_prepare(&image_obj, &loaded_image_info,
|
||||||
"\\selftest", (uintptr_t)&efi_selftest,
|
"\\selftest", "efi_selftest");
|
||||||
"efi_selftest"))
|
if (r != EFI_SUCCESS)
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
/* Execute the test */
|
/* Execute the test */
|
||||||
r = efi_selftest(&image_obj->header, &systab);
|
r = EFI_CALL(efi_selftest(&image_obj->header, &systab));
|
||||||
bootefi_run_finish(image_obj, loaded_image_info);
|
bootefi_run_finish(image_obj, loaded_image_info);
|
||||||
return r != EFI_SUCCESS;
|
return r != EFI_SUCCESS;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -301,8 +301,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
|
||||||
/* Called from places to check whether a timer expired */
|
/* Called from places to check whether a timer expired */
|
||||||
void efi_timer_check(void);
|
void efi_timer_check(void);
|
||||||
/* PE loader implementation */
|
/* PE loader implementation */
|
||||||
void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
struct efi_loaded_image *loaded_image_info);
|
struct efi_loaded_image *loaded_image_info);
|
||||||
/* Called once to store the pristine gd pointer */
|
/* Called once to store the pristine gd pointer */
|
||||||
void efi_save_gd(void);
|
void efi_save_gd(void);
|
||||||
/* Special case handler for error/abort that just tries to dtrt to get
|
/* Special case handler for error/abort that just tries to dtrt to get
|
||||||
|
@ -320,6 +320,10 @@ efi_status_t efi_create_handle(efi_handle_t *handle);
|
||||||
void efi_delete_handle(efi_handle_t obj);
|
void efi_delete_handle(efi_handle_t obj);
|
||||||
/* Call this to validate a handle and find the EFI object for it */
|
/* Call this to validate a handle and find the EFI object for it */
|
||||||
struct efi_object *efi_search_obj(const efi_handle_t handle);
|
struct efi_object *efi_search_obj(const efi_handle_t handle);
|
||||||
|
/* Start image */
|
||||||
|
efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||||
|
efi_uintn_t *exit_data_size,
|
||||||
|
u16 **exit_data);
|
||||||
/* Find a protocol on a handle */
|
/* Find a protocol on a handle */
|
||||||
efi_status_t efi_search_protocol(const efi_handle_t handle,
|
efi_status_t efi_search_protocol(const efi_handle_t handle,
|
||||||
const efi_guid_t *protocol_guid,
|
const efi_guid_t *protocol_guid,
|
||||||
|
@ -397,7 +401,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
struct efi_loaded_image_obj **handle_ptr,
|
struct efi_loaded_image_obj **handle_ptr,
|
||||||
struct efi_loaded_image **info_ptr);
|
struct efi_loaded_image **info_ptr);
|
||||||
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
|
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
|
||||||
void **buffer);
|
void **buffer, efi_uintn_t *size);
|
||||||
/* Print information about all loaded images */
|
/* Print information about all loaded images */
|
||||||
void efi_print_image_infos(void *pc);
|
void efi_print_image_infos(void *pc);
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
|
||||||
debug("%s: trying to load \"%ls\" from %pD\n",
|
debug("%s: trying to load \"%ls\" from %pD\n",
|
||||||
__func__, lo.label, lo.file_path);
|
__func__, lo.label, lo.file_path);
|
||||||
|
|
||||||
ret = efi_load_image_from_path(lo.file_path, &image);
|
ret = efi_load_image_from_path(lo.file_path, &image, &size);
|
||||||
|
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -44,7 +44,8 @@ static bool efi_is_direct_boot = true;
|
||||||
static volatile void *efi_gd, *app_gd;
|
static volatile void *efi_gd, *app_gd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int entry_count;
|
/* 1 if inside U-Boot code, 0 if inside EFI payload code */
|
||||||
|
static int entry_count = 1;
|
||||||
static int nesting_level;
|
static int nesting_level;
|
||||||
/* GUID of the device tree table */
|
/* GUID of the device tree table */
|
||||||
const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
|
const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
|
||||||
|
@ -1497,15 +1498,18 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_setup_loaded_image() - initialize a loaded image
|
* efi_setup_loaded_image() - initialize a loaded image
|
||||||
* @info: loaded image info to be passed to the entry point of the image
|
|
||||||
* @obj: internal object associated with the loaded image
|
|
||||||
* @device_path: device path of the loaded image
|
|
||||||
* @file_path: file path of the loaded image
|
|
||||||
*
|
*
|
||||||
* Initialize a loaded_image_info and loaded_image_info object with correct
|
* Initialize a loaded_image_info and loaded_image_info object with correct
|
||||||
* protocols, boot-device, etc.
|
* protocols, boot-device, etc.
|
||||||
*
|
*
|
||||||
* Return: status code
|
* In case of an error *handle_ptr and *info_ptr are set to NULL and an error
|
||||||
|
* code is returned.
|
||||||
|
*
|
||||||
|
* @device_path: device path of the loaded image
|
||||||
|
* @file_path: file path of the loaded image
|
||||||
|
* @handle_ptr: handle of the loaded image
|
||||||
|
* @info_ptr: loaded image protocol
|
||||||
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
struct efi_device_path *file_path,
|
struct efi_device_path *file_path,
|
||||||
|
@ -1513,8 +1517,12 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
struct efi_loaded_image **info_ptr)
|
struct efi_loaded_image **info_ptr)
|
||||||
{
|
{
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
struct efi_loaded_image *info;
|
struct efi_loaded_image *info = NULL;
|
||||||
struct efi_loaded_image_obj *obj;
|
struct efi_loaded_image_obj *obj = NULL;
|
||||||
|
|
||||||
|
/* In case of EFI_OUT_OF_RESOURCES avoid illegal free by caller. */
|
||||||
|
*handle_ptr = NULL;
|
||||||
|
*info_ptr = NULL;
|
||||||
|
|
||||||
info = calloc(1, sizeof(*info));
|
info = calloc(1, sizeof(*info));
|
||||||
if (!info)
|
if (!info)
|
||||||
|
@ -1528,11 +1536,6 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
/* Add internal object to object list */
|
/* Add internal object to object list */
|
||||||
efi_add_handle(&obj->header);
|
efi_add_handle(&obj->header);
|
||||||
|
|
||||||
if (info_ptr)
|
|
||||||
*info_ptr = info;
|
|
||||||
if (handle_ptr)
|
|
||||||
*handle_ptr = obj;
|
|
||||||
|
|
||||||
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
|
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
|
||||||
info->file_path = file_path;
|
info->file_path = file_path;
|
||||||
info->system_table = &systab;
|
info->system_table = &systab;
|
||||||
|
@ -1578,58 +1581,87 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
goto failure;
|
goto failure;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (info_ptr)
|
||||||
|
*info_ptr = info;
|
||||||
|
if (handle_ptr)
|
||||||
|
*handle_ptr = obj;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
failure:
|
failure:
|
||||||
printf("ERROR: Failure to install protocols for loaded image\n");
|
printf("ERROR: Failure to install protocols for loaded image\n");
|
||||||
|
efi_delete_handle(&obj->header);
|
||||||
|
free(info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_load_image_from_path() - load an image using a file path
|
* efi_load_image_from_path() - load an image using a file path
|
||||||
* @file_path: the path of the image to load
|
|
||||||
* @buffer: buffer containing the loaded image
|
|
||||||
*
|
*
|
||||||
* Return: status code
|
* 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
|
||||||
*/
|
*/
|
||||||
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
|
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
|
||||||
void **buffer)
|
void **buffer, efi_uintn_t *size)
|
||||||
{
|
{
|
||||||
struct efi_file_info *info = NULL;
|
struct efi_file_info *info = NULL;
|
||||||
struct efi_file_handle *f;
|
struct efi_file_handle *f;
|
||||||
static efi_status_t ret;
|
static efi_status_t ret;
|
||||||
|
u64 addr;
|
||||||
efi_uintn_t bs;
|
efi_uintn_t bs;
|
||||||
|
|
||||||
|
/* In case of failure nothing is returned */
|
||||||
|
*buffer = NULL;
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
f = efi_file_from_path(file_path);
|
f = efi_file_from_path(file_path);
|
||||||
if (!f)
|
if (!f)
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
|
|
||||||
|
/* Get file size */
|
||||||
bs = 0;
|
bs = 0;
|
||||||
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
|
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
|
||||||
&bs, info));
|
&bs, info));
|
||||||
if (ret == EFI_BUFFER_TOO_SMALL) {
|
if (ret != EFI_BUFFER_TOO_SMALL) {
|
||||||
info = malloc(bs);
|
ret = EFI_DEVICE_ERROR;
|
||||||
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
|
goto error;
|
||||||
&bs, info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info = malloc(bs);
|
||||||
|
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
|
||||||
|
info));
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
|
/*
|
||||||
if (ret)
|
* When reading the file we do not yet know if it contains an
|
||||||
goto error;
|
* application, a boottime driver, or a runtime driver. So here we
|
||||||
|
* allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
|
||||||
|
* update the reservation according to the image type.
|
||||||
|
*/
|
||||||
bs = info->file_size;
|
bs = info->file_size;
|
||||||
EFI_CALL(ret = f->read(f, &bs, *buffer));
|
ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
|
||||||
|
EFI_BOOT_SERVICES_DATA,
|
||||||
error:
|
efi_size_in_pages(bs), &addr);
|
||||||
free(info);
|
|
||||||
EFI_CALL(f->close(f));
|
|
||||||
|
|
||||||
if (ret != EFI_SUCCESS) {
|
if (ret != EFI_SUCCESS) {
|
||||||
efi_free_pool(*buffer);
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
*buffer = NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read file */
|
||||||
|
EFI_CALL(ret = f->read(f, &bs, (void *)(uintptr_t)addr));
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
efi_free_pages(addr, efi_size_in_pages(bs));
|
||||||
|
*buffer = (void *)(uintptr_t)addr;
|
||||||
|
*size = bs;
|
||||||
|
error:
|
||||||
|
EFI_CALL(f->close(f));
|
||||||
|
free(info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,6 +1688,7 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||||
efi_uintn_t source_size,
|
efi_uintn_t source_size,
|
||||||
efi_handle_t *image_handle)
|
efi_handle_t *image_handle)
|
||||||
{
|
{
|
||||||
|
struct efi_device_path *dp, *fp;
|
||||||
struct efi_loaded_image *info = NULL;
|
struct efi_loaded_image *info = NULL;
|
||||||
struct efi_loaded_image_obj **image_obj =
|
struct efi_loaded_image_obj **image_obj =
|
||||||
(struct efi_loaded_image_obj **)image_handle;
|
(struct efi_loaded_image_obj **)image_handle;
|
||||||
|
@ -1675,36 +1708,51 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!source_buffer) {
|
if (!source_buffer) {
|
||||||
struct efi_device_path *dp, *fp;
|
ret = efi_load_image_from_path(file_path, &source_buffer,
|
||||||
|
&source_size);
|
||||||
ret = efi_load_image_from_path(file_path, &source_buffer);
|
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
goto failure;
|
goto error;
|
||||||
/*
|
/*
|
||||||
* split file_path which contains both the device and
|
* split file_path which contains both the device and
|
||||||
* file parts:
|
* file parts:
|
||||||
*/
|
*/
|
||||||
efi_dp_split_file_path(file_path, &dp, &fp);
|
efi_dp_split_file_path(file_path, &dp, &fp);
|
||||||
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
|
|
||||||
if (ret != EFI_SUCCESS)
|
|
||||||
goto failure;
|
|
||||||
} else {
|
} else {
|
||||||
/* In this case, file_path is the "device" path, i.e.
|
/* In this case, file_path is the "device" path, i.e.
|
||||||
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
|
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
|
||||||
*/
|
*/
|
||||||
ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
|
u64 addr;
|
||||||
|
void *dest_buffer;
|
||||||
|
|
||||||
|
ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
|
||||||
|
EFI_RUNTIME_SERVICES_CODE,
|
||||||
|
efi_size_in_pages(source_size), &addr);
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
|
dest_buffer = (void *)(uintptr_t)addr;
|
||||||
|
memcpy(dest_buffer, source_buffer, source_size);
|
||||||
|
source_buffer = dest_buffer;
|
||||||
|
|
||||||
|
dp = file_path;
|
||||||
|
fp = NULL;
|
||||||
}
|
}
|
||||||
(*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
|
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
|
||||||
if (!(*image_obj)->entry) {
|
if (ret != EFI_SUCCESS)
|
||||||
ret = EFI_UNSUPPORTED;
|
goto error_invalid_image;
|
||||||
goto failure;
|
ret = efi_load_pe(*image_obj, source_buffer, info);
|
||||||
}
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto error_invalid_image;
|
||||||
|
/* Update the type of the allocated memory */
|
||||||
|
efi_add_memory_map((uintptr_t)source_buffer,
|
||||||
|
efi_size_in_pages(source_size),
|
||||||
|
info->image_code_type, false);
|
||||||
info->system_table = &systab;
|
info->system_table = &systab;
|
||||||
info->parent_handle = parent_image;
|
info->parent_handle = parent_image;
|
||||||
return EFI_EXIT(EFI_SUCCESS);
|
return EFI_EXIT(EFI_SUCCESS);
|
||||||
failure:
|
error_invalid_image:
|
||||||
|
/* The image is invalid. Release all associated resources. */
|
||||||
|
efi_free_pages((uintptr_t)source_buffer,
|
||||||
|
efi_size_in_pages(source_size));
|
||||||
efi_delete_handle(*image_handle);
|
efi_delete_handle(*image_handle);
|
||||||
*image_handle = NULL;
|
*image_handle = NULL;
|
||||||
free(info);
|
free(info);
|
||||||
|
@ -1725,9 +1773,9 @@ error:
|
||||||
*
|
*
|
||||||
* Return: status code
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||||
efi_uintn_t *exit_data_size,
|
efi_uintn_t *exit_data_size,
|
||||||
u16 **exit_data)
|
u16 **exit_data)
|
||||||
{
|
{
|
||||||
struct efi_loaded_image_obj *image_obj =
|
struct efi_loaded_image_obj *image_obj =
|
||||||
(struct efi_loaded_image_obj *)image_handle;
|
(struct efi_loaded_image_obj *)image_handle;
|
||||||
|
|
|
@ -910,9 +910,17 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Helper to split a full device path (containing both device and file
|
* efi_dp_split_file_path() - split of relative file path from device path
|
||||||
* parts) into it's constituent parts.
|
*
|
||||||
|
* Given a device path indicating a file on a device, separate the device
|
||||||
|
* path in two: the device path of the actual device and the file path
|
||||||
|
* relative to this device.
|
||||||
|
*
|
||||||
|
* @full_path: device path including device and file path
|
||||||
|
* @device_path: path of the device
|
||||||
|
* @file_path: relative path of the file
|
||||||
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
|
efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
|
||||||
struct efi_device_path **device_path,
|
struct efi_device_path **device_path,
|
||||||
|
@ -929,7 +937,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
|
||||||
while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
|
while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
|
||||||
p = efi_dp_next(p);
|
p = efi_dp_next(p);
|
||||||
if (!p)
|
if (!p)
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
fp = efi_dp_dup(p);
|
fp = efi_dp_dup(p);
|
||||||
if (!fp)
|
if (!fp)
|
||||||
|
|
|
@ -641,6 +641,12 @@ static const struct efi_file_handle efi_file_handle_protocol = {
|
||||||
.flush = efi_file_flush,
|
.flush = efi_file_flush,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_file_handle *efi_file_from_path(struct efi_device_path *fp)
|
||||||
{
|
{
|
||||||
struct efi_simple_file_system_protocol *v;
|
struct efi_simple_file_system_protocol *v;
|
||||||
|
@ -655,10 +661,14 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* skip over device-path nodes before the file path: */
|
/* Skip over device-path nodes before the file path. */
|
||||||
while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
|
while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
|
||||||
fp = efi_dp_next(fp);
|
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.
|
||||||
|
*/
|
||||||
while (fp) {
|
while (fp) {
|
||||||
struct efi_device_path_file_path *fdp =
|
struct efi_device_path_file_path *fdp =
|
||||||
container_of(fp, struct efi_device_path_file_path, dp);
|
container_of(fp, struct efi_device_path_file_path, dp);
|
||||||
|
|
|
@ -42,8 +42,8 @@ static int machines[] = {
|
||||||
#endif
|
#endif
|
||||||
0 };
|
0 };
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Print information about a loaded image.
|
* efi_print_image_info() - print information about a loaded image
|
||||||
*
|
*
|
||||||
* If the program counter is located within the image the offset to the base
|
* If the program counter is located within the image the offset to the base
|
||||||
* address is shown.
|
* address is shown.
|
||||||
|
@ -51,7 +51,7 @@ static int machines[] = {
|
||||||
* @obj: EFI object
|
* @obj: EFI object
|
||||||
* @image: loaded image
|
* @image: loaded image
|
||||||
* @pc: program counter (use NULL to suppress offset output)
|
* @pc: program counter (use NULL to suppress offset output)
|
||||||
* @return: status code
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
|
static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
|
||||||
struct efi_loaded_image *image,
|
struct efi_loaded_image *image,
|
||||||
|
@ -69,8 +69,8 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Print information about all loaded images.
|
* efi_print_image_infos() - print information about all loaded images
|
||||||
*
|
*
|
||||||
* @pc: program counter (use NULL to suppress offset output)
|
* @pc: program counter (use NULL to suppress offset output)
|
||||||
*/
|
*/
|
||||||
|
@ -90,6 +90,15 @@ void efi_print_image_infos(void *pc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_loader_relocate() - relocate UEFI binary
|
||||||
|
*
|
||||||
|
* @rel: pointer to the relocation table
|
||||||
|
* @rel_size: size of the relocation table in bytes
|
||||||
|
* @efi_reloc: actual load address of the image
|
||||||
|
* @pref_address: preferred load address of the image
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
|
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
|
||||||
unsigned long rel_size, void *efi_reloc,
|
unsigned long rel_size, void *efi_reloc,
|
||||||
unsigned long pref_address)
|
unsigned long pref_address)
|
||||||
|
@ -102,7 +111,7 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
|
end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
|
||||||
while (rel < end - 1 && rel->SizeOfBlock) {
|
while (rel < end && rel->SizeOfBlock) {
|
||||||
const uint16_t *relocs = (const uint16_t *)(rel + 1);
|
const uint16_t *relocs = (const uint16_t *)(rel + 1);
|
||||||
i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
|
i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
@ -159,11 +168,12 @@ void __weak invalidate_icache_all(void)
|
||||||
/* If the system doesn't support icache_all flush, cross our fingers */
|
/* If the system doesn't support icache_all flush, cross our fingers */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Determine the memory types to be used for code and data.
|
* efi_set_code_and_data_type() - determine the memory types to be used for code
|
||||||
|
* and data.
|
||||||
*
|
*
|
||||||
* @loaded_image_info image descriptor
|
* @loaded_image_info: image descriptor
|
||||||
* @image_type field Subsystem of the optional header for
|
* @image_type: field Subsystem of the optional header for
|
||||||
* Windows specific field
|
* Windows specific field
|
||||||
*/
|
*/
|
||||||
static void efi_set_code_and_data_type(
|
static void efi_set_code_and_data_type(
|
||||||
|
@ -193,13 +203,19 @@ static void efi_set_code_and_data_type(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* efi_load_pe() - relocate EFI binary
|
||||||
|
*
|
||||||
* This function loads all sections from a PE binary into a newly reserved
|
* This function loads all sections from a PE binary into a newly reserved
|
||||||
* piece of memory. On successful load it then returns the entry point for
|
* piece of memory. On success the entry point is returned as handle->entry.
|
||||||
* the binary. Otherwise NULL.
|
*
|
||||||
|
* @handle: loaded image handle
|
||||||
|
* @efi: pointer to the EFI binary
|
||||||
|
* @loaded_image_info: loaded image protocol
|
||||||
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
struct efi_loaded_image *loaded_image_info)
|
struct efi_loaded_image *loaded_image_info)
|
||||||
{
|
{
|
||||||
IMAGE_NT_HEADERS32 *nt;
|
IMAGE_NT_HEADERS32 *nt;
|
||||||
IMAGE_DOS_HEADER *dos;
|
IMAGE_DOS_HEADER *dos;
|
||||||
|
@ -210,7 +226,6 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
const IMAGE_BASE_RELOCATION *rel;
|
const IMAGE_BASE_RELOCATION *rel;
|
||||||
unsigned long rel_size;
|
unsigned long rel_size;
|
||||||
int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
|
int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
|
||||||
void *entry;
|
|
||||||
uint64_t image_base;
|
uint64_t image_base;
|
||||||
uint64_t image_size;
|
uint64_t image_size;
|
||||||
unsigned long virt_size = 0;
|
unsigned long virt_size = 0;
|
||||||
|
@ -219,13 +234,13 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
dos = efi;
|
dos = efi;
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
|
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
printf("%s: Invalid DOS Signature\n", __func__);
|
printf("%s: Invalid DOS Signature\n", __func__);
|
||||||
return NULL;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
nt = (void *) ((char *)efi + dos->e_lfanew);
|
nt = (void *) ((char *)efi + dos->e_lfanew);
|
||||||
if (nt->Signature != IMAGE_NT_SIGNATURE) {
|
if (nt->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
printf("%s: Invalid NT Signature\n", __func__);
|
printf("%s: Invalid NT Signature\n", __func__);
|
||||||
return NULL;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; machines[i]; i++)
|
for (i = 0; machines[i]; i++)
|
||||||
|
@ -237,7 +252,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
printf("%s: Machine type 0x%04x is not supported\n",
|
printf("%s: Machine type 0x%04x is not supported\n",
|
||||||
__func__, nt->FileHeader.Machine);
|
__func__, nt->FileHeader.Machine);
|
||||||
return NULL;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate upper virtual address boundary */
|
/* Calculate upper virtual address boundary */
|
||||||
|
@ -263,9 +278,9 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
printf("%s: Could not allocate %lu bytes\n",
|
printf("%s: Could not allocate %lu bytes\n",
|
||||||
__func__, virt_size);
|
__func__, virt_size);
|
||||||
return NULL;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
entry = efi_reloc + opt->AddressOfEntryPoint;
|
handle->entry = efi_reloc + opt->AddressOfEntryPoint;
|
||||||
rel_size = opt->DataDirectory[rel_idx].Size;
|
rel_size = opt->DataDirectory[rel_idx].Size;
|
||||||
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
|
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
|
||||||
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
||||||
|
@ -279,16 +294,16 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
printf("%s: Could not allocate %lu bytes\n",
|
printf("%s: Could not allocate %lu bytes\n",
|
||||||
__func__, virt_size);
|
__func__, virt_size);
|
||||||
return NULL;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
entry = efi_reloc + opt->AddressOfEntryPoint;
|
handle->entry = efi_reloc + opt->AddressOfEntryPoint;
|
||||||
rel_size = opt->DataDirectory[rel_idx].Size;
|
rel_size = opt->DataDirectory[rel_idx].Size;
|
||||||
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
|
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
|
||||||
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
||||||
} else {
|
} else {
|
||||||
printf("%s: Invalid optional header magic %x\n", __func__,
|
printf("%s: Invalid optional header magic %x\n", __func__,
|
||||||
nt->OptionalHeader.Magic);
|
nt->OptionalHeader.Magic);
|
||||||
return NULL;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load sections into RAM */
|
/* Load sections into RAM */
|
||||||
|
@ -306,7 +321,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
(unsigned long)image_base) != EFI_SUCCESS) {
|
(unsigned long)image_base) != EFI_SUCCESS) {
|
||||||
efi_free_pages((uintptr_t) efi_reloc,
|
efi_free_pages((uintptr_t) efi_reloc,
|
||||||
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
|
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
|
||||||
return NULL;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush cache */
|
/* Flush cache */
|
||||||
|
@ -320,5 +335,5 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
handle->reloc_base = efi_reloc;
|
handle->reloc_base = efi_reloc;
|
||||||
handle->reloc_size = virt_size;
|
handle->reloc_size = virt_size;
|
||||||
|
|
||||||
return entry;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ endif
|
||||||
ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M)$(CONFIG_X86_64),)
|
ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M)$(CONFIG_X86_64),)
|
||||||
|
|
||||||
obj-y += \
|
obj-y += \
|
||||||
|
efi_selftest_loadimage.o \
|
||||||
efi_selftest_startimage_exit.o \
|
efi_selftest_startimage_exit.o \
|
||||||
efi_selftest_startimage_return.o
|
efi_selftest_startimage_return.o
|
||||||
|
|
||||||
|
@ -68,6 +69,8 @@ $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
|
||||||
$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
|
$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
|
||||||
$(obj)/efi_miniapp_file_image_return.h
|
$(obj)/efi_miniapp_file_image_return.h
|
||||||
|
|
||||||
|
$(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
|
||||||
|
|
||||||
$(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
|
$(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
|
||||||
|
|
||||||
$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
|
$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
|
||||||
|
|
|
@ -264,7 +264,7 @@ static int teardown(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
r = efi_free_pool(image);
|
r = boottime->free_pool(image);
|
||||||
if (r != EFI_SUCCESS) {
|
if (r != EFI_SUCCESS) {
|
||||||
efi_st_error("Failed to free image\n");
|
efi_st_error("Failed to free image\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <efi_selftest.h>
|
#include <efi_selftest.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include "efi_selftest_hii_data.c"
|
#include "efi_selftest_hii_data.c"
|
||||||
|
|
||||||
#define PRINT_TESTNAME efi_st_printf("%s:\n", __func__)
|
#define PRINT_TESTNAME efi_st_printf("%s:\n", __func__)
|
||||||
|
@ -192,9 +191,10 @@ static int test_hii_database_list_package_lists(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handles = malloc(handles_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
|
||||||
if (!handles) {
|
(void **)&handles);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_database_protocol->list_package_lists(hii_database_protocol,
|
ret = hii_database_protocol->list_package_lists(hii_database_protocol,
|
||||||
|
@ -205,7 +205,11 @@ static int test_hii_database_list_package_lists(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(handles);
|
ret = boottime->free_pool(handles);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* STRINGS */
|
/* STRINGS */
|
||||||
handles = NULL;
|
handles = NULL;
|
||||||
|
@ -219,9 +223,10 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handles = malloc(handles_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
|
||||||
if (!handles) {
|
(void **)&handles);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +239,11 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(handles);
|
ret = boottime->free_pool(handles);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* GUID */
|
/* GUID */
|
||||||
handles = NULL;
|
handles = NULL;
|
||||||
|
@ -248,9 +257,10 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handles = malloc(handles_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
|
||||||
if (!handles) {
|
(void **)&handles);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +273,12 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(handles);
|
ret = boottime->free_pool(handles);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
ret = EFI_ST_FAILURE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* KEYBOARD_LAYOUT */
|
/* KEYBOARD_LAYOUT */
|
||||||
handles = NULL;
|
handles = NULL;
|
||||||
|
@ -277,9 +292,10 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handles = malloc(handles_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
|
||||||
if (!handles) {
|
(void **)&handles);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +308,12 @@ static int test_hii_database_list_package_lists(void)
|
||||||
ret = EFI_ST_FAILURE;
|
ret = EFI_ST_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(handles);
|
ret = boottime->free_pool(handles);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
ret = EFI_ST_FAILURE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
result = EFI_ST_SUCCESS;
|
result = EFI_ST_SUCCESS;
|
||||||
|
|
||||||
|
@ -398,9 +419,10 @@ static int test_hii_database_find_keyboard_layouts(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
guids = malloc(guids_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, guids_size,
|
||||||
if (!guids) {
|
(void **)&guids);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_database_protocol->find_keyboard_layouts(
|
ret = hii_database_protocol->find_keyboard_layouts(
|
||||||
|
@ -410,7 +432,11 @@ static int test_hii_database_find_keyboard_layouts(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(guids);
|
ret = boottime->free_pool(guids);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
result = EFI_ST_SUCCESS;
|
result = EFI_ST_SUCCESS;
|
||||||
|
|
||||||
|
@ -479,9 +505,10 @@ static int test_hii_database_get_keyboard_layout(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
kb_layout = malloc(kb_layout_size);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, kb_layout_size,
|
||||||
if (!kb_layout) {
|
(void **)&kb_layout);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
|
ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
|
||||||
|
@ -491,7 +518,11 @@ static int test_hii_database_get_keyboard_layout(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(kb_layout);
|
ret = boottime->free_pool(kb_layout);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("FreePool failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* current */
|
/* current */
|
||||||
kb_layout = NULL;
|
kb_layout = NULL;
|
||||||
|
@ -738,9 +769,10 @@ static int test_hii_string_get_string(void)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
string_len += sizeof(u16);
|
string_len += sizeof(u16);
|
||||||
string = malloc(string_len);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, string_len,
|
||||||
if (!string) {
|
(void **)&string);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_string_protocol->get_string(hii_string_protocol,
|
ret = hii_string_protocol->get_string(hii_string_protocol,
|
||||||
|
@ -875,9 +907,10 @@ static int test_hii_string_get_languages(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
languages = malloc(languages_len);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
|
||||||
if (!languages) {
|
(void **)&languages);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
|
ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
|
||||||
|
@ -947,9 +980,10 @@ static int test_hii_string_get_secondary_languages(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
languages = malloc(languages_len);
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
|
||||||
if (!languages) {
|
(void **)&languages);
|
||||||
efi_st_error("malloc failed\n");
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("AllocatePool failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
|
ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
|
||||||
|
|
529
lib/efi_selftest/efi_selftest_loadimage.c
Normal file
529
lib/efi_selftest/efi_selftest_loadimage.c
Normal file
|
@ -0,0 +1,529 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* efi_selftest_loadimage
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||||
|
*
|
||||||
|
* This test checks the LoadImage and StartImage boot service.
|
||||||
|
*
|
||||||
|
* The efi_selftest_miniapp_exit.efi application is loaded via a file device
|
||||||
|
* path and started.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <efi_selftest.h>
|
||||||
|
/* Include containing the efi_selftest_miniapp_exit.efi application */
|
||||||
|
#include "efi_miniapp_file_image_exit.h"
|
||||||
|
|
||||||
|
/* Block size of compressed disk image */
|
||||||
|
#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
|
||||||
|
|
||||||
|
/* Binary logarithm of the block size */
|
||||||
|
#define LB_BLOCK_SIZE 9
|
||||||
|
|
||||||
|
#define FILE_NAME L"app.efi"
|
||||||
|
#define VOLUME_NAME L"EfiDisk"
|
||||||
|
|
||||||
|
static struct efi_boot_services *boottime;
|
||||||
|
static efi_handle_t handle_image;
|
||||||
|
static efi_handle_t handle_volume;
|
||||||
|
|
||||||
|
static const efi_guid_t guid_device_path = DEVICE_PATH_GUID;
|
||||||
|
static const efi_guid_t guid_simple_file_system_protocol =
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
||||||
|
static const efi_guid_t guid_file_info = EFI_FILE_INFO_GUID;
|
||||||
|
static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID;
|
||||||
|
|
||||||
|
/* One 8 byte block of the compressed disk image */
|
||||||
|
struct line {
|
||||||
|
size_t addr;
|
||||||
|
char *line;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compressed file image */
|
||||||
|
struct compressed_file_image {
|
||||||
|
size_t length;
|
||||||
|
struct line lines[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* File info including file name */
|
||||||
|
struct file_info {
|
||||||
|
struct efi_file_info info;
|
||||||
|
u16 file_name[sizeof(FILE_NAME)];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* File system info including volume name */
|
||||||
|
struct file_system_info {
|
||||||
|
struct efi_file_system_info info;
|
||||||
|
u16 file_name[sizeof(VOLUME_NAME)];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compressed file image */
|
||||||
|
static struct compressed_file_image img = EFI_ST_DISK_IMG;
|
||||||
|
|
||||||
|
/* Pointer to decompressed file image */
|
||||||
|
static u8 *image;
|
||||||
|
|
||||||
|
/* File info */
|
||||||
|
static struct file_info priv_file_info = {
|
||||||
|
{
|
||||||
|
.size = sizeof(struct file_info),
|
||||||
|
.attribute = EFI_FILE_READ_ONLY,
|
||||||
|
},
|
||||||
|
FILE_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pointer to file info */
|
||||||
|
struct efi_file_info *file_info = &priv_file_info.info;
|
||||||
|
|
||||||
|
/* Volume device path */
|
||||||
|
static struct {
|
||||||
|
struct efi_device_path_vendor vendor;
|
||||||
|
struct efi_device_path end;
|
||||||
|
} __packed dp_volume = {
|
||||||
|
.vendor = {
|
||||||
|
.dp = {
|
||||||
|
.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
|
||||||
|
.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
|
||||||
|
.length = sizeof(struct efi_device_path_vendor),
|
||||||
|
},
|
||||||
|
.guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
|
||||||
|
0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
|
||||||
|
},
|
||||||
|
.end = {
|
||||||
|
.type = DEVICE_PATH_TYPE_END,
|
||||||
|
.sub_type = DEVICE_PATH_SUB_TYPE_END,
|
||||||
|
.length = sizeof(struct efi_device_path),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* File device path */
|
||||||
|
static struct {
|
||||||
|
struct efi_device_path_vendor vendor;
|
||||||
|
struct efi_device_path path;
|
||||||
|
u16 file[sizeof(FILE_NAME)];
|
||||||
|
struct efi_device_path end;
|
||||||
|
} __packed dp_file = {
|
||||||
|
.vendor = {
|
||||||
|
.dp = {
|
||||||
|
.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
|
||||||
|
.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
|
||||||
|
.length = sizeof(struct efi_device_path_vendor),
|
||||||
|
},
|
||||||
|
.guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
|
||||||
|
0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
|
||||||
|
},
|
||||||
|
.path = {
|
||||||
|
.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
|
||||||
|
.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
|
||||||
|
.length = sizeof(struct efi_device_path) + sizeof(dp_file.file),
|
||||||
|
},
|
||||||
|
.file = FILE_NAME,
|
||||||
|
.end = {
|
||||||
|
.type = DEVICE_PATH_TYPE_END,
|
||||||
|
.sub_type = DEVICE_PATH_SUB_TYPE_END,
|
||||||
|
.length = sizeof(struct efi_device_path),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* File system info */
|
||||||
|
static struct file_system_info priv_file_system_info = {
|
||||||
|
{
|
||||||
|
.size = sizeof(struct file_system_info),
|
||||||
|
.read_only = true,
|
||||||
|
.volume_size = 0x100000,
|
||||||
|
.free_space = 0x0,
|
||||||
|
.block_size = 0x200,
|
||||||
|
},
|
||||||
|
VOLUME_NAME
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pointer to file system info */
|
||||||
|
static struct efi_file_system_info *file_system_info =
|
||||||
|
&priv_file_system_info.info;
|
||||||
|
|
||||||
|
/* Forward definitions of file and file system functions */
|
||||||
|
static efi_status_t EFIAPI open_volume
|
||||||
|
(struct efi_simple_file_system_protocol *this,
|
||||||
|
struct efi_file_handle **root);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI open
|
||||||
|
(struct efi_file_handle *this,
|
||||||
|
struct efi_file_handle **new_handle,
|
||||||
|
u16 *file_name, u64 open_mode, u64 attributes);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI close(struct efi_file_handle *this);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI delete(struct efi_file_handle *this);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI read
|
||||||
|
(struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI write
|
||||||
|
(struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI getinfo
|
||||||
|
(struct efi_file_handle *this, const efi_guid_t *info_type,
|
||||||
|
efi_uintn_t *buffer_size, void *buffer);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI setinfo
|
||||||
|
(struct efi_file_handle *this, const efi_guid_t *info_type,
|
||||||
|
efi_uintn_t buffer_size, void *buffer);
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI flush(struct efi_file_handle *this);
|
||||||
|
|
||||||
|
/* Internal information about status of file system */
|
||||||
|
static struct {
|
||||||
|
/* Difference of volume open count minus volume close count */
|
||||||
|
int volume_open_count;
|
||||||
|
/* Difference of file open count minus file close count */
|
||||||
|
int file_open_count;
|
||||||
|
/* File size */
|
||||||
|
u64 file_size;
|
||||||
|
/* Current position in file */
|
||||||
|
u64 file_pos;
|
||||||
|
} priv;
|
||||||
|
|
||||||
|
/* EFI_FILE_PROTOCOL for file */
|
||||||
|
static struct efi_file_handle file = {
|
||||||
|
.rev = 0x00010000,
|
||||||
|
.open = open,
|
||||||
|
.close = close,
|
||||||
|
.delete = delete,
|
||||||
|
.read = read,
|
||||||
|
.write = write,
|
||||||
|
.getpos = getpos,
|
||||||
|
.setpos = setpos,
|
||||||
|
.getinfo = getinfo,
|
||||||
|
.setinfo = setinfo,
|
||||||
|
.flush = flush,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* EFI_FILE_PROTOCOL for root directory */
|
||||||
|
static struct efi_file_handle volume = {
|
||||||
|
.rev = 0x00010000,
|
||||||
|
.open = open,
|
||||||
|
.close = close,
|
||||||
|
.delete = delete,
|
||||||
|
.read = read,
|
||||||
|
.write = write,
|
||||||
|
.getpos = getpos,
|
||||||
|
.setpos = setpos,
|
||||||
|
.getinfo = getinfo,
|
||||||
|
.setinfo = setinfo,
|
||||||
|
.flush = flush,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* EFI_SIMPLE_FILE_SYSTEM_PROTOCOL of the block device */
|
||||||
|
struct efi_simple_file_system_protocol file_system = {
|
||||||
|
.rev = 0x00010000,
|
||||||
|
.open_volume = open_volume,
|
||||||
|
};
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI open_volume
|
||||||
|
(struct efi_simple_file_system_protocol *this,
|
||||||
|
struct efi_file_handle **root)
|
||||||
|
{
|
||||||
|
if (this != &file_system || !root)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
*root = &volume;
|
||||||
|
priv.volume_open_count++;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI open
|
||||||
|
(struct efi_file_handle *this,
|
||||||
|
struct efi_file_handle **new_handle,
|
||||||
|
u16 *file_name, u64 open_mode, u64 attributes)
|
||||||
|
{
|
||||||
|
if (this != &volume)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
*new_handle = &file;
|
||||||
|
priv.file_pos = 0;
|
||||||
|
priv.file_open_count++;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI close(struct efi_file_handle *this)
|
||||||
|
{
|
||||||
|
if (this == &file)
|
||||||
|
priv.file_open_count--;
|
||||||
|
else if (this == &volume)
|
||||||
|
priv.volume_open_count--;
|
||||||
|
else
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI delete(struct efi_file_handle *this)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI read
|
||||||
|
(struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (priv.file_pos >= img.length)
|
||||||
|
*buffer_size = 0;
|
||||||
|
else if (priv.file_pos + *buffer_size > img.length)
|
||||||
|
*buffer_size = img.length - priv.file_pos;
|
||||||
|
|
||||||
|
boottime->copy_mem(buffer, &image[priv.file_pos], *buffer_size);
|
||||||
|
priv.file_pos += *buffer_size;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI write
|
||||||
|
(struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
*pos = priv.file_pos;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
priv.file_pos = pos;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI getinfo
|
||||||
|
(struct efi_file_handle *this, const efi_guid_t *info_type,
|
||||||
|
efi_uintn_t *buffer_size, void *buffer)
|
||||||
|
{
|
||||||
|
if (this == &file) {
|
||||||
|
if (efi_st_memcmp(info_type, &guid_file_info,
|
||||||
|
sizeof(efi_guid_t)))
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
if (*buffer_size >= sizeof(struct file_info)) {
|
||||||
|
boottime->copy_mem(buffer, file_info,
|
||||||
|
sizeof(struct file_info));
|
||||||
|
} else {
|
||||||
|
*buffer_size = sizeof(struct file_info);
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
} else if (this == &volume) {
|
||||||
|
if (efi_st_memcmp(info_type, &guid_file_system_info,
|
||||||
|
sizeof(efi_guid_t)))
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
if (*buffer_size >= sizeof(struct file_system_info)) {
|
||||||
|
boottime->copy_mem(buffer, file_system_info,
|
||||||
|
sizeof(struct file_system_info));
|
||||||
|
} else {
|
||||||
|
*buffer_size = sizeof(struct file_system_info);
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI setinfo
|
||||||
|
(struct efi_file_handle *this, const efi_guid_t *info_type,
|
||||||
|
efi_uintn_t buffer_size, void *buffer)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t EFIAPI flush(struct efi_file_handle *this)
|
||||||
|
{
|
||||||
|
if (this != &file)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompress the disk image.
|
||||||
|
*
|
||||||
|
* @image decompressed disk image
|
||||||
|
* @return status code
|
||||||
|
*/
|
||||||
|
static efi_status_t decompress(u8 **image)
|
||||||
|
{
|
||||||
|
u8 *buf;
|
||||||
|
size_t i;
|
||||||
|
size_t addr;
|
||||||
|
size_t len;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
|
||||||
|
(void **)&buf);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("Out of memory\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
boottime->set_mem(buf, img.length, 0);
|
||||||
|
|
||||||
|
for (i = 0; ; ++i) {
|
||||||
|
if (!img.lines[i].line)
|
||||||
|
break;
|
||||||
|
addr = img.lines[i].addr;
|
||||||
|
len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
|
||||||
|
if (addr + len > img.length)
|
||||||
|
len = img.length - addr;
|
||||||
|
boottime->copy_mem(buf + addr, img.lines[i].line, len);
|
||||||
|
}
|
||||||
|
*image = buf;
|
||||||
|
priv.file_size = img.length;
|
||||||
|
file_info->file_size = img.length;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup unit test.
|
||||||
|
*
|
||||||
|
* Decompress application image and provide a handle for the in memory block
|
||||||
|
* device.
|
||||||
|
*
|
||||||
|
* @handle: handle of the loaded image
|
||||||
|
* @systable: system table
|
||||||
|
* @return: EFI_ST_SUCCESS for success
|
||||||
|
*/
|
||||||
|
static int setup(const efi_handle_t handle,
|
||||||
|
const struct efi_system_table *systable)
|
||||||
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
handle_image = handle;
|
||||||
|
boottime = systable->boottime;
|
||||||
|
|
||||||
|
/* Load the application image into memory */
|
||||||
|
decompress(&image);
|
||||||
|
|
||||||
|
ret = boottime->install_protocol_interface
|
||||||
|
(&handle_volume, &guid_device_path, EFI_NATIVE_INTERFACE,
|
||||||
|
&dp_volume);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("Failed to install device path\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
ret = boottime->install_protocol_interface
|
||||||
|
(&handle_volume, &guid_simple_file_system_protocol,
|
||||||
|
EFI_NATIVE_INTERFACE, &file_system);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("Failed to install simple file system protocol\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_ST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tear down unit test.
|
||||||
|
*
|
||||||
|
* Uninstall protocols and free memory.
|
||||||
|
*
|
||||||
|
* @return: EFI_ST_SUCCESS for success
|
||||||
|
*/
|
||||||
|
static int teardown(void)
|
||||||
|
{
|
||||||
|
efi_status_t ret = EFI_ST_SUCCESS;
|
||||||
|
|
||||||
|
if (handle_volume) {
|
||||||
|
ret = boottime->uninstall_protocol_interface
|
||||||
|
(handle_volume, &guid_simple_file_system_protocol,
|
||||||
|
&file_system);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error
|
||||||
|
("Failed to uninstall simple file system protocol\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
ret = boottime->uninstall_protocol_interface
|
||||||
|
(handle_volume, &guid_device_path, &dp_volume);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error
|
||||||
|
("Failed to uninstall device path protocol\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
ret = boottime->free_pool(image);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("Failed to free image\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute unit test.
|
||||||
|
*
|
||||||
|
* Load and start the application image.
|
||||||
|
*
|
||||||
|
* @return: EFI_ST_SUCCESS for success
|
||||||
|
*/
|
||||||
|
static int execute(void)
|
||||||
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
efi_handle_t handle;
|
||||||
|
|
||||||
|
ret = boottime->load_image(false, handle_image, &dp_file.vendor.dp,
|
||||||
|
NULL, 0, &handle);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
efi_st_error("Failed to load image\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
ret = boottime->start_image(handle, NULL, NULL);
|
||||||
|
if (ret != EFI_UNSUPPORTED) {
|
||||||
|
efi_st_error("Wrong return value from application\n");
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv.file_open_count) {
|
||||||
|
efi_st_error("File open count = %d, expected 0\n",
|
||||||
|
priv.file_open_count);
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
if (priv.volume_open_count) {
|
||||||
|
efi_st_error("Volume open count = %d, expected 0\n",
|
||||||
|
priv.volume_open_count);
|
||||||
|
return EFI_ST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_ST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_UNIT_TEST(loadimage) = {
|
||||||
|
.name = "load image from file",
|
||||||
|
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||||
|
.setup = setup,
|
||||||
|
.execute = execute,
|
||||||
|
.teardown = teardown,
|
||||||
|
};
|
|
@ -103,7 +103,7 @@ static int teardown(void)
|
||||||
efi_status_t r = EFI_ST_SUCCESS;
|
efi_status_t r = EFI_ST_SUCCESS;
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
r = efi_free_pool(image);
|
r = boottime->free_pool(image);
|
||||||
if (r != EFI_SUCCESS) {
|
if (r != EFI_SUCCESS) {
|
||||||
efi_st_error("Failed to free image\n");
|
efi_st_error("Failed to free image\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
|
|
|
@ -103,7 +103,7 @@ static int teardown(void)
|
||||||
efi_status_t r = EFI_ST_SUCCESS;
|
efi_status_t r = EFI_ST_SUCCESS;
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
r = efi_free_pool(image);
|
r = boottime->free_pool(image);
|
||||||
if (r != EFI_SUCCESS) {
|
if (r != EFI_SUCCESS) {
|
||||||
efi_st_error("Failed to free image\n");
|
efi_st_error("Failed to free image\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
|
|
|
@ -288,6 +288,8 @@ static char *string16(char *buf, char *end, u16 *s, int field_width,
|
||||||
for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) {
|
for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) {
|
||||||
s32 s = utf16_get(&str);
|
s32 s = utf16_get(&str);
|
||||||
|
|
||||||
|
if (s < 0)
|
||||||
|
s = '?';
|
||||||
utf8_put(s, &buf);
|
utf8_put(s, &buf);
|
||||||
}
|
}
|
||||||
for (; len < field_width; --field_width)
|
for (; len < field_width; --field_width)
|
||||||
|
|
|
@ -50,7 +50,7 @@ static const char j1[] = {0x6a, 0x31, 0xa1, 0x6c, 0x00};
|
||||||
static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00};
|
static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00};
|
||||||
static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00};
|
static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00};
|
||||||
|
|
||||||
static int ut_u16_strdup(struct unit_test_state *uts)
|
static int unicode_test_u16_strdup(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
u16 *copy = u16_strdup(c4);
|
u16 *copy = u16_strdup(c4);
|
||||||
|
|
||||||
|
@ -59,9 +59,9 @@ static int ut_u16_strdup(struct unit_test_state *uts)
|
||||||
free(copy);
|
free(copy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_u16_strdup);
|
UNICODE_TEST(unicode_test_u16_strdup);
|
||||||
|
|
||||||
static int ut_u16_strcpy(struct unit_test_state *uts)
|
static int unicode_test_u16_strcpy(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
u16 *r;
|
u16 *r;
|
||||||
u16 copy[10];
|
u16 copy[10];
|
||||||
|
@ -71,11 +71,11 @@ static int ut_u16_strcpy(struct unit_test_state *uts)
|
||||||
ut_assert(!memcmp(copy, c1, sizeof(c1)));
|
ut_assert(!memcmp(copy, c1, sizeof(c1)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_u16_strcpy);
|
UNICODE_TEST(unicode_test_u16_strcpy);
|
||||||
|
|
||||||
/* U-Boot uses UTF-16 strings in the EFI context only. */
|
/* U-Boot uses UTF-16 strings in the EFI context only. */
|
||||||
#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
|
#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
|
||||||
static int ut_string16(struct unit_test_state *uts)
|
static int unicode_test_string16(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
|
@ -113,10 +113,10 @@ static int ut_string16(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_string16);
|
UNICODE_TEST(unicode_test_string16);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ut_utf8_get(struct unit_test_state *uts)
|
static int unicode_test_utf8_get(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
s32 code;
|
s32 code;
|
||||||
|
@ -152,9 +152,9 @@ static int ut_utf8_get(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_get);
|
UNICODE_TEST(unicode_test_utf8_get);
|
||||||
|
|
||||||
static int ut_utf8_put(struct unit_test_state *uts)
|
static int unicode_test_utf8_put(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
char buffer[8] = { 0, };
|
char buffer[8] = { 0, };
|
||||||
char *pos;
|
char *pos;
|
||||||
|
@ -190,9 +190,9 @@ static int ut_utf8_put(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_put);
|
UNICODE_TEST(unicode_test_utf8_put);
|
||||||
|
|
||||||
static int ut_utf8_utf16_strlen(struct unit_test_state *uts)
|
static int unicode_test_utf8_utf16_strlen(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq(6, utf8_utf16_strlen(d1));
|
ut_asserteq(6, utf8_utf16_strlen(d1));
|
||||||
ut_asserteq(8, utf8_utf16_strlen(d2));
|
ut_asserteq(8, utf8_utf16_strlen(d2));
|
||||||
|
@ -206,9 +206,9 @@ static int ut_utf8_utf16_strlen(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_utf16_strlen);
|
UNICODE_TEST(unicode_test_utf8_utf16_strlen);
|
||||||
|
|
||||||
static int ut_utf8_utf16_strnlen(struct unit_test_state *uts)
|
static int unicode_test_utf8_utf16_strnlen(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq(3, utf8_utf16_strnlen(d1, 3));
|
ut_asserteq(3, utf8_utf16_strnlen(d1, 3));
|
||||||
ut_asserteq(6, utf8_utf16_strnlen(d1, 13));
|
ut_asserteq(6, utf8_utf16_strnlen(d1, 13));
|
||||||
|
@ -224,7 +224,7 @@ static int ut_utf8_utf16_strnlen(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_utf16_strnlen);
|
UNICODE_TEST(unicode_test_utf8_utf16_strnlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ut_u16_strcmp() - Compare to u16 strings.
|
* ut_u16_strcmp() - Compare to u16 strings.
|
||||||
|
@ -234,7 +234,7 @@ UNICODE_TEST(ut_utf8_utf16_strnlen);
|
||||||
* @count: number of u16 to compare
|
* @count: number of u16 to compare
|
||||||
* Return: -1 if a1 < a2, 0 if a1 == a2, 1 if a1 > a2
|
* Return: -1 if a1 < a2, 0 if a1 == a2, 1 if a1 > a2
|
||||||
*/
|
*/
|
||||||
static int ut_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
|
static int unicode_test_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
|
||||||
{
|
{
|
||||||
for (; (*a1 || *a2) && count; ++a1, ++a2, --count) {
|
for (; (*a1 || *a2) && count; ++a1, ++a2, --count) {
|
||||||
if (*a1 < *a2)
|
if (*a1 < *a2)
|
||||||
|
@ -245,7 +245,7 @@ static int ut_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ut_utf8_utf16_strcpy(struct unit_test_state *uts)
|
static int unicode_test_utf8_utf16_strcpy(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
u16 buf[16];
|
u16 buf[16];
|
||||||
u16 *pos;
|
u16 *pos;
|
||||||
|
@ -253,44 +253,44 @@ static int ut_utf8_utf16_strcpy(struct unit_test_state *uts)
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, d1);
|
utf8_utf16_strcpy(&pos, d1);
|
||||||
ut_asserteq(6, pos - buf);
|
ut_asserteq(6, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c1, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c1, SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, d2);
|
utf8_utf16_strcpy(&pos, d2);
|
||||||
ut_asserteq(8, pos - buf);
|
ut_asserteq(8, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, d3);
|
utf8_utf16_strcpy(&pos, d3);
|
||||||
ut_asserteq(3, pos - buf);
|
ut_asserteq(3, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c3, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c3, SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, d4);
|
utf8_utf16_strcpy(&pos, d4);
|
||||||
ut_asserteq(6, pos - buf);
|
ut_asserteq(6, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
|
||||||
|
|
||||||
/* Illegal utf-8 strings */
|
/* Illegal utf-8 strings */
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, j1);
|
utf8_utf16_strcpy(&pos, j1);
|
||||||
ut_asserteq(4, pos - buf);
|
ut_asserteq(4, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, L"j1?l", SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, L"j1?l", SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, j2);
|
utf8_utf16_strcpy(&pos, j2);
|
||||||
ut_asserteq(4, pos - buf);
|
ut_asserteq(4, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, L"j2?l", SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, L"j2?l", SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
utf8_utf16_strcpy(&pos, j3);
|
utf8_utf16_strcpy(&pos, j3);
|
||||||
ut_asserteq(3, pos - buf);
|
ut_asserteq(3, pos - buf);
|
||||||
ut_assert(!ut_u16_strcmp(buf, L"j3?", SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, L"j3?", SIZE_MAX));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_utf16_strcpy);
|
UNICODE_TEST(unicode_test_utf8_utf16_strcpy);
|
||||||
|
|
||||||
int ut_utf8_utf16_strncpy(struct unit_test_state *uts)
|
static int unicode_test_utf8_utf16_strncpy(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
u16 buf[16];
|
u16 buf[16];
|
||||||
u16 *pos;
|
u16 *pos;
|
||||||
|
@ -300,41 +300,41 @@ int ut_utf8_utf16_strncpy(struct unit_test_state *uts)
|
||||||
utf8_utf16_strncpy(&pos, d1, 4);
|
utf8_utf16_strncpy(&pos, d1, 4);
|
||||||
ut_asserteq(4, pos - buf);
|
ut_asserteq(4, pos - buf);
|
||||||
ut_assert(!buf[4]);
|
ut_assert(!buf[4]);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c1, 4));
|
ut_assert(!unicode_test_u16_strcmp(buf, c1, 4));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
utf8_utf16_strncpy(&pos, d2, 10);
|
utf8_utf16_strncpy(&pos, d2, 10);
|
||||||
ut_asserteq(8, pos - buf);
|
ut_asserteq(8, pos - buf);
|
||||||
ut_assert(buf[4]);
|
ut_assert(buf[4]);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
utf8_utf16_strncpy(&pos, d3, 2);
|
utf8_utf16_strncpy(&pos, d3, 2);
|
||||||
ut_asserteq(2, pos - buf);
|
ut_asserteq(2, pos - buf);
|
||||||
ut_assert(!buf[2]);
|
ut_assert(!buf[2]);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c3, 2));
|
ut_assert(!unicode_test_u16_strcmp(buf, c3, 2));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
utf8_utf16_strncpy(&pos, d4, 2);
|
utf8_utf16_strncpy(&pos, d4, 2);
|
||||||
ut_asserteq(4, pos - buf);
|
ut_asserteq(4, pos - buf);
|
||||||
ut_assert(!buf[4]);
|
ut_assert(!buf[4]);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c4, 4));
|
ut_assert(!unicode_test_u16_strcmp(buf, c4, 4));
|
||||||
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
utf8_utf16_strncpy(&pos, d4, 10);
|
utf8_utf16_strncpy(&pos, d4, 10);
|
||||||
ut_asserteq(6, pos - buf);
|
ut_asserteq(6, pos - buf);
|
||||||
ut_assert(buf[5]);
|
ut_assert(buf[5]);
|
||||||
ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
|
ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf8_utf16_strncpy);
|
UNICODE_TEST(unicode_test_utf8_utf16_strncpy);
|
||||||
|
|
||||||
static int ut_utf16_get(struct unit_test_state *uts)
|
static int unicode_test_utf16_get(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
const u16 *s;
|
const u16 *s;
|
||||||
s32 code;
|
s32 code;
|
||||||
|
@ -358,9 +358,9 @@ static int ut_utf16_get(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_get);
|
UNICODE_TEST(unicode_test_utf16_get);
|
||||||
|
|
||||||
static int ut_utf16_put(struct unit_test_state *uts)
|
static int unicode_test_utf16_put(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
u16 buffer[4] = { 0, };
|
u16 buffer[4] = { 0, };
|
||||||
u16 *pos;
|
u16 *pos;
|
||||||
|
@ -386,9 +386,9 @@ static int ut_utf16_put(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_put);
|
UNICODE_TEST(unicode_test_utf16_put);
|
||||||
|
|
||||||
int ut_utf16_strnlen(struct unit_test_state *uts)
|
static int unicode_test_utf16_strnlen(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq(3, utf16_strnlen(c1, 3));
|
ut_asserteq(3, utf16_strnlen(c1, 3));
|
||||||
ut_asserteq(6, utf16_strnlen(c1, 13));
|
ut_asserteq(6, utf16_strnlen(c1, 13));
|
||||||
|
@ -404,9 +404,9 @@ int ut_utf16_strnlen(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_strnlen);
|
UNICODE_TEST(unicode_test_utf16_strnlen);
|
||||||
|
|
||||||
int ut_utf16_utf8_strlen(struct unit_test_state *uts)
|
static int unicode_test_utf16_utf8_strlen(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq(6, utf16_utf8_strlen(c1));
|
ut_asserteq(6, utf16_utf8_strlen(c1));
|
||||||
ut_asserteq(9, utf16_utf8_strlen(c2));
|
ut_asserteq(9, utf16_utf8_strlen(c2));
|
||||||
|
@ -420,9 +420,9 @@ int ut_utf16_utf8_strlen(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_utf8_strlen);
|
UNICODE_TEST(unicode_test_utf16_utf8_strlen);
|
||||||
|
|
||||||
int ut_utf16_utf8_strnlen(struct unit_test_state *uts)
|
static int unicode_test_utf16_utf8_strnlen(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq(3, utf16_utf8_strnlen(c1, 3));
|
ut_asserteq(3, utf16_utf8_strnlen(c1, 3));
|
||||||
ut_asserteq(6, utf16_utf8_strnlen(c1, 13));
|
ut_asserteq(6, utf16_utf8_strnlen(c1, 13));
|
||||||
|
@ -432,9 +432,9 @@ int ut_utf16_utf8_strnlen(struct unit_test_state *uts)
|
||||||
ut_asserteq(12, utf16_utf8_strnlen(c4, 3));
|
ut_asserteq(12, utf16_utf8_strnlen(c4, 3));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_utf8_strnlen);
|
UNICODE_TEST(unicode_test_utf16_utf8_strnlen);
|
||||||
|
|
||||||
int ut_utf16_utf8_strcpy(struct unit_test_state *uts)
|
static int unicode_test_utf16_utf8_strcpy(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
char *pos;
|
char *pos;
|
||||||
|
@ -477,9 +477,9 @@ int ut_utf16_utf8_strcpy(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_utf8_strcpy);
|
UNICODE_TEST(unicode_test_utf16_utf8_strcpy);
|
||||||
|
|
||||||
int ut_utf16_utf8_strncpy(struct unit_test_state *uts)
|
static int unicode_test_utf16_utf8_strncpy(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
char *pos;
|
char *pos;
|
||||||
|
@ -521,9 +521,9 @@ int ut_utf16_utf8_strncpy(struct unit_test_state *uts)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf16_utf8_strncpy);
|
UNICODE_TEST(unicode_test_utf16_utf8_strncpy);
|
||||||
|
|
||||||
int ut_utf_to_lower(struct unit_test_state *uts)
|
static int unicode_test_utf_to_lower(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq('@', utf_to_lower('@'));
|
ut_asserteq('@', utf_to_lower('@'));
|
||||||
ut_asserteq('a', utf_to_lower('A'));
|
ut_asserteq('a', utf_to_lower('A'));
|
||||||
|
@ -538,9 +538,9 @@ int ut_utf_to_lower(struct unit_test_state *uts)
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf_to_lower);
|
UNICODE_TEST(unicode_test_utf_to_lower);
|
||||||
|
|
||||||
int ut_utf_to_upper(struct unit_test_state *uts)
|
static int unicode_test_utf_to_upper(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
ut_asserteq('`', utf_to_upper('`'));
|
ut_asserteq('`', utf_to_upper('`'));
|
||||||
ut_asserteq('A', utf_to_upper('a'));
|
ut_asserteq('A', utf_to_upper('a'));
|
||||||
|
@ -555,7 +555,7 @@ int ut_utf_to_upper(struct unit_test_state *uts)
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UNICODE_TEST(ut_utf_to_upper);
|
UNICODE_TEST(unicode_test_utf_to_upper);
|
||||||
|
|
||||||
int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue