Skip to content

Commit 85d2f13

Browse files
medhefgobluca
authored andcommitted
boot: Add PC speaker support
Fixes: systemd#17508
1 parent 8a592c6 commit 85d2f13

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

man/loader.conf.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@
196196
by using the <keycap>f</keycap> key.</para></listitem>
197197
</varlistentry>
198198

199+
<varlistentry>
200+
<term>beep</term>
201+
202+
<listitem><para>Beep once as soon as the boot menu is shown (default disabled). Currently,
203+
only x86 is supported, where it uses the PC speaker.</para></listitem>
204+
</varlistentry>
205+
199206
<varlistentry>
200207
<term>reboot-for-bitlocker</term>
201208

src/boot/efi/boot.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ typedef struct {
8989
BOOLEAN force_menu;
9090
BOOLEAN use_saved_entry;
9191
BOOLEAN use_saved_entry_efivar;
92+
BOOLEAN beep;
9293
INT64 console_mode;
9394
INT64 console_mode_efivar;
9495
RandomSeedMode random_seed_mode;
@@ -497,6 +498,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
497498
ps_bool(L" editor: %s\n", config->editor);
498499
ps_bool(L" auto-entries: %s\n", config->auto_entries);
499500
ps_bool(L" auto-firmware: %s\n", config->auto_firmware);
501+
ps_bool(L" beep: %s\n", config->beep);
500502
ps_bool(L" reboot-for-bitlocker: %s\n", config->reboot_for_bitlocker);
501503
ps_string(L" random-seed-mode: %s\n", random_seed_modes_table[config->random_seed_mode]);
502504

@@ -588,7 +590,7 @@ static BOOLEAN menu_run(
588590
_cleanup_freepool_ CHAR16 *clearline = NULL, *status = NULL;
589591
UINT32 timeout_efivar_saved = config->timeout_sec_efivar;
590592
UINT32 timeout_remain = config->timeout_sec == TIMEOUT_MENU_FORCE ? 0 : config->timeout_sec;
591-
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE;
593+
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE, do_beep = config->beep;
592594
INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar;
593595
UINTN default_efivar_saved = config->idx_default_efivar;
594596

@@ -725,6 +727,11 @@ static BOOLEAN menu_run(
725727
ST->ConOut->OutputString(ST->ConOut, clearline + 1 + x + len);
726728
}
727729

730+
if (do_beep) {
731+
beep();
732+
do_beep = FALSE;
733+
}
734+
728735
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : UINT64_MAX);
729736
if (err == EFI_TIMEOUT) {
730737
timeout_remain--;
@@ -1144,6 +1151,12 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) {
11441151
continue;
11451152
}
11461153

1154+
if (strcmpa((CHAR8 *)"beep", key) == 0) {
1155+
err = parse_boolean(value, &config->beep);
1156+
if (EFI_ERROR(err))
1157+
log_error_stall(L"Error parsing 'beep' config option: %a", value);
1158+
}
1159+
11471160
if (strcmpa((CHAR8 *)"reboot-for-bitlocker", key) == 0) {
11481161
err = parse_boolean(value, &config->reboot_for_bitlocker);
11491162
if (EFI_ERROR(err))

src/boot/efi/util.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,3 +757,46 @@ __attribute__((noinline)) void debug_break(void) {
757757
#endif
758758
}
759759
#endif
760+
761+
#if defined(__i386__) || defined(__x86_64__)
762+
static inline UINT8 inb(UINT16 port) {
763+
UINT8 value;
764+
asm volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
765+
return value;
766+
}
767+
768+
static inline void outb(UINT16 port, UINT8 value) {
769+
asm volatile("outb %0, %1" : : "a"(value), "Nd"(port));
770+
}
771+
772+
void beep(void) {
773+
enum {
774+
PITCH = 500,
775+
DURATION_USEC = 100 * 1000,
776+
777+
PIT_FREQUENCY = 0x1234dd,
778+
SPEAKER_CONTROL_PORT = 0x61,
779+
SPEAKER_ON_MASK = 0x03,
780+
TIMER_PORT_MAGIC = 0xB6,
781+
TIMER_CONTROL_PORT = 0x43,
782+
TIMER_CONTROL2_PORT = 0x42,
783+
};
784+
785+
/* Set frequency. */
786+
UINT32 counter = PIT_FREQUENCY / PITCH;
787+
outb(TIMER_CONTROL_PORT, TIMER_PORT_MAGIC);
788+
outb(TIMER_CONTROL2_PORT, counter & 0xFF);
789+
outb(TIMER_CONTROL2_PORT, (counter >> 8) & 0xFF);
790+
791+
/* Turn speaker on. */
792+
UINT8 value = inb(SPEAKER_CONTROL_PORT);
793+
value |= SPEAKER_ON_MASK;
794+
outb(SPEAKER_CONTROL_PORT, value);
795+
796+
BS->Stall(DURATION_USEC);
797+
798+
/* Turn speaker off. */
799+
value &= ~SPEAKER_ON_MASK;
800+
outb(SPEAKER_CONTROL_PORT, value);
801+
}
802+
#endif

src/boot/efi/util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,9 @@ extern UINT8 _text, _data;
169169
#else
170170
# define debug_hook(identity)
171171
#endif
172+
173+
#if defined(__i386__) || defined(__x86_64__)
174+
void beep(void);
175+
#else
176+
static inline void beep(void) {}
177+
#endif

0 commit comments

Comments
 (0)