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 */ 24static VbCommonParams cparams; 25static VbNvContext vnc; 26static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 27static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 28static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)]; 29static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)gbb_data; 30static BmpBlockHeader *bhdr; 31static char debug_info[4096]; 32 33/* Reset mock data (for use before each test) */ 34static 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 90VbError_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 */ 98static 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 */ 145static 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 */ 170static 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 213static 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 260int 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