/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Tests for vboot_audio
*/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "crc32.h"
#include "gbb_header.h"
#include "host_common.h"
#include "load_kernel_fw.h"
#include "rollback_index.h"
#include "test_common.h"
#include "vboot_audio.h"
#include "vboot_audio_private.h"
#include "vboot_common.h"
#include "vboot_display.h"
#include "vboot_nvstorage.h"
#include "vboot_struct.h"
/* Builtin notes */
extern VbDevMusicNote default_notes_[], short_notes_[];
extern uint32_t default_count_, short_count_;
/* Mock data */
static VbCommonParams cparams;
static GoogleBinaryBlockHeader gbb;
static VbDevMusicNote good_notes[] = { {100, 100},
{100, 0},
{200, 200},
{100, 0},
{300, 300},
{100, 0},
{400, 400},
{30000, 0} };
static VbDevMusic good_header =
{ .sig = { '$', 'S', 'N', 'D' },
.count = sizeof(good_notes) / sizeof(VbDevMusicNote),
};
static uint8_t notebuf[sizeof(good_header) +
sizeof(good_notes) - sizeof(VbDevMusicNote)];
static VbDevMusic *use_hdr;
static VbDevMusicNote *use_notes;
static uint32_t use_size;
/* Set correct checksum for custom notes */
void FixChecksum(VbDevMusic *hdr) {
hdr->checksum = Crc32(&(hdr->count), sizeof(hdr->count) +
hdr->count * sizeof(hdr->notes[0]));
}
/* Reset mock data (for use before each test) */
static void ResetMocks(void) {
VBDEBUG(("ResetMocks()\n"));
Memset(&cparams, 0, sizeof(cparams));
cparams.gbb_data = &gbb;
cparams.gbb = &gbb;
Memset(&gbb, 0, sizeof(gbb));
gbb.major_version = GBB_MAJOR_VER;
gbb.minor_version = GBB_MINOR_VER;
gbb.flags = 0;
use_hdr = (VbDevMusic *)notebuf;
use_notes = use_hdr->notes;
Memcpy(use_hdr, &good_header, sizeof(good_header));
Memcpy(use_notes, good_notes, sizeof(good_notes));
FixChecksum(use_hdr);
use_size = sizeof(notebuf);
}
/* Compare two sets of notes */
static int NotesMatch(VbDevMusicNote *a, VbDevMusicNote *b, uint32_t count) {
int i;
if (!a || !b)
return 0;
for ( i=0; i<count; i++) {
if ( a[i].msec != b[i].msec || a[i].frequency != b[i].frequency)
return 0;
}
return count;
}
/****************************************************************************/
/* Mocked verification functions */
void *VbExGetMusicPtr(void) {
return use_hdr;
}
uint32_t VbExMaxMusicSize(void) {
return use_size;
}
/****************************************************************************/
static void VbAudioTest(void) {
VbAudioContext* a = 0;
/* default is okay */
ResetMocks();
use_hdr = 0;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( default )");
VbAudioClose(a);
/* short is okay */
ResetMocks();
use_hdr = 0;
gbb.flags = 0x00000001;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == short_notes_ &&
a->note_count == short_count_,
"VbAudioTest( short )");
VbAudioClose(a);
/* good custom is okay */
ResetMocks();
a = VbAudioOpen(&cparams);
TEST_TRUE(NotesMatch(a->music_notes, good_notes, good_header.count) &&
a->note_count == good_header.count,
"VbAudioTest( custom good )");
VbAudioClose(a);
/* good custom is rejected when short flag is set */
ResetMocks();
gbb.flags = 0x00000001;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == short_notes_ &&
a->note_count == short_count_,
"VbAudioTest( short has priority )");
VbAudioClose(a);
/* too short gets extended */
ResetMocks();
use_hdr->count--;
FixChecksum(use_hdr);
a = VbAudioOpen(&cparams);
TEST_TRUE(NotesMatch(a->music_notes, use_notes, use_hdr->count) &&
a->note_count == use_hdr->count + 1 &&
a->music_notes[use_hdr->count].msec == 28700 &&
a->music_notes[use_hdr->count].frequency == 0,
"VbAudioTest( too short )");
VbAudioClose(a);
/* too quiet is rejected */
ResetMocks();
use_notes[6].msec = 10;
FixChecksum(use_hdr);
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( too quiet )");
VbAudioClose(a);
/* inaudible is rejected */
ResetMocks();
use_notes[0].frequency = 99;
use_notes[2].frequency = 2001;
FixChecksum(use_hdr);
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( inaudible )");
VbAudioClose(a);
/* bad signature is rejected */
ResetMocks();
use_hdr->sig[0] = 'C';
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( bad signature )");
VbAudioClose(a);
/* count == 0 is rejected */
ResetMocks();
use_hdr->count = 0;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( count == 0 )");
VbAudioClose(a);
/* too big is rejected */
ResetMocks();
use_hdr->count = 999;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( count too big )");
VbAudioClose(a);
/* bad checksum is rejected */
ResetMocks();
use_hdr->checksum++;
a = VbAudioOpen(&cparams);
TEST_TRUE(a->music_notes == default_notes_ &&
a->note_count == default_count_,
"VbAudioTest( count too big )");
VbAudioClose(a);
}
int main(int argc, char* argv[]) {
int error_code = 0;
VbAudioTest();
if (!gTestSuccess)
error_code = 255;
if (vboot_api_stub_check_memory())
error_code = 255;
return error_code;
}