efi-boot-shim/test-mock-variables.c
2025-03-24 10:18:24 +01:00

874 lines
24 KiB
C

// SPDX-License-Identifier: BSD-2-Clause-Patent
/*
* test-mock-variables.c - test our mock variable implementation (irony)
* Copyright Peter Jones <pjones@redhat.com>
*/
#include "shim.h"
#include "mock-variables.h"
#include <errno.h>
#include <efivar/efivar.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "test-data-efivars-0.h"
#pragma GCC diagnostic ignored "-Wunused-label"
static const size_t guidstr_size = sizeof("8be4df61-93ca-11d2-aa0d-00e098032b8c");
void mock_print_guidname(EFI_GUID *guid, CHAR16 *name);
void mock_print_var_list(list_t *head);
static int
test_filter_out_helper(size_t nvars, const CHAR16 *varnames[nvars],
bool filter_out, UINTN expected_count)
{
const char *mok_rt_vars[n_mok_state_variables];
EFI_STATUS status;
EFI_GUID guid = SHIM_LOCK_GUID;
CHAR16 name[1024] = L"";
UINTN sz;
char asciiname[1024];
bool found = false;
int ret = 0;
UINTN count = 0;
for (size_t i = 0; i < n_mok_state_variables; i++) {
mok_rt_vars[i] = mok_state_variables[i].rtname8;
}
sz = sizeof(name);
status = RT->GetNextVariableName(&sz, name, &guid);
assert_equal_return(status, EFI_NOT_FOUND, -1, "got %lx, expected %lx");
mock_load_variables("test-data/efivars-1", mok_rt_vars, filter_out);
while (true) {
int rc = 0;
sz = sizeof(name);
status = RT->GetNextVariableName(&sz, name, &guid);
if (status == EFI_NOT_FOUND)
break;
if (EFI_ERROR(status))
return -1;
count += 1;
SetMem(asciiname, sizeof(asciiname), 0);
for (UINTN i = 0; i < sizeof(asciiname); i++)
asciiname[i] = name[i];
for (UINTN i = 0; varnames[i] != NULL; i++) {
if (sz == 0 || StrLen(varnames[i]) != sz-1)
continue;
if (StrCmp(name, varnames[i]) == 0) {
found = true;
if (filter_out) {
rc = assert_false_as_expr(found, -1,
"found=%u for undesired variable \"%s\"\n",
asciiname);
break;
}
}
}
if (!filter_out)
rc = assert_true_as_expr(found, -1,
"found=%u for undesired variable \"%s\"\n",
asciiname);
if (ret >= 0 && rc < 0)
ret = rc;
}
mock_reset_variables();
assert_equal_return(count, expected_count, -1, "%lu != %lu\n");
assert_true_return(list_empty(&mock_variables), -1, "%lu != %lu\n");
return ret;
}
static int
test_filter_out_true(void)
{
const CHAR16 *varnames[] = {
L"MokListRT",
L"MokListXRT",
L"SbatLevelRT",
NULL
};
size_t nvars = sizeof(varnames) / sizeof(varnames[0]);
return test_filter_out_helper(nvars, varnames, true, 3);
}
static int
test_filter_out_false(void)
{
const CHAR16 *varnames[] = {
L"MokListRT",
L"MokListXRT",
L"SbatLevelRT",
NULL
};
size_t nvars = sizeof(varnames) / sizeof(varnames[0]);
return test_filter_out_helper(nvars, varnames, false, 3);
}
static int
test_gnvn_buf_size_0(void)
{
UINTN size = 0;
CHAR16 buf[6] = { 0, };
EFI_STATUS status;
EFI_GUID empty_guid = { 0, };
int ret = -1;
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
assert_equal_return(status, EFI_INVALID_PARAMETER, -1, "0x%lx != 0x%lx\n");
size = 1;
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
assert_equal_return(status, EFI_NOT_FOUND, -1, "0x%lx != 0x%lx\n");
status = RT->SetVariable(L"test", &GV_GUID,
EFI_VARIABLE_BOOTSERVICE_ACCESS, 5, "test");
assert_equal_return(status, EFI_SUCCESS, -1, "0x%lx != 0x%lx\n");
size = 1;
status = RT->GetNextVariableName(&size, &buf[0], &empty_guid);
assert_equal_goto(status, EFI_NOT_FOUND, err, "0x%lx != 0x%lx\n");
size = 1;
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
assert_equal_goto(status, EFI_BUFFER_TOO_SMALL, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, StrSize(L"test"), err, "%zu != %zu\n");
size = StrSize(L"test");
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
status = RT->SetVariable(L"testa", &GV_GUID,
EFI_VARIABLE_BOOTSERVICE_ACCESS, 5, "test");
assert_equal_return(status, EFI_SUCCESS, -1, "0x%lx != 0x%lx\n");
buf[0] = 0;
size = 1;
status = RT->GetNextVariableName(&size, &buf[0], &empty_guid);
assert_equal_goto(status, EFI_NOT_FOUND, err, "0x%lx != 0x%lx\n");
size = StrSize(L"test");
StrCpy(buf, L"test");
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
switch (mock_variable_sort_policy) {
case MOCK_SORT_DESCENDING:
case MOCK_SORT_PREPEND:
assert_equal_goto(status, EFI_NOT_FOUND, err, "0x%lx != 0x%lx\n");
break;
case MOCK_SORT_APPEND:
case MOCK_SORT_ASCENDING:
assert_equal_goto(status, EFI_BUFFER_TOO_SMALL, err, "0x%lx != 0x%lx\n");
break;
default:
break;
}
size = StrSize(L"testa");
StrCpy(buf, L"test");
status = RT->GetNextVariableName(&size, &buf[0], &GV_GUID);
switch (mock_variable_sort_policy) {
case MOCK_SORT_DESCENDING:
case MOCK_SORT_PREPEND:
assert_equal_goto(status, EFI_NOT_FOUND, err, "0x%lx != 0x%lx\n");
break;
case MOCK_SORT_APPEND:
case MOCK_SORT_ASCENDING:
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
break;
default:
break;
}
ret = 0;
err:
mock_reset_variables();
return ret;
}
static int
test_gnvn_helper(char *testvars)
{
UINTN size = 0;
CHAR16 buf[8192] = { 0, };
EFI_STATUS status;
EFI_GUID empty_guid = { 0, };
int ret = -1;
const char *mok_rt_vars[n_mok_state_variables];
for (size_t i = 0; i < n_mok_state_variables; i++) {
/*
* We don't want to filter out the variables we've added to
* mok mirroring that aren't really from mok; right now
* this is a reasonable heuristic for that.
*/
if (mok_state_variables[i].flags & MOK_VARIABLE_CONFIG_ONLY)
continue;
mok_rt_vars[i] = mok_state_variables[i].rtname8;
}
mock_load_variables(testvars, mok_rt_vars, true);
#if defined(SHIM_DEBUG) && SHIM_DEBUG != 0
dump_mock_variables(__FILE__, __LINE__, __func__);
#endif
/*
* This tests the sort policy, filtering for only variables in the
* EFI "global" namespace. If ascending the first thing should
* be Boot0000, if descending it should be dbxDefault
*/
#if defined(SHIM_DEBUG) && SHIM_DEBUG >= 1
printf("Testing mock variable sorting in the global namespace\n");
#endif
size = sizeof(buf);
buf[0] = L'\0';
status = RT->GetNextVariableName(&size, buf, &GV_GUID);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
switch (mock_variable_sort_policy) {
case MOCK_SORT_DESCENDING:
dump_mock_variables_if_wrong(__FILE__, __LINE__, __func__,
&GV_GUID, L"dbxDefault");
assert_zero_goto(StrCmp(buf, L"dbxDefault"), err, "0x%lx != 0x%lx\n");
break;
case MOCK_SORT_ASCENDING:
dump_mock_variables_if_wrong(__FILE__, __LINE__, __func__,
&GV_GUID, L"Boot0000");
assert_zero_goto(StrCmp(buf, L"Boot0000"), err, "0x%lx != 0x%lx buf:\"%s\"\n",
0, Str2str(buf));
break;
default:
break;
}
/*
* Do it again but test for only variables in the Secure Boot
* policy guid namespace. Ascending should be "db", descending
* "dbx".
*/
#if defined(SHIM_DEBUG) && SHIM_DEBUG >= 1
printf("Testing mock variable sorting in the Secure Boot GUID namespace\n");
#endif
size = sizeof(buf);
buf[0] = 0;
status = RT->GetNextVariableName(&size, buf, &EFI_SECURE_BOOT_DB_GUID);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
switch (mock_variable_sort_policy) {
case MOCK_SORT_DESCENDING:
assert_zero_goto(StrCmp(buf, L"dbx"), err, "0x%lx != 0x%lx\n");
break;
case MOCK_SORT_ASCENDING:
assert_zero_goto(StrCmp(buf, L"db"), err, "0x%lx != 0x%lx\n");
break;
default:
break;
}
ret = 0;
err:
if (ret)
mock_print_var_list(&mock_variables);
mock_reset_variables();
return ret;
}
static int
test_gnvn_0(void)
{
return test_gnvn_helper("test-data/efivars-0");
}
static int
test_gnvn_1(void)
{
return test_gnvn_helper("test-data/efivars-1");
}
static int
test_get_variable_0(void)
{
UINTN size = 0;
uint8_t buf[8192] = { 0, };
EFI_STATUS status;
EFI_GUID empty_guid = { 0, };
UINT32 attrs = 0;
int ret = -1;
int cmp;
const char *mok_rt_vars[n_mok_state_variables];
for (size_t i = 0; i < n_mok_state_variables; i++) {
/*
* We don't want to filter out the variables we've added to
* mok mirroring that aren't really from mok; right now
* this is a reasonable heuristic for that.
*/
if (mok_state_variables[i].flags & MOK_VARIABLE_CONFIG_ONLY)
continue;
mok_rt_vars[i] = mok_state_variables[i].rtname8;
}
mock_load_variables("test-data/efivars-1", mok_rt_vars, true);
size = 0;
status = RT->GetVariable(L"Boot0000", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_BUFFER_TOO_SMALL, err, "0x%lx != 0x%lx\n");
size = sizeof(buf);
status = RT->GetVariable(L"Boot0000", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, sizeof(test_data_efivars_0_Boot0000), err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, test_data_efivars_0_Boot0000, size), err, "%zu != %zu\n");
ret = 0;
err:
if (ret)
mock_print_var_list(&mock_variables);
mock_reset_variables();
return ret;
}
static int
test_set_variable_0(void)
{
UINTN size = 0;
uint8_t buf[8192] = { 0, };
EFI_STATUS status;
EFI_GUID empty_guid = { 0, };
UINT32 attrs = 0;
int ret = -1;
UINT32 bs_rt_nv = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_NON_VOLATILE;
size = 4;
strcpy(buf, "foo");
status = RT->SetVariable(L"tmp", &GV_GUID, bs_rt_nv, size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
size = sizeof(buf);
SetMem(buf, sizeof(buf), 0);
status = RT->GetVariable(L"tmp", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, 4, err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, "foo", 4), err, "0x%lx != 0x%lx\n");
size = 5;
strcpy(buf, "bang");
status = RT->SetVariable(L"tmp", &GV_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, buf);
size = sizeof(buf);
SetMem(buf, sizeof(buf), 0);
status = RT->GetVariable(L"tmp", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, 5, err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, "bang", 5), err, "%d != %d\n");
size = 5;
strcpy(buf, "foop");
status = RT->SetVariable(L"tmp", &GV_GUID, bs_rt_nv, size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
size = sizeof(buf);
SetMem(buf, sizeof(buf), 0);
status = RT->GetVariable(L"tmp", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, 5, err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, "foop", 5), err, "%d != %d\n");
size = 0;
strcpy(buf, "");
status = RT->SetVariable(L"tmp", &GV_GUID, bs_rt_nv | EFI_VARIABLE_APPEND_WRITE, size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
size = sizeof(buf);
SetMem(buf, sizeof(buf), 0);
status = RT->GetVariable(L"tmp", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, 5, err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, "foop", 5), err, "%d != %d\n");
size = 5;
strcpy(buf, "poof");
status = RT->SetVariable(L"tmp", &GV_GUID, bs_rt_nv | EFI_VARIABLE_APPEND_WRITE, size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
size = sizeof(buf);
SetMem(buf, sizeof(buf), 0);
status = RT->GetVariable(L"tmp", &GV_GUID, &attrs, &size, buf);
assert_equal_goto(status, EFI_SUCCESS, err, "0x%lx != 0x%lx\n");
assert_equal_goto(size, 10, err, "%zu != %zu\n");
assert_zero_goto(memcmp(buf, "foop\0poof", 10), err, "%d != %d\n");
ret = 0;
err:
if (ret)
mock_print_var_list(&mock_variables);
mock_reset_variables();
return ret;
}
static void
dump_config_table_if_wrong(const char * const func, int line, ...)
{
va_list alist, blist;
bool okay = true;
size_t n = 0, m = 0;
va_start(alist, line);
va_copy(blist, alist);
int idx = va_arg(alist, int);
EFI_GUID *guid = va_arg(alist, EFI_GUID *);
while (idx >= 0 && guid != NULL) {
EFI_CONFIGURATION_TABLE *entry;
if (idx < 0)
goto nexta;
n += 1;
if (idx >= (int)ST->NumberOfTableEntries) {
okay = false;
goto nexta;
}
entry = &ST->ConfigurationTable[idx];
if (CompareGuid(guid, &entry->VendorGuid) != 0)
okay = false;
nexta:
idx = va_arg(alist, int);
guid = va_arg(alist, EFI_GUID *);
}
va_end(alist);
if (okay)
return;
printf("%s:%d:%s(): %d entries:\n", __FILE__, line, func, ST->NumberOfTableEntries);
idx = va_arg(blist, int);
guid = va_arg(blist, EFI_GUID *);
while (idx >= 0 && guid != NULL) {
EFI_CONFIGURATION_TABLE *entry;
if (idx >= (int)ST->NumberOfTableEntries) {
printf("\t[%d]: invalid index for " GUID_FMT "\n",
idx, GUID_ARGS(*guid));
goto nexta;
}
if (idx < 0) {
printf("\t[%d]: " GUID_FMT "\n", idx, GUID_ARGS(*guid));
} else {
entry = &ST->ConfigurationTable[idx];
printf("\t[%d]: %p ", idx, entry);
printf("{.VendorGuid:" GUID_FMT ",", GUID_ARGS(entry->VendorGuid));
printf("&.VendorTable:%p}\n", entry->VendorTable);
if (CompareGuid(guid, &entry->VendorGuid) != 0)
printf("\t\t\t expected:" GUID_FMT "\n", GUID_ARGS(*guid));
}
next:
idx = va_arg(blist, int);
guid = va_arg(blist, EFI_GUID *);
}
va_end(blist);
if ((int)ST->NumberOfTableEntries - n == 0)
return;
printf("%d extra table entries:\n", ST->NumberOfTableEntries - n);
for (m = n; m < ST->NumberOfTableEntries; m++) {
EFI_CONFIGURATION_TABLE *entry;
entry = &ST->ConfigurationTable[m];
printf("\t[%d]: %p ", m, entry);
printf("{.VendorGuid:" GUID_FMT ",", GUID_ARGS(entry->VendorGuid));
printf("&.VendorTable:%p}\n", entry->VendorTable);
}
}
static int
test_install_config_table_0(void)
{
int ret = -1;
EFI_STATUS status;
/*
* These three guids are chosen on purpose: they start with "a",
* "b", and "c", respective to their variable names, so you can
* identify them when dumped.
*/
EFI_GUID aguid = SECURITY_PROTOCOL_GUID;
char astr[guidstr_size];
void *astrp = &astr[0];
int aidx = -1;
EFI_GUID bguid = EFI_HTTP_BINDING_GUID;
char bstr[guidstr_size];
void *bstrp = &bstr[0];
int bidx = -1;
EFI_GUID cguid = MOK_VARIABLE_STORE;
char cstr[guidstr_size];
void *cstrp = &cstr[0];
int cidx = -1;
EFI_GUID lip = LOADED_IMAGE_PROTOCOL;
EFI_GUID guids[3];
char tmpstr[guidstr_size];
sprintf(astrp, GUID_FMT, GUID_ARGS(aguid));
sprintf(bstrp, GUID_FMT, GUID_ARGS(bguid));
sprintf(cstrp, GUID_FMT, GUID_ARGS(cguid));
assert_equal_return(ST->NumberOfTableEntries, 0, -1, "%lu != %lu\n");
/*
* test installing one
*/
status = BS->InstallConfigurationTable(&bguid, bstrp);
assert_equal_return(status, EFI_SUCCESS, -1, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 1, err, "%lu != %lu\n");
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[0].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[0].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[0].VendorTable,
bstrp, err, "%p != %p\n");
/*
* test re-installing the same one
*/
status = BS->InstallConfigurationTable(&bguid, bstrp);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 1, err, "%lu != %lu\n");
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[0].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[0].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[0].VendorTable,
bstrp, err, "%p != %p\n");
/*
* Test installing a second one
*/
status = BS->InstallConfigurationTable(&aguid, astrp);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 2, err, "%lu != %lu\n");
switch (mock_config_table_sort_policy) {
case MOCK_SORT_DESCENDING:
aidx = 1;
bidx = 0;
break;
case MOCK_SORT_PREPEND:
aidx = 0;
bidx = 1;
break;
case MOCK_SORT_APPEND:
aidx = 1;
bidx = 0;
break;
case MOCK_SORT_ASCENDING:
aidx = 0;
bidx = 1;
break;
default:
break;
}
dump_config_table_if_wrong(__func__, __LINE__,
aidx, &aguid,
bidx, &bguid,
cidx, &cguid,
-1, NULL);
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[aidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[aidx].VendorGuid, &aguid),
err, "%d != 0 (%s != %s)\n", tmpstr, astr);
assert_equal_goto(ST->ConfigurationTable[aidx].VendorTable, astrp,
err, "%p != %p\n");
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[bidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[bidx].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[bidx].VendorTable, bstrp,
err, "%p != %p\n");
/*
* Test installing a third one
*/
status = BS->InstallConfigurationTable(&cguid, cstrp);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 3, err, "%lu != %lu\n");
switch (mock_config_table_sort_policy) {
case MOCK_SORT_DESCENDING:
aidx = 2;
bidx = 1;
cidx = 0;
break;
case MOCK_SORT_PREPEND:
aidx = 1;
bidx = 2;
cidx = 0;
break;
case MOCK_SORT_APPEND:
aidx = 1;
bidx = 0;
cidx = 2;
break;
case MOCK_SORT_ASCENDING:
aidx = 0;
bidx = 1;
cidx = 2;
break;
default:
break;
}
dump_config_table_if_wrong(__func__, __LINE__,
aidx, &aguid,
bidx, &bguid,
cidx, &cguid,
-1, NULL);
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[aidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[aidx].VendorGuid, &aguid),
err, "%d != 0 (%s != %s)\n", tmpstr, astr);
assert_equal_goto(ST->ConfigurationTable[aidx].VendorTable, astrp,
err, "%p != %p\n");
memcpy(&guids[aidx], &aguid, sizeof(EFI_GUID));
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[bidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[bidx].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[bidx].VendorTable, bstrp,
err, "%p != %p\n");
memcpy(&guids[bidx], &bguid, sizeof(EFI_GUID));
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[cidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[cidx].VendorGuid, &cguid),
err, "%d != 0 (%s != %s)\n", tmpstr, cstr);
assert_equal_goto(ST->ConfigurationTable[cidx].VendorTable, cstrp,
err, "%p != %p\n");
memcpy(&guids[cidx], &cguid, sizeof(EFI_GUID));
/*
* Test removing NULL guid
*/
status = BS->InstallConfigurationTable(NULL, NULL);
assert_equal_goto(status, EFI_INVALID_PARAMETER, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 3, err, "%lu != %lu\n");
/*
* Test removing a guid that's not present
*/
status = BS->InstallConfigurationTable(&lip, NULL);
assert_equal_goto(status, EFI_NOT_FOUND, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 3, err, "%lu != %lu\n");
/*
* Test removing the middle one
*/
status = BS->InstallConfigurationTable(&guids[1], NULL);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 2, err, "%lu != %lu\n");
switch (mock_config_table_sort_policy) {
case MOCK_SORT_DESCENDING:
aidx = 1;
bidx = -1;
cidx = 0;
break;
case MOCK_SORT_PREPEND:
aidx = -1;
bidx = 1;
cidx = 0;
break;
case MOCK_SORT_APPEND:
aidx = -1;
bidx = 0;
cidx = 1;
break;
case MOCK_SORT_ASCENDING:
aidx = 0;
bidx = -1;
cidx = 1;
break;
default:
break;
}
dump_config_table_if_wrong(__func__, __LINE__,
aidx, &aguid,
bidx, &bguid,
cidx, &cguid,
-1, NULL);
if (aidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[aidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[aidx].VendorGuid, &aguid),
err, "%d != 0 (%s != %s)\n", tmpstr, astr);
assert_equal_goto(ST->ConfigurationTable[aidx].VendorTable, astrp,
err, "%p != %p\n");
memcpy(&guids[aidx], &aguid, sizeof(EFI_GUID));
}
if (bidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[bidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[bidx].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[bidx].VendorTable, bstrp,
err, "%p != %p\n");
memcpy(&guids[bidx], &bguid, sizeof(EFI_GUID));
}
if (cidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[cidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[cidx].VendorGuid, &cguid),
err, "%d != 0 (%s != %s)\n", tmpstr, cstr);
assert_equal_goto(ST->ConfigurationTable[cidx].VendorTable, cstrp,
err, "%p != %p\n");
memcpy(&guids[cidx], &cguid, sizeof(EFI_GUID));
}
/*
* Test removing the lowest one
*/
status = BS->InstallConfigurationTable(&guids[0], NULL);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 1, err, "%lu != %lu\n");
switch (mock_config_table_sort_policy) {
case MOCK_SORT_DESCENDING:
aidx = 0;
bidx = -1;
cidx = -1;
break;
case MOCK_SORT_PREPEND:
aidx = -1;
bidx = 0;
cidx = -1;
break;
case MOCK_SORT_APPEND:
aidx = -1;
bidx = -1;
cidx = 0;
break;
case MOCK_SORT_ASCENDING:
aidx = -1;
bidx = -1;
cidx = 0;
break;
default:
break;
}
dump_config_table_if_wrong(__func__, __LINE__,
aidx, &aguid,
bidx, &bguid,
cidx, &cguid,
-1, NULL);
if (aidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[aidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[aidx].VendorGuid, &aguid),
err, "%d != 0 (%s != %s)\n", tmpstr, astr);
assert_equal_goto(ST->ConfigurationTable[aidx].VendorTable, astrp,
err, "%p != %p\n");
memcpy(&guids[aidx], &aguid, sizeof(EFI_GUID));
}
if (bidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[bidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[bidx].VendorGuid, &bguid),
err, "%d != 0 (%s != %s)\n", tmpstr, bstr);
assert_equal_goto(ST->ConfigurationTable[bidx].VendorTable, bstrp,
err, "%p != %p\n");
memcpy(&guids[bidx], &bguid, sizeof(EFI_GUID));
}
if (cidx >= 0) {
sprintf(tmpstr, GUID_FMT, GUID_ARGS(ST->ConfigurationTable[cidx].VendorGuid));
assert_zero_goto(CompareGuid(&ST->ConfigurationTable[cidx].VendorGuid, &cguid),
err, "%d != 0 (%s != %s)\n", tmpstr, cstr);
assert_equal_goto(ST->ConfigurationTable[cidx].VendorTable, cstrp,
err, "%p != %p\n");
memcpy(&guids[cidx], &cguid, sizeof(EFI_GUID));
}
/*
* Test removing the last one
*/
status = BS->InstallConfigurationTable(&guids[0], NULL);
assert_equal_goto(status, EFI_SUCCESS, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 0, err, "%lu != %lu\n");
/*
* Test removing it again
*/
status = BS->InstallConfigurationTable(&guids[0], NULL);
assert_equal_goto(status, EFI_NOT_FOUND, err, "%lx != %lx\n");
assert_equal_goto(ST->NumberOfTableEntries, 0, err, "%lu != %lu\n");
ret = 0;
err:
while (ST->NumberOfTableEntries)
BS->InstallConfigurationTable(&ST->ConfigurationTable[0].VendorGuid, NULL);
mock_reset_config_table();
return ret;
}
int
main(void)
{
int status = 0;
setbuf(stdout, NULL);
const char *policies[] = {
"MOCK_SORT_DESCENDING",
"MOCK_SORT_PREPEND",
"MOCK_SORT_APPEND",
"MOCK_SORT_ASCENDING",
"MOCK_SORT_MAX_SENTINEL"
};
test(test_filter_out_true);
test(test_filter_out_false);
for (int i = 0; i < MOCK_SORT_MAX_SENTINEL; i++) {
mock_variable_sort_policy = i;
mock_config_table_sort_policy = i;
printf("%s: setting variable sort policy to %s\n",
program_invocation_short_name, policies[i]);
test(test_gnvn_buf_size_0);
test(test_gnvn_0);
test(test_gnvn_1);
test(test_install_config_table_0);
}
test(test_get_variable_0);
test(test_set_variable_0);
return status;
}
// vim:fenc=utf-8:tw=75:noet