Home | History | Annotate | Download | only in tests
      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) */
    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 
    189 VbError_t VbExNvStorageRead(uint8_t* buf) {
    190   Memcpy(buf, vnc.raw, sizeof(vnc.raw));
    191   return VBERROR_SUCCESS;
    192 }
    193 
    194 VbError_t VbExNvStorageWrite(const uint8_t* buf) {
    195   Memcpy(vnc.raw, buf, sizeof(vnc.raw));
    196   return VBERROR_SUCCESS;
    197 }
    198 
    199 VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
    200                           uint32_t disk_flags) {
    201   return VBERROR_UNKNOWN;
    202 }
    203 
    204 VbError_t VbExDiskFreeInfo(VbDiskInfo* infos,
    205                            VbExDiskHandle_t preserve_handle) {
    206   return VBERROR_SUCCESS;
    207 }
    208 
    209 VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
    210                        uint64_t lba_count, void* buffer) {
    211   return VBERROR_UNKNOWN;
    212 }
    213 
    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 
    219 uint32_t VbExIsShutdownRequested(void) {
    220   return 0;
    221 }
    222 
    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 
    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 
    248 uint64_t VbExGetTimer(void) {
    249   return current_ticks;
    250 }
    251 
    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 
    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 
    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 
    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