diff options
author | Bill Richardson <wfrichar@chromium.org> | 2011-10-03 14:00:58 -0700 |
---|---|---|
committer | Bill Richardson <wfrichar@chromium.org> | 2011-10-05 11:09:20 -0700 |
commit | 253a58e3834631e4688da45d31b0c475926bcbd6 (patch) | |
tree | d1a1555a98adf7323c035f554dd44bb765354b2f | |
parent | 791c95fa23d93fb6104f3c6ec248c7ad4c773b8c (diff) | |
download | vboot-253a58e3834631e4688da45d31b0c475926bcbd6.tar.gz |
Refactor dev-mode delay handling into a separate file.
BUG=none
TEST=manual
cd src/platform/vboot_reference
make && make runtests
Change-Id: I56feceb7d4fce80e4f50d5d7875eafef325363cc
Reviewed-on: http://gerrit.chromium.org/gerrit/8659
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Tested-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | firmware/Makefile | 1 | ||||
-rw-r--r-- | firmware/lib/include/vboot_audio.h | 25 | ||||
-rw-r--r-- | firmware/lib/include/vboot_display.h | 13 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 104 | ||||
-rw-r--r-- | firmware/lib/vboot_audio.c | 151 | ||||
-rw-r--r-- | tests/vboot_api_devmode_tests.c | 3 |
6 files changed, 189 insertions, 108 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index 379252d0..faee7c3d 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -63,6 +63,7 @@ LIB_SRCS = \ ./lib/vboot_api_init.c \ ./lib/vboot_api_firmware.c \ ./lib/vboot_api_kernel.c \ + ./lib/vboot_audio.c \ ./lib/vboot_common.c \ ./lib/vboot_display.c \ ./lib/vboot_firmware.c \ diff --git a/firmware/lib/include/vboot_audio.h b/firmware/lib/include/vboot_audio.h new file mode 100644 index 00000000..efa241b3 --- /dev/null +++ b/firmware/lib/include/vboot_audio.h @@ -0,0 +1,25 @@ +/* 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. + * + * Display functions used in kernel selection. + */ + +#ifndef VBOOT_REFERENCE_VBOOT_AUDIO_H_ +#define VBOOT_REFERENCE_VBOOT_AUDIO_H_ + +#include "vboot_api.h" + +typedef struct VbAudioContext VbAudioContext; + +/* Initialization function. Returns context for processing dev-mode delay */ +VbAudioContext* VbAudioOpen(VbCommonParams* cparams); + +/* Caller should loop without extra delay until this returns false */ +int VbAudioLooping(VbAudioContext* audio); + +/* Caller should call this prior to booting */ +void VbAudioClose(VbAudioContext* audio); + +#endif /* VBOOT_REFERENCE_VBOOT_AUDIO_H_ */ + diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h index aace9708..8dc22606 100644 --- a/firmware/lib/include/vboot_display.h +++ b/firmware/lib/include/vboot_display.h @@ -21,18 +21,5 @@ VbError_t VbCheckDisplayKey(VbCommonParams* cparams, uint32_t key, void VbExEasterEgg(VbCommonParams* cparams, VbNvContext *vncptr); -typedef struct VbDevMusicNote { - uint16_t msec; - uint16_t frequency; -} __attribute__((packed)) VbDevMusicNote; - -typedef struct VbDevMusic { - uint8_t sig[4]; /* "$SND" */ - uint32_t checksum; /* crc32 over count & all notes */ - uint32_t count; /* number of notes */ - VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */ - /* more VbDevMusicNotes follow immediately */ -} __attribute__((packed)) VbDevMusic; - #endif /* VBOOT_REFERENCE_VBOOT_DISPLAY_H_ */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index fa3a9372..a8368603 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -10,6 +10,7 @@ #include "rollback_index.h" #include "utility.h" #include "vboot_api.h" +#include "vboot_audio.h" #include "vboot_common.h" #include "vboot_display.h" #include "vboot_nvstorage.h" @@ -105,42 +106,10 @@ VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) { return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED); } -#define DEV_LOOP_TIME 10 /* Minimum note granularity in msecs */ - -static uint16_t VbMsecToLoops(uint16_t msec) { - return (DEV_LOOP_TIME / 2 + msec) / DEV_LOOP_TIME; -} - -static VbDevMusicNote default_notes[] = { {20000, 0}, /* 20 seconds */ - {250, 400}, /* two beeps */ - {250, 0}, - {250, 400}, - {9250, 0} }; /* total 30 seconds */ - -static VbDevMusicNote short_notes[] = { {2000, 0} }; /* two seconds */ - -/* Return a valid set of note events. */ -static VbDevMusicNote* VbGetDevMusicNotes(uint32_t *count, int use_short) { - - if (use_short) { - *count = sizeof(short_notes) / sizeof(short_notes[0]); - return short_notes; - } - - *count = sizeof(default_notes) / sizeof(default_notes[0]); - return default_notes; -} - - /* Handle a developer-mode boot */ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { - GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; uint32_t allow_usb = 0; - uint32_t note_count = 0; - VbDevMusicNote* music_notes = 0; - uint32_t current_note = 0; - uint32_t current_note_loops = 0; - int background_beep = 1; + VbAudioContext* audio = 0; /* Check if USB booting is allowed */ VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb); @@ -148,27 +117,11 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { /* Show the dev mode warning screen */ VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc); - /* See if we have full background sound capability or not. */ - if (VBERROR_SUCCESS != VbExBeep(0,0)) { - VBDEBUG(("VbBootDeveloper: VbExBeep() is limited\n")); - background_beep = 0; - } - - /* Prepare to generate audio/delay event. Use a short developer screen delay - * if indicated by GBB flags. - */ - if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 - && (gbb->flags & GBB_FLAG_DEV_SCREEN_SHORT_DELAY)) { - VBDEBUG(("VbBootDeveloper() - using short developer screen delay\n")); - music_notes = VbGetDevMusicNotes(¬e_count, 1); - } else { - music_notes = VbGetDevMusicNotes(¬e_count, 0); - } - - VBDEBUG(("VbBootDeveloper() - note count %d\n", note_count)); + /* Get audio/delay context */ + audio = VbAudioOpen(cparams); - /* We'll loop until we finish the notes or are interrupted */ - while(1) { + /* We'll loop until we finish the delay or are interrupted */ + do { uint32_t key; if (VbExIsShutdownRequested()) @@ -184,8 +137,8 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { case 0x1B: /* Enter, space, or ESC = reboot to recovery */ VBDEBUG(("VbBootDeveloper() - user pressed ENTER/SPACE/ESC\n")); - VbExBeep(0, 0); /* sound off */ VbSetRecoveryRequest(VBNV_RECOVERY_RW_DEV_SCREEN); + VbAudioClose(audio); return 1; case 0x04: /* Ctrl+D = dismiss warning; advance to timeout */ @@ -195,7 +148,6 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { case 0x15: /* Ctrl+U = try USB boot, or beep if failure */ VBDEBUG(("VbBootDeveloper() - user pressed Ctrl+U; try USB\n")); - VbExBeep(0, 0); /* sound off */ if (!allow_usb) { VBDEBUG(("VbBootDeveloper() - USB booting is disabled\n")); VbExBeep(120, 400); @@ -204,11 +156,12 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { } else if (VBERROR_SUCCESS == VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE)) { VBDEBUG(("VbBootDeveloper() - booting USB\n")); + VbAudioClose(audio); return VBERROR_SUCCESS; } else { VBDEBUG(("VbBootDeveloper() - no kernel found on USB\n")); VbExBeep(250, 200); - VbExBeep(100, 0); + VbExSleepMs(120); /* Clear recovery requests from failed kernel loading, so * that powering off at this point doesn't put us into * recovery mode. */ @@ -220,47 +173,12 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) { break; } - /* Time to play a note? */ - if (!current_note_loops) { - VBDEBUG(("VbBootDeveloper() - current_note is %d\n", current_note)); - - /* Sorry, out of notes */ - if (current_note >= note_count) - break; - - /* For how many loops do we hold this note? */ - current_note_loops = VbMsecToLoops(music_notes[current_note].msec); - VBDEBUG(("VbBootDeveloper() - new current_note_loops == %d\n", - current_note_loops)); - - if (background_beep) { - - /* start (or stop) the sound */ - VbExBeep(0, music_notes[current_note].frequency); - - } else if (music_notes[current_note].frequency) { - - /* the sound will block, so don't loop repeatedly */ - current_note_loops = 1; - VbExBeep(music_notes[current_note].msec, - music_notes[current_note].frequency); - } - - current_note++; - } - - /* Wait a bit. Yes, one extra loop sometimes, but it's only 10msec */ - VbExSleepMs(DEV_LOOP_TIME); - - /* That's one... */ - if (current_note_loops) - current_note_loops--; - } + } while( VbAudioLooping(audio) ); fallout: /* Timeout or Ctrl+D; attempt loading from fixed disk */ - VbExBeep(0, 0); /* sound off */ VBDEBUG(("VbBootDeveloper() - trying fixed disk\n")); + VbAudioClose(audio); return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED); } diff --git a/firmware/lib/vboot_audio.c b/firmware/lib/vboot_audio.c new file mode 100644 index 00000000..45e9f175 --- /dev/null +++ b/firmware/lib/vboot_audio.c @@ -0,0 +1,151 @@ +/* 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. + * + * Audio functions used in dev-mode kernel selection. + */ + +#include "gbb_header.h" +#include "utility.h" +#include "vboot_api.h" +#include "vboot_audio.h" +#include "vboot_common.h" + + +typedef struct VbDevMusicNote { + uint16_t msec; + uint16_t frequency; +} __attribute__((packed)) VbDevMusicNote; + +typedef struct VbDevMusic { + uint8_t sig[4]; /* "$SND" */ + uint32_t checksum; /* crc32 over count & all notes */ + uint32_t count; /* number of notes */ + VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */ + /* more VbDevMusicNotes follow immediately */ +} __attribute__((packed)) VbDevMusic; + +static struct VbAudioContext { + uint32_t note_count; + VbDevMusicNote* music_notes; + uint32_t current_note; + uint32_t current_note_loops; + int background_beep; +} au; + + +#define DEV_LOOP_TIME 10 /* Minimum note granularity in msecs */ + + +static uint16_t VbMsecToLoops(uint16_t msec) { + return (DEV_LOOP_TIME / 2 + msec) / DEV_LOOP_TIME; +} + +static VbDevMusicNote default_notes[] = { {20000, 0}, /* 20 seconds */ + {250, 400}, /* two beeps */ + {250, 0}, + {250, 400}, + {9250, 0} }; /* total 30 seconds */ + +static VbDevMusicNote short_notes[] = { {2000, 0} }; /* two seconds */ + +/* Return a valid set of note events. */ +static VbDevMusicNote* VbGetDevMusicNotes(uint32_t* count, int use_short) { + + if (use_short) { + *count = sizeof(short_notes) / sizeof(short_notes[0]); + return short_notes; + } + + *count = sizeof(default_notes) / sizeof(default_notes[0]); + return default_notes; +} + + +/* Initialization function. Returns context for processing dev-mode delay */ +VbAudioContext* VbAudioOpen(VbCommonParams* cparams) { + GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; + VbAudioContext* audio = &au; + + /* Note: may need to allocate things here in future */ + + /* defaults */ + audio->note_count = 0; + audio->music_notes = 0; + audio->current_note = 0; + audio->current_note_loops = 0; + audio->background_beep = 1; + + + /* See if we have full background sound capability or not. */ + if (VBERROR_SUCCESS != VbExBeep(0,0)) { + VBDEBUG(("VbAudioOpen() - VbExBeep() is limited\n")); + audio->background_beep = 0; + } + + /* Prepare to generate audio/delay event. Use a short developer screen delay + * if indicated by GBB flags. + */ + if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 + && (gbb->flags & GBB_FLAG_DEV_SCREEN_SHORT_DELAY)) { + VBDEBUG(("VbAudioOpen() - using short developer screen delay\n")); + audio->music_notes = VbGetDevMusicNotes(&(audio->note_count), 1); + } else { + audio->music_notes = VbGetDevMusicNotes(&(audio->note_count), 0); + } + + VBDEBUG(("VbAudioOpen() - note count %d\n", audio->note_count)); + + return audio; +} + +/* Caller should loop without extra delay until this returns false */ +int VbAudioLooping(VbAudioContext* audio) { + + /* Time to play a note? */ + if (!audio->current_note_loops) { + VBDEBUG(("VbAudioLooping() - current_note is %d\n", audio->current_note)); + + /* Hooray, out of notes! */ + if (audio->current_note >= audio->note_count) + return 0; + + /* For how many loops do we hold this note? */ + audio->current_note_loops = + VbMsecToLoops(audio->music_notes[audio->current_note].msec); + VBDEBUG(("VbAudioLooping() - new current_note_loops == %d\n", + audio->current_note_loops)); + + if (audio->background_beep) { + + /* start (or stop) the sound */ + VbExBeep(0, audio->music_notes[audio->current_note].frequency); + + } else if (audio->music_notes[audio->current_note].frequency) { + + /* the sound will block, so don't loop repeatedly */ + audio->current_note_loops = 1; + VbExBeep(audio->music_notes[audio->current_note].msec, + audio->music_notes[audio->current_note].frequency); + } + + audio->current_note++; + } + + /* Wait a bit. Yes, one extra loop sometimes, but it's only 10msec */ + VbExSleepMs(DEV_LOOP_TIME); + + /* That's one... */ + if (audio->current_note_loops) + audio->current_note_loops--; + + return 1; +} + +/* Caller should call this prior to booting */ +void VbAudioClose(VbAudioContext* audio) { + + VbExBeep(0,0); + + /* Note: Free any allocated structs here */ +} diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c index 2853c863..c42795cd 100644 --- a/tests/vboot_api_devmode_tests.c +++ b/tests/vboot_api_devmode_tests.c @@ -113,11 +113,10 @@ test_case_t test[] = { { "VbBootDeveloperSoundTest( normal, background, Ctrl-U not allowed )", 0x00000000, VBERROR_SUCCESS, 21, 10000, // Ctrl-U at 10 seconds - 10, + 9, { {0, 0, 0}, // probing for capability {0, 0, 0}, // starts with no sound - {0, 0, 10000}, // sees Ctrl-U, turns sound off {120, 400, 10000}, // complains about Ctrl-U (one beep) // waits 120ms... {120, 400, 10240}, // complains about Ctrl-U (two beeps) |