summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2021-07-22 16:23:49 -0400
committerPeter Jones <pjones@redhat.com>2021-09-07 17:05:04 -0400
commit3386d4f5b7cf63fba4b1ba9b1c2878617b141b23 (patch)
tree55f3fbf529003c0241c04826457390d4cfa90247
parent54bc72cf0abd306d96782cdfa6db7c71ff72e056 (diff)
downloadefi-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.c191
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;