Files
OpenCellular/tests/vboot_display_tests.c
Simon Glass 2500185a83 Add memory leak checking
Add checks that the vboot library does not leak memory. This works by
tracking VbExMalloc() calls and making sure that they have an associated
VbExFree().

Adjust host_signature to use VbExFree() instead of free(), so that this
scheme works correctly for existing code.

BUG=chrome-os-partner:21115
BRANCH=pit
TEST=FEATURES=test emerge-peach_pit vboot_reference

Change-Id: I6ccccfbcc162fc43fb75862cd0eddad78ce8b18a
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/66175
2013-09-17 23:17:17 +00:00

272 lines
7.3 KiB
C

/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Tests for firmware display library.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bmpblk_font.h"
#include "gbb_header.h"
#include "host_common.h"
#include "region.h"
#include "test_common.h"
#include "vboot_common.h"
#include "vboot_display.h"
#include "vboot_kernel.h"
#include "vboot_nvstorage.h"
/* Mock data */
static VbCommonParams cparams;
static VbNvContext vnc;
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)];
static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)gbb_data;
static BmpBlockHeader *bhdr;
static char debug_info[4096];
/* Reset mock data (for use before each test) */
static void ResetMocks(void)
{
int gbb_used;
Memset(gbb_data, 0, sizeof(gbb_data));
gbb->major_version = GBB_MAJOR_VER;
gbb->minor_version = GBB_MINOR_VER;
gbb->flags = 0;
gbb_used = sizeof(GoogleBinaryBlockHeader);
gbb->hwid_offset = gbb_used;
strcpy(gbb_data + gbb->hwid_offset, "Test HWID");
gbb->hwid_size = strlen(gbb_data + gbb->hwid_offset) + 1;
gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7;
gbb->bmpfv_offset = gbb_used;
bhdr = (BmpBlockHeader *)(gbb_data + gbb->bmpfv_offset);
gbb->bmpfv_size = sizeof(BmpBlockHeader);
gbb_used = (gbb_used + gbb->bmpfv_size + 7) & ~7;
memcpy(bhdr->signature, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE);
bhdr->major_version = BMPBLOCK_MAJOR_VERSION;
bhdr->minor_version = BMPBLOCK_MINOR_VERSION;
bhdr->number_of_localizations = 3;
Memset(&cparams, 0, sizeof(cparams));
cparams.shared_data_size = sizeof(shared_data);
cparams.shared_data_blob = shared_data;
cparams.gbb_data = gbb;
cparams.gbb_size = sizeof(gbb_data);
/*
* Note, VbApiKernelFree() expects this to be allocated by
* VbExMalloc(), so we cannot just assign it staticly.
*/
cparams.gbb = VbExMalloc(sizeof(*gbb));
gbb->header_size = sizeof(*gbb);
gbb->rootkey_offset = gbb_used;
gbb->rootkey_size = 64;
gbb_used += 64;
gbb->recovery_key_offset = gbb_used;
gbb->recovery_key_size = 64;
gbb_used += 64;
memcpy(cparams.gbb, gbb, sizeof(*gbb));
Memset(&vnc, 0, sizeof(vnc));
VbNvSetup(&vnc);
VbNvTeardown(&vnc); /* So CRC gets generated */
Memset(&shared_data, 0, sizeof(shared_data));
VbSharedDataInit(shared, sizeof(shared_data));
*debug_info = 0;
}
/* Mocks */
VbError_t VbExDisplayDebugInfo(const char *info_str)
{
strncpy(debug_info, info_str, sizeof(debug_info));
debug_info[sizeof(debug_info) - 1] = '\0';
return VBERROR_SUCCESS;
}
/* Test displaying debug info */
static void DebugInfoTest(void)
{
char hwid[VB_REGION_HWID_LEN];
int i;
/* Recovery string should be non-null for any code */
for (i = 0; i < 0x100; i++)
TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason");
/* HWID should come from the gbb */
ResetMocks();
VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID");
VbApiKernelFree(&cparams);
ResetMocks();
cparams.gbb_size = 0;
VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb");
VbApiKernelFree(&cparams);
ResetMocks();
cparams.gbb->hwid_size = 0;
VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing");
VbApiKernelFree(&cparams);
ResetMocks();
cparams.gbb->hwid_offset = cparams.gbb_size + 1;
VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end");
VbApiKernelFree(&cparams);
ResetMocks();
cparams.gbb->hwid_size = cparams.gbb_size;
VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow");
VbApiKernelFree(&cparams);
/* Display debug info */
ResetMocks();
VbDisplayDebugInfo(&cparams, &vnc);
TEST_NEQ(*debug_info, '\0', "Some debug info was displayed");
VbApiKernelFree(&cparams);
}
/* Test localization */
static void LocalizationTest(void)
{
uint32_t count = 6;
ResetMocks();
cparams.gbb->bmpfv_size = 0;
TEST_EQ(VbGetLocalizationCount(&cparams, &count),
VBERROR_INVALID_GBB, "VbGetLocalizationCount bad gbb");
TEST_EQ(count, 0, " count");
VbApiKernelFree(&cparams);
ResetMocks();
bhdr->signature[0] ^= 0x5a;
TEST_EQ(VbGetLocalizationCount(&cparams, &count),
VBERROR_INVALID_BMPFV, "VbGetLocalizationCount bad bmpfv");
VbApiKernelFree(&cparams);
ResetMocks();
TEST_EQ(VbGetLocalizationCount(&cparams, &count), 0,
"VbGetLocalizationCount()");
TEST_EQ(count, 3, " count");
VbApiKernelFree(&cparams);
}
/* Test display key checking */
static void DisplayKeyTest(void)
{
uint32_t u;
ResetMocks();
VbCheckDisplayKey(&cparams, 'q', &vnc);
TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing");
VbApiKernelFree(&cparams);
ResetMocks();
VbCheckDisplayKey(&cparams, '\t', &vnc);
TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display");
VbApiKernelFree(&cparams);
/* Toggle localization */
ResetMocks();
VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0);
VbNvTeardown(&vnc);
VbCheckDisplayKey(&cparams, VB_KEY_DOWN, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 2, "DisplayKey up");
VbCheckDisplayKey(&cparams, VB_KEY_LEFT, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 1, "DisplayKey left");
VbCheckDisplayKey(&cparams, VB_KEY_RIGHT, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 2, "DisplayKey right");
VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 0, "DisplayKey up");
VbApiKernelFree(&cparams);
/* Reset localization if localization count is invalid */
ResetMocks();
VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 1);
VbNvTeardown(&vnc);
bhdr->signature[0] ^= 0x5a;
VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 0, "DisplayKey invalid");
VbApiKernelFree(&cparams);
}
static void FontTest(void)
{
FontArrayHeader h;
FontArrayEntryHeader eh[3] = {
{
.ascii = 'A',
.info.original_size = 10,
},
{
.ascii = 'B',
.info.original_size = 20,
},
{
.ascii = 'C',
.info.original_size = 30,
},
};
FontArrayEntryHeader *eptr;
uint8_t buf[sizeof(h) + sizeof(eh)];
VbFont_t *fptr;
void *bufferptr;
uint32_t buffersize;
/* Create font data */
h.num_entries = ARRAY_SIZE(eh);
Memcpy(buf, &h, sizeof(h));
eptr = (FontArrayEntryHeader *)(buf + sizeof(h));
Memcpy(eptr, eh, sizeof(eh));
fptr = VbInternalizeFontData((FontArrayHeader *)buf);
TEST_PTR_EQ(fptr, buf, "Internalize");
TEST_PTR_EQ(VbFindFontGlyph(fptr, 'B', &bufferptr, &buffersize),
&eptr[1].info, "Glyph found");
TEST_EQ(buffersize, eptr[1].info.original_size, " size");
TEST_PTR_EQ(VbFindFontGlyph(fptr, 'X', &bufferptr, &buffersize),
&eptr[0].info, "Glyph not found");
TEST_EQ(buffersize, eptr[0].info.original_size, " size");
/* Test invalid rendering params */
VbRenderTextAtPos(NULL, 0, 0, 0, fptr);
VbRenderTextAtPos("ABC", 0, 0, 0, NULL);
VbDoneWithFontForNow(fptr);
}
int main(void)
{
DebugInfoTest();
LocalizationTest();
DisplayKeyTest();
FontTest();
if (vboot_api_stub_check_memory())
return 255;
return gTestSuccess ? 0 : 255;
}