1 /* Copyright (c) 2011 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 vboot_api_firmware
6 */
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #include "crc32.h"
14 #include "gbb_header.h"
15 #include "host_common.h"
16 #include "load_kernel_fw.h"
17 #include "rollback_index.h"
18 #include "test_common.h"
19 #include "vboot_common.h"
20 #include "vboot_display.h"
21 #include "vboot_nvstorage.h"
22 #include "vboot_struct.h"
23
24
25 /* Expected results */
26
27 #define MAX_NOTE_EVENTS 10
28 #define TICKS_PER_MSEC 1900ULL
29 #define TIME_FUZZ 500
30 #define KBD_READ_TIME 60
31
32 typedef struct {
33 uint16_t msec;
34 uint16_t freq;
35 int time;
36 } note_event_t;
37
38 typedef struct {
39 char *name;
40 uint32_t gbb_flags;
41 VbError_t beep_return;
42 uint32_t keypress_key;
43 int keypress_at_count;
44 int num_events;
45 note_event_t notes[MAX_NOTE_EVENTS];
46 } test_case_t;
47
48 test_case_t test[] = {
49
50 { "VbBootDeveloperSoundTest( fast, background )",
51 0x00000001, VBERROR_SUCCESS,
52 0, 0,
53 2,
54 {
55 {0, 0, 0}, // probing for capability
56 {0, 0, 2000}, // off and return at 2 seconds
57 }},
58
59 { "VbBootDeveloperSoundTest( normal, background )",
60 0x00000000, VBERROR_SUCCESS,
61 0, 0,
62 6,
63 {
64 {0, 0, 0}, // probing for capability
65 {0, 400, 20000}, // starts first beep at 20 seconds
66 {0, 0, 20250}, // stops 250ms later
67 {0, 400, 20500}, // starts second beep
68 {0, 0, 20750}, // stops 250ms later
69 {0, 0, 30000}, // off and return at 30 seconds
70 }},
71
72 { "VbBootDeveloperSoundTest( fast, no background )",
73 0x00000001, VBERROR_NO_BACKGROUND_SOUND,
74 0, 0,
75 2,
76 {
77 {0, 0, 0}, // probing for capability
78 {0, 0, 2000}, // off and return at 2 seconds
79 }},
80
81 { "VbBootDeveloperSoundTest( normal, no background )",
82 0x00000000, VBERROR_NO_BACKGROUND_SOUND,
83 0, 0,
84 4,
85 {
86 {0, 0, 0}, // probing for capability
87 {250, 400, 20000}, // first beep at 20 seconds
88 {250, 400, 20510}, // second beep shortly after
89 {0, 0, 30020}, // off and return at 30 seconds
90 }},
91
92 // Now with some keypresses
93
94 { "VbBootDeveloperSoundTest( normal, background, Ctrl-D )",
95 0x00000000, VBERROR_SUCCESS,
96 4, 10000, // Ctrl-D at 10 seconds
97 2,
98 {
99 {0, 0, 0}, // probing for capability
100 {0, 0, 10000}, // sees Ctrl-D, sound off, return
101 }},
102
103 { "VbBootDeveloperSoundTest( normal, no background, Ctrl-D )",
104 0x00000000, VBERROR_NO_BACKGROUND_SOUND,
105 4, 20400, // Ctrl-D between beeps
106 3,
107 {
108 {0, 0, 0}, // probing for capability
109 {250, 400, 20000}, // first beep at 20 seconds
110 {0, 0, 20400}, // sees Ctrl-D, sound off, return
111 }},
112
113 { "VbBootDeveloperSoundTest( normal, background, Ctrl-U not allowed )",
114 0x00000000, VBERROR_SUCCESS,
115 21, 10000, // Ctrl-U at 10 seconds
116 8,
117 {
118 {0, 0, 0}, // probing for capability
119 {120, 400, 10000}, // complains about Ctrl-U (one beep)
120 // waits 120ms...
121 {120, 400, 10240}, // complains about Ctrl-U (two beeps)
122 // original sequence is now shifted...
123 {0, 400, 20360}, // starts first beep at 20 seconds
124 {0, 0, 20610}, // stops 250ms later
125 {0, 400, 20860}, // starts second beep
126 {0, 0, 21110}, // stops 250ms later
127 {0, 0, 30360}, // returns at 30 seconds + 360ms
128 }},
129
130 };
131
132 /* Mock data */
133 static VbCommonParams cparams;
134 static LoadKernelParams lkparams;
135 static VbNvContext vnc;
136 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
137 static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
138 static GoogleBinaryBlockHeader gbb;
139 static int current_time;
140 static uint64_t current_ticks;
141 static int current_event;
142 static int max_events;
143 static int matched_events;
144 static int kbd_fire_at;
145 static uint32_t kbd_fire_key;
146 static VbError_t beep_return;
147 static note_event_t *expected_event;
148
149 /* Reset mock data (for use before each test) */
ResetMocks(void)150 static void ResetMocks(void) {
151
152 Memset(&cparams, 0, sizeof(cparams));
153 cparams.shared_data_size = sizeof(shared_data);
154 cparams.shared_data_blob = shared_data;
155 cparams.gbb_data = &gbb;
156 cparams.gbb = &gbb;
157
158 Memset(&lkparams, 0, sizeof(lkparams));
159
160 Memset(&vnc, 0, sizeof(vnc));
161 VbNvSetup(&vnc);
162 VbNvTeardown(&vnc); /* So CRC gets generated */
163
164 Memset(&shared_data, 0, sizeof(shared_data));
165 VbSharedDataInit(shared, sizeof(shared_data));
166 shared->fw_keyblock_flags = 0xABCDE0;
167
168 Memset(&gbb, 0, sizeof(gbb));
169 gbb.major_version = GBB_MAJOR_VER;
170 gbb.minor_version = GBB_MINOR_VER;
171 gbb.flags = 0;
172
173 current_ticks = 0;
174 current_time = 0;
175
176 current_event = 0;
177 kbd_fire_at = 0;
178 kbd_fire_key = 0;
179
180 beep_return = VBERROR_SUCCESS;
181
182 matched_events = 0;
183 max_events = 0;
184 }
185
186 /****************************************************************************/
187 /* Mocked verification functions */
188
VbExNvStorageRead(uint8_t * buf)189 VbError_t VbExNvStorageRead(uint8_t* buf) {
190 Memcpy(buf, vnc.raw, sizeof(vnc.raw));
191 return VBERROR_SUCCESS;
192 }
193
VbExNvStorageWrite(const uint8_t * buf)194 VbError_t VbExNvStorageWrite(const uint8_t* buf) {
195 Memcpy(vnc.raw, buf, sizeof(vnc.raw));
196 return VBERROR_SUCCESS;
197 }
198
VbExDiskGetInfo(VbDiskInfo ** infos_ptr,uint32_t * count,uint32_t disk_flags)199 VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
200 uint32_t disk_flags) {
201 return VBERROR_UNKNOWN;
202 }
203
VbExDiskFreeInfo(VbDiskInfo * infos,VbExDiskHandle_t preserve_handle)204 VbError_t VbExDiskFreeInfo(VbDiskInfo* infos,
205 VbExDiskHandle_t preserve_handle) {
206 return VBERROR_SUCCESS;
207 }
208
VbExDiskRead(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,void * buffer)209 VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
210 uint64_t lba_count, void* buffer) {
211 return VBERROR_UNKNOWN;
212 }
213
VbExDiskWrite(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,const void * buffer)214 VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
215 uint64_t lba_count, const void* buffer) {
216 return VBERROR_UNKNOWN;
217 }
218
VbExIsShutdownRequested(void)219 uint32_t VbExIsShutdownRequested(void) {
220 return 0;
221 }
222
VbExKeyboardRead(void)223 uint32_t VbExKeyboardRead(void) {
224 uint32_t tmp;
225 uint32_t now;
226
227 VbExSleepMs(KBD_READ_TIME);
228 now = current_time;
229
230 if (kbd_fire_key && now >= kbd_fire_at) {
231 VBDEBUG((" VbExKeyboardRead() - returning %d at %d msec\n",
232 kbd_fire_key, now));
233 tmp = kbd_fire_key;
234 kbd_fire_key = 0;
235 return tmp;
236 }
237 VBDEBUG((" VbExKeyboardRead() - returning %d at %d msec\n",
238 0, now));
239 return 0;
240 }
241
VbExSleepMs(uint32_t msec)242 void VbExSleepMs(uint32_t msec) {
243 current_ticks += (uint64_t)msec * TICKS_PER_MSEC;
244 current_time = current_ticks / TICKS_PER_MSEC;
245 VBDEBUG(("VbExSleepMs(%d) -> %d\n", msec, current_time));
246 }
247
VbExGetTimer(void)248 uint64_t VbExGetTimer(void) {
249 return current_ticks;
250 }
251
VbExBeep(uint32_t msec,uint32_t frequency)252 VbError_t VbExBeep(uint32_t msec, uint32_t frequency) {
253 VBDEBUG(("VbExBeep(%d, %d) at %d msec\n", msec, frequency, current_time));
254
255 if (current_event < max_events &&
256 msec == expected_event[current_event].msec &&
257 frequency == expected_event[current_event].freq &&
258 abs(current_time - expected_event[current_event].time) < TIME_FUZZ ) {
259 matched_events++;
260 }
261
262 if (msec)
263 VbExSleepMs(msec);
264 current_event++;
265 return beep_return;
266 }
267
VbExDisplayScreen(uint32_t screen_type)268 VbError_t VbExDisplayScreen(uint32_t screen_type) {
269 switch(screen_type) {
270 case VB_SCREEN_BLANK:
271 VBDEBUG(("VbExDisplayScreen(BLANK)\n"));
272 break;
273 case VB_SCREEN_DEVELOPER_WARNING:
274 VBDEBUG(("VbExDisplayScreen(DEV)\n"));
275 break;
276 case VB_SCREEN_DEVELOPER_EGG:
277 VBDEBUG(("VbExDisplayScreen(EGG)\n"));
278 break;
279 case VB_SCREEN_RECOVERY_REMOVE:
280 VBDEBUG(("VbExDisplayScreen(REMOVE)\n"));
281 break;
282 case VB_SCREEN_RECOVERY_INSERT:
283 VBDEBUG(("VbExDisplayScreen(INSERT)\n"));
284 break;
285 case VB_SCREEN_RECOVERY_NO_GOOD:
286 VBDEBUG(("VbExDisplayScreen(NO_GOOD)\n"));
287 break;
288 default:
289 VBDEBUG(("VbExDisplayScreen(%d)\n", screen_type));
290 }
291
292 VBDEBUG((" current_time is %d msec\n", current_time));
293
294 return VBERROR_SUCCESS;
295 }
296
297 /****************************************************************************/
298
299 VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p);
300
301
VbBootDeveloperSoundTest(void)302 static void VbBootDeveloperSoundTest(void) {
303 int i;
304 int num_tests = sizeof(test) / sizeof(test_case_t);
305
306 for (i=0; i<num_tests; i++) {
307 VBDEBUG(("STARTING %s ...\n", test[i].name));
308 ResetMocks();
309 gbb.flags = test[i].gbb_flags;
310 beep_return = test[i].beep_return;
311 kbd_fire_key = test[i].keypress_key;
312 kbd_fire_at = test[i].keypress_at_count;
313 max_events = test[i].num_events;
314 expected_event = test[i].notes;
315 (void) VbBootDeveloper(&cparams, &lkparams);
316 VBDEBUG(("INFO: matched %d total %d expected %d\n",
317 matched_events, current_event, test[i].num_events));
318 TEST_TRUE(matched_events == test[i].num_events &&
319 current_event == test[i].num_events, test[i].name);
320 }
321 }
322
323
main(int argc,char * argv[])324 int main(int argc, char* argv[]) {
325 int error_code = 0;
326
327 VbBootDeveloperSoundTest();
328
329 if (!gTestSuccess)
330 error_code = 255;
331 if (vboot_api_stub_check_memory())
332 error_code = 255;
333
334 return error_code;
335 }
336