mirror of
				https://git.proxmox.com/git/efi-boot-shim
				synced 2025-11-04 13:10:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			843 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			843 lines
		
	
	
		
			23 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++) {
 | 
						|
		mok_rt_vars[i] = mok_state_variables[i].rtname8;
 | 
						|
	}
 | 
						|
 | 
						|
	mock_load_variables(testvars, mok_rt_vars, true);
 | 
						|
 | 
						|
	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");
 | 
						|
 | 
						|
#if defined(SHIM_DEBUG) && SHIM_DEBUG != 0
 | 
						|
	dump_mock_variables(__FILE__, __LINE__, __func__);
 | 
						|
#endif
 | 
						|
	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;
 | 
						|
	}
 | 
						|
 | 
						|
	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++) {
 | 
						|
		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
 |