diff options
| author | Peter Jones <pjones@redhat.com> | 2021-07-22 16:23:49 -0400 |
|---|---|---|
| committer | Peter Jones <pjones@redhat.com> | 2021-09-07 17:05:04 -0400 |
| commit | 3386d4f5b7cf63fba4b1ba9b1c2878617b141b23 (patch) | |
| tree | 55f3fbf529003c0241c04826457390d4cfa90247 | |
| parent | 54bc72cf0abd306d96782cdfa6db7c71ff72e056 (diff) | |
| download | efi-boot-shim-3386d4f5b7cf63fba4b1ba9b1c2878617b141b23.tar.gz efi-boot-shim-3386d4f5b7cf63fba4b1ba9b1c2878617b141b23.zip | |
tests: add pre and post hooks to the mock variable store
For testing of the mok mirroring behavior, we have to be able to account
for what variable calls happened and in what order.
In order to support that, this patch adds 8 callbacks:
mock_set_variable_pre_hook()
mock_set_variable_post_hook()
mock_get_variable_pre_hook()
mock_get_variable_post_hook()
mock_get_next_variable_name_pre_hook()
mock_get_next_variable_name_post_hook()
mock_query_variable_info_pre_hook()
mock_query_variable_info_post_hook()
The pre hooks each take the same arguments as their mocked namesake, and
they fire before any input validation. The post hooks take an
additional EFI_STATUS argument. The post hook fires immediately before
any return from the mocked namesake function. For SetVariable(), the
arguments when the post hook fires are the current contents of the
variable if status is EFI_SUCCESS, and whatever arguments were passed in
if status is any other value. For everything else, the arguments are
the correct results on EFI_SUCCESS, and whatever was passed in if status
is any other value.
Signed-off-by: Peter Jones <pjones@redhat.com>
| -rw-r--r-- | mock-variables.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/mock-variables.c b/mock-variables.c index e02febec..6a9a9dea 100644 --- a/mock-variables.c +++ b/mock-variables.c @@ -29,6 +29,116 @@ mock_sort_policy_t mock_variable_sort_policy = MOCK_SORT_APPEND; UINT32 mock_variable_delete_attr_policy; +mock_set_variable_pre_hook_t *mock_set_variable_pre_hook = NULL; +mock_set_variable_post_hook_t *mock_set_variable_post_hook = NULL; +mock_get_variable_pre_hook_t *mock_get_variable_pre_hook = NULL; +mock_get_variable_post_hook_t *mock_get_variable_post_hook = NULL; +mock_get_next_variable_name_pre_hook_t *mock_get_next_variable_name_pre_hook = NULL; +mock_get_next_variable_name_post_hook_t *mock_get_next_variable_name_post_hook = NULL; +mock_query_variable_info_pre_hook_t *mock_query_variable_info_pre_hook = NULL; +mock_query_variable_info_post_hook_t *mock_query_variable_info_post_hook = NULL; + +static EFI_STATUS +mock_sv_pre_hook(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, + VOID *data) +{ + EFI_STATUS status = EFI_SUCCESS; + if (mock_set_variable_pre_hook) + status = mock_set_variable_pre_hook(name, guid, + attrs, size, data); + return status; +} + +static void +mock_sv_post_hook_(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, + VOID *data, EFI_STATUS *status, mock_variable_op_t op, + const char * const file, const int line, + const char * const func) +{ + if (mock_set_variable_post_hook) + mock_set_variable_post_hook(name, guid, attrs, size, + data, status, op, file, line, func); +} +#define mock_sv_post_hook(name, guid, attrs, size, data, status, op) \ + mock_sv_post_hook_(name, guid, attrs, size, data, status, op,\ + __FILE__, __LINE__, __func__) + +static EFI_STATUS +mock_gv_pre_hook(CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, + VOID *data) +{ + EFI_STATUS status = EFI_SUCCESS; + if (mock_get_variable_pre_hook) + status = mock_get_variable_pre_hook(name, guid, + attrs, size, data); + return status; +} + +static void +mock_gv_post_hook_(CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, + VOID *data, EFI_STATUS *status, const char * const file, + const int line, const char * const func) +{ + if (mock_get_variable_post_hook) + mock_get_variable_post_hook(name, guid, attrs, size, data, + status, file, line, func); +} +#define mock_gv_post_hook(name, guid, attrs, size, data, status) \ + mock_gv_post_hook_(name, guid, attrs, size, data, status,\ + __FILE__, __LINE__, __func__) + +static EFI_STATUS +mock_gnvn_pre_hook(UINTN *size, CHAR16 *name, EFI_GUID *guid) +{ + EFI_STATUS status = EFI_SUCCESS; + if (mock_get_next_variable_name_pre_hook) + status = mock_get_next_variable_name_pre_hook(size, name, guid); + return status; +} + +static void +mock_gnvn_post_hook_(UINTN *size, CHAR16 *name, EFI_GUID *guid, + EFI_STATUS *status, const char * const file, + const int line, const char * const func) +{ + if (mock_get_next_variable_name_post_hook) + mock_get_next_variable_name_post_hook(size, name, guid, status, + file, line, func); +} +#define mock_gnvn_post_hook(size, name, guid, status) \ + mock_gnvn_post_hook_(size, name, guid, status,\ + __FILE__, __LINE__, __func__) + +static EFI_STATUS +mock_qvi_pre_hook(UINT32 attrs, UINT64 *max_var_storage, + UINT64 *remaining_var_storage, UINT64 *max_var_size) +{ + EFI_STATUS status = EFI_SUCCESS; + if (mock_query_variable_info_pre_hook) + status = mock_query_variable_info_pre_hook( + attrs, max_var_storage, + remaining_var_storage, max_var_size); + return status; +} + +static void +mock_qvi_post_hook_(UINT32 attrs, UINT64 *max_var_storage, + UINT64 *remaining_var_storage, UINT64 *max_var_size, + EFI_STATUS *status, const char * const file, + const int line, const char * const func) +{ + if (mock_query_variable_info_post_hook) + mock_query_variable_info_post_hook(attrs, max_var_storage, + remaining_var_storage, + max_var_size, status, + file, line, func); +} +#define mock_qvi_post_hook(attrs, max_var_storage, remaining_var_storage,\ + max_var_size, status) \ + mock_qvi_post_hook_(attrs, max_var_storage, remaining_var_storage,\ + max_var_size, status, \ + __FILE__, __LINE__, __func__) + static const size_t guidstr_size = sizeof("8be4df61-93ca-11d2-aa0d-00e098032b8c"); static int @@ -113,8 +223,13 @@ mock_get_variable(CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, struct mock_variable *result = NULL; EFI_STATUS status; + status = mock_gv_pre_hook(name, guid, attrs, size, data); + if (EFI_ERROR(status)) + return status; + if (name == NULL || guid == NULL || size == NULL) { status = EFI_INVALID_PARAMETER; + mock_gv_post_hook(name, guid, attrs, size, data, &status); return status; } @@ -134,20 +249,27 @@ mock_get_variable(CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, if (var->size > *size) { *size = var->size; status = EFI_BUFFER_TOO_SMALL; + mock_gv_post_hook(name, guid, attrs, size, data, + &status); return status; } if (data == NULL) { status = EFI_INVALID_PARAMETER; + mock_gv_post_hook(name, guid, attrs, size, data, + &status); return status; } *size = var->size; memcpy(data, var->data, var->size); status = EFI_SUCCESS; + mock_gv_post_hook(name, guid, attrs, size, data, + &status); return status; } } status = EFI_NOT_FOUND; + mock_gv_post_hook(name, guid, attrs, size, data, &status); return status; } @@ -160,6 +282,7 @@ mock_gnvn_set_result(UINTN *size, CHAR16 *name, EFI_GUID *guid, if (*size < StrSize(result->name)) { *size = StrSize(result->name); status = EFI_BUFFER_TOO_SMALL; + mock_gnvn_post_hook(size, name, guid, &status); #if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0) printf("%s:%d:%s(): returning %lx\n", __FILE__, __LINE__-1, __func__, status); @@ -172,6 +295,7 @@ mock_gnvn_set_result(UINTN *size, CHAR16 *name, EFI_GUID *guid, memcpy(guid, &result->guid, sizeof(EFI_GUID)); status = EFI_SUCCESS; + mock_gnvn_post_hook(size, name, guid, &status); #if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0) printf("%s:%d:%s(): returning %lx\n", __FILE__, __LINE__-1, __func__, status); @@ -191,8 +315,13 @@ mock_get_next_variable_name(UINTN *size, CHAR16 *name, EFI_GUID *guid) bool found = false; EFI_STATUS status; + status = mock_gnvn_pre_hook(size, name, guid); + if (EFI_ERROR(status)) + return status; + if (size == NULL || name == NULL || guid == NULL) { status = EFI_INVALID_PARAMETER; + mock_gnvn_post_hook(size, name, guid, &status); return status; } @@ -205,6 +334,7 @@ mock_get_next_variable_name(UINTN *size, CHAR16 *name, EFI_GUID *guid) if (found == false) { status = EFI_INVALID_PARAMETER; + mock_gnvn_post_hook(size, name, guid, &status); return status; } @@ -277,11 +407,13 @@ mock_get_next_variable_name(UINTN *size, CHAR16 *name, EFI_GUID *guid) status = EFI_NOT_FOUND; else status = EFI_INVALID_PARAMETER; + mock_gnvn_post_hook(size, name, guid, &status); return status; } if (!result) { status = EFI_NOT_FOUND; + mock_gnvn_post_hook(size, name, guid, &status); return status; } @@ -409,10 +541,14 @@ mock_delete_variable(struct mock_variable *var) if (EFI_ERROR(status)) { printf("%s:%d:%s(): status:0x%lx\n", __FILE__, __LINE__ - 1, __func__, status); + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, DELETE); return status; } status = EFI_SUCCESS; + mock_sv_post_hook(var->name, &var->guid, var->attrs, 0, 0, &status, + DELETE); free_var(var); return status; } @@ -426,6 +562,8 @@ mock_replace_variable(struct mock_variable *var, VOID *data, UINTN size) status = mock_sv_adjust_usage_data(var->attrs, size, - var->size + size); if (EFI_ERROR(status)) { + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, REPLACE); return status; } @@ -437,6 +575,8 @@ mock_replace_variable(struct mock_variable *var, VOID *data, UINTN size) size); #endif status = EFI_OUT_OF_RESOURCES; + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, REPLACE); return status; } memcpy(new, data, size); @@ -445,6 +585,8 @@ mock_replace_variable(struct mock_variable *var, VOID *data, UINTN size) var->size = size; status = EFI_SUCCESS; + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, REPLACE); return status; } @@ -456,11 +598,15 @@ mock_sv_extend(struct mock_variable *var, VOID *data, UINTN size) if (size == 0) { status = EFI_SUCCESS; + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, APPEND); return status; } status = mock_sv_adjust_usage_data(var->attrs, var->size + size, size); if (EFI_ERROR(status)) { + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, APPEND); return status; } @@ -472,6 +618,8 @@ mock_sv_extend(struct mock_variable *var, VOID *data, UINTN size) var->size + size); #endif status = EFI_OUT_OF_RESOURCES; + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, APPEND); return status; } @@ -480,6 +628,8 @@ mock_sv_extend(struct mock_variable *var, VOID *data, UINTN size) var->size += size; status = EFI_SUCCESS; + mock_sv_post_hook(var->name, &var->guid, var->attrs, var->size, + var->data, &status, APPEND); return status; } @@ -574,14 +724,22 @@ mock_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, EFI_STATUS status; long cmp = -1; + status = mock_sv_pre_hook(name, guid, attrs, size, data); + if (EFI_ERROR(status)) + return status; + if (!name || name[0] == 0 || !guid) { status = EFI_INVALID_PARAMETER; + mock_sv_post_hook(name, guid, attrs, size, data, &status, + CREATE); return status; } if ((attrs & EFI_VARIABLE_RUNTIME_ACCESS) && !(attrs & EFI_VARIABLE_BOOTSERVICE_ACCESS)) { status = EFI_INVALID_PARAMETER; + mock_sv_post_hook(name, guid, attrs, size, data, &status, + CREATE); return status; } @@ -592,6 +750,8 @@ mock_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, */ if (has_exited_boot_services() && !(attrs & EFI_VARIABLE_RUNTIME_ACCESS)) { status = EFI_INVALID_PARAMETER; + mock_sv_post_hook(name, guid, attrs, size, data, &status, + CREATE); return status; } #endif @@ -605,6 +765,8 @@ mock_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS)) { status = EFI_UNSUPPORTED; + mock_sv_post_hook(name, guid, attrs, size, data, &status, + CREATE); return status; } #endif @@ -682,9 +844,13 @@ mock_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, #endif status = mock_new_variable(name, guid, attrs, size, data, &var); if (EFI_ERROR(status)) { + mock_sv_post_hook(name, guid, attrs, size, data, + &status, CREATE); return status; } mock_sv_adjust_usage_data(attrs, size, totalsz); + mock_sv_post_hook(name, guid, attrs, size, data, + &status, CREATE); if (EFI_ERROR(status)) { mock_sv_adjust_usage_data(attrs, 0, -totalsz); return status; @@ -725,6 +891,8 @@ mock_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, __FILE__, __LINE__ - 1, __func__, format_var_attrs(var->attrs), format_var_attrs(attrs)); + mock_sv_post_hook(name, guid, attrs, size, data, + &status, REPLACE); return status; } } @@ -760,10 +928,18 @@ mock_query_variable_info(UINT32 attrs, UINT64 *max_var_storage, struct mock_variable_limits *limits = NULL; EFI_STATUS status; + status = mock_qvi_pre_hook(attrs, max_var_storage, + remaining_var_storage, max_var_size); + if (EFI_ERROR(status)) + return status; + if (max_var_storage == NULL || remaining_var_storage == NULL || max_var_size == NULL) { status = EFI_INVALID_PARAMETER; + mock_qvi_post_hook(attrs, max_var_storage, + remaining_var_storage, max_var_size, + &status); return status; } @@ -773,12 +949,18 @@ mock_query_variable_info(UINT32 attrs, UINT64 *max_var_storage, *max_var_storage = *limits->max_var_storage; *remaining_var_storage = *limits->remaining_var_storage; *max_var_size = *limits->max_var_size; + status = EFI_SUCCESS; + mock_qvi_post_hook(attrs, max_var_storage, + remaining_var_storage, max_var_size, + &status); return status; } } status = EFI_UNSUPPORTED; + mock_qvi_post_hook(attrs, max_var_storage, remaining_var_storage, + max_var_size, &status); return status; } @@ -991,6 +1173,15 @@ mock_reset_variables(void) init_efi_system_table(); + mock_set_variable_pre_hook = NULL; + mock_set_variable_post_hook = NULL; + mock_get_variable_pre_hook = NULL; + mock_get_variable_post_hook = NULL; + mock_get_next_variable_name_pre_hook = NULL; + mock_get_next_variable_name_post_hook = NULL; + mock_query_variable_info_pre_hook = NULL; + mock_query_variable_info_post_hook = NULL; + if (once) { INIT_LIST_HEAD(&mock_variables); once = false; |
