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