Home | History | Annotate | Download | only in tests
      1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  *
      5  * Tests for firmware display library.
      6  */
      7 
      8 #include <stdint.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #include "bmpblk_font.h"
     14 #include "gbb_header.h"
     15 #include "host_common.h"
     16 #include "region.h"
     17 #include "test_common.h"
     18 #include "vboot_common.h"
     19 #include "vboot_display.h"
     20 #include "vboot_kernel.h"
     21 #include "vboot_nvstorage.h"
     22 
     23 /* Mock data */
     24 static VbCommonParams cparams;
     25 static VbNvContext vnc;
     26 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
     27 static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
     28 static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)];
     29 static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)gbb_data;
     30 static BmpBlockHeader *bhdr;
     31 static char debug_info[4096];
     32 
     33 /* Reset mock data (for use before each test) */
     34 static void ResetMocks(void)
     35 {
     36 	int gbb_used;
     37 
     38 	Memset(gbb_data, 0, sizeof(gbb_data));
     39 	gbb->major_version = GBB_MAJOR_VER;
     40 	gbb->minor_version = GBB_MINOR_VER;
     41 	gbb->flags = 0;
     42 	gbb_used = sizeof(GoogleBinaryBlockHeader);
     43 
     44 	gbb->hwid_offset = gbb_used;
     45 	strcpy(gbb_data + gbb->hwid_offset, "Test HWID");
     46 	gbb->hwid_size = strlen(gbb_data + gbb->hwid_offset) + 1;
     47 	gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7;
     48 
     49 	gbb->bmpfv_offset = gbb_used;
     50 	bhdr = (BmpBlockHeader *)(gbb_data + gbb->bmpfv_offset);
     51 	gbb->bmpfv_size = sizeof(BmpBlockHeader);
     52 	gbb_used = (gbb_used + gbb->bmpfv_size + 7) & ~7;
     53 	memcpy(bhdr->signature, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE);
     54 	bhdr->major_version = BMPBLOCK_MAJOR_VERSION;
     55 	bhdr->minor_version = BMPBLOCK_MINOR_VERSION;
     56 	bhdr->number_of_localizations = 3;
     57 
     58 	Memset(&cparams, 0, sizeof(cparams));
     59 	cparams.shared_data_size = sizeof(shared_data);
     60 	cparams.shared_data_blob = shared_data;
     61 	cparams.gbb_data = gbb;
     62 	cparams.gbb_size = sizeof(gbb_data);
     63 
     64 	/*
     65 	 * Note, VbApiKernelFree() expects this to be allocated by
     66 	 * VbExMalloc(), so we cannot just assign it staticly.
     67 	 */
     68 	cparams.gbb = VbExMalloc(sizeof(*gbb));
     69 	gbb->header_size = sizeof(*gbb);
     70 	gbb->rootkey_offset = gbb_used;
     71 	gbb->rootkey_size = 64;
     72 	gbb_used += 64;
     73 	gbb->recovery_key_offset = gbb_used;
     74 	gbb->recovery_key_size = 64;
     75 	gbb_used += 64;
     76 	memcpy(cparams.gbb, gbb, sizeof(*gbb));
     77 
     78 	Memset(&vnc, 0, sizeof(vnc));
     79 	VbNvSetup(&vnc);
     80 	VbNvTeardown(&vnc);                   /* So CRC gets generated */
     81 
     82 	Memset(&shared_data, 0, sizeof(shared_data));
     83 	VbSharedDataInit(shared, sizeof(shared_data));
     84 
     85 	*debug_info = 0;
     86 }
     87 
     88 /* Mocks */
     89 
     90 VbError_t VbExDisplayDebugInfo(const char *info_str)
     91 {
     92 	strncpy(debug_info, info_str, sizeof(debug_info));
     93 	debug_info[sizeof(debug_info) - 1] = '\0';
     94 	return VBERROR_SUCCESS;
     95 }
     96 
     97 /* Test displaying debug info */
     98 static void DebugInfoTest(void)
     99 {
    100 	char hwid[VB_REGION_HWID_LEN];
    101 	int i;
    102 
    103 	/* Recovery string should be non-null for any code */
    104 	for (i = 0; i < 0x100; i++)
    105 		TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason");
    106 
    107 	/* HWID should come from the gbb */
    108 	ResetMocks();
    109 	VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
    110 	TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID");
    111 	VbApiKernelFree(&cparams);
    112 
    113 	ResetMocks();
    114 	cparams.gbb_size = 0;
    115 	VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
    116 	TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb");
    117 	VbApiKernelFree(&cparams);
    118 
    119 	ResetMocks();
    120 	cparams.gbb->hwid_size = 0;
    121 	VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
    122 	TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing");
    123 	VbApiKernelFree(&cparams);
    124 
    125 	ResetMocks();
    126 	cparams.gbb->hwid_offset = cparams.gbb_size + 1;
    127 	VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
    128 	TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end");
    129 	VbApiKernelFree(&cparams);
    130 
    131 	ResetMocks();
    132 	cparams.gbb->hwid_size = cparams.gbb_size;
    133 	VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
    134 	TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow");
    135 	VbApiKernelFree(&cparams);
    136 
    137 	/* Display debug info */
    138 	ResetMocks();
    139 	VbDisplayDebugInfo(&cparams, &vnc);
    140 	TEST_NEQ(*debug_info, '\0', "Some debug info was displayed");
    141 	VbApiKernelFree(&cparams);
    142 }
    143 
    144 /* Test localization */
    145 static void LocalizationTest(void)
    146 {
    147 	uint32_t count = 6;
    148 
    149 	ResetMocks();
    150 	cparams.gbb->bmpfv_size = 0;
    151 	TEST_EQ(VbGetLocalizationCount(&cparams, &count),
    152 		VBERROR_INVALID_GBB, "VbGetLocalizationCount bad gbb");
    153 	TEST_EQ(count, 0, "  count");
    154 	VbApiKernelFree(&cparams);
    155 
    156 	ResetMocks();
    157 	bhdr->signature[0] ^= 0x5a;
    158 	TEST_EQ(VbGetLocalizationCount(&cparams, &count),
    159 		VBERROR_INVALID_BMPFV, "VbGetLocalizationCount bad bmpfv");
    160 	VbApiKernelFree(&cparams);
    161 
    162 	ResetMocks();
    163 	TEST_EQ(VbGetLocalizationCount(&cparams, &count), 0,
    164 		"VbGetLocalizationCount()");
    165 	TEST_EQ(count, 3, "  count");
    166 	VbApiKernelFree(&cparams);
    167 }
    168 
    169 /* Test display key checking */
    170 static void DisplayKeyTest(void)
    171 {
    172 	uint32_t u;
    173 
    174 	ResetMocks();
    175 	VbCheckDisplayKey(&cparams, 'q', &vnc);
    176 	TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing");
    177 	VbApiKernelFree(&cparams);
    178 
    179 	ResetMocks();
    180 	VbCheckDisplayKey(&cparams, '\t', &vnc);
    181 	TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display");
    182 	VbApiKernelFree(&cparams);
    183 
    184 	/* Toggle localization */
    185 	ResetMocks();
    186 	VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0);
    187 	VbNvTeardown(&vnc);
    188 	VbCheckDisplayKey(&cparams, VB_KEY_DOWN, &vnc);
    189 	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
    190 	TEST_EQ(u, 2, "DisplayKey up");
    191 	VbCheckDisplayKey(&cparams, VB_KEY_LEFT, &vnc);
    192 	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
    193 	TEST_EQ(u, 1, "DisplayKey left");
    194 	VbCheckDisplayKey(&cparams, VB_KEY_RIGHT, &vnc);
    195 	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
    196 	TEST_EQ(u, 2, "DisplayKey right");
    197 	VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
    198 	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
    199 	TEST_EQ(u, 0, "DisplayKey up");
    200 	VbApiKernelFree(&cparams);
    201 
    202 	/* Reset localization if localization count is invalid */
    203 	ResetMocks();
    204 	VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 1);
    205 	VbNvTeardown(&vnc);
    206 	bhdr->signature[0] ^= 0x5a;
    207 	VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
    208 	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
    209 	TEST_EQ(u, 0, "DisplayKey invalid");
    210 	VbApiKernelFree(&cparams);
    211 }
    212 
    213 static void FontTest(void)
    214 {
    215 	FontArrayHeader h;
    216 	FontArrayEntryHeader eh[3] = {
    217 		{
    218 			.ascii = 'A',
    219 			.info.original_size = 10,
    220 		},
    221 		{
    222 			.ascii = 'B',
    223 			.info.original_size = 20,
    224 		},
    225 		{
    226 			.ascii = 'C',
    227 			.info.original_size = 30,
    228 		},
    229 	};
    230 	FontArrayEntryHeader *eptr;
    231 	uint8_t buf[sizeof(h) + sizeof(eh)];
    232 	VbFont_t *fptr;
    233 	void *bufferptr;
    234 	uint32_t buffersize;
    235 
    236 	/* Create font data */
    237 	h.num_entries = ARRAY_SIZE(eh);
    238 	Memcpy(buf, &h, sizeof(h));
    239 	eptr = (FontArrayEntryHeader *)(buf + sizeof(h));
    240 	Memcpy(eptr, eh, sizeof(eh));
    241 
    242 	fptr = VbInternalizeFontData((FontArrayHeader *)buf);
    243 	TEST_PTR_EQ(fptr, buf, "Internalize");
    244 
    245 	TEST_PTR_EQ(VbFindFontGlyph(fptr, 'B', &bufferptr, &buffersize),
    246 		    &eptr[1].info, "Glyph found");
    247 	TEST_EQ(buffersize, eptr[1].info.original_size, "  size");
    248 	TEST_PTR_EQ(VbFindFontGlyph(fptr, 'X', &bufferptr, &buffersize),
    249 		    &eptr[0].info, "Glyph not found");
    250 	TEST_EQ(buffersize, eptr[0].info.original_size, "  size");
    251 
    252 	/* Test invalid rendering params */
    253 	VbRenderTextAtPos(NULL, 0, 0, 0, fptr);
    254 	VbRenderTextAtPos("ABC", 0, 0, 0, NULL);
    255 
    256 	VbDoneWithFontForNow(fptr);
    257 
    258 }
    259 
    260 int main(void)
    261 {
    262 	DebugInfoTest();
    263 	LocalizationTest();
    264 	DisplayKeyTest();
    265 	FontTest();
    266 
    267 	if (vboot_api_stub_check_memory())
    268 		return 255;
    269 
    270 	return gTestSuccess ? 0 : 255;
    271 }
    272