Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/23072
Change subject: drvs/lenovo/h8: Morse death message ......................................................................
drvs/lenovo/h8: Morse death message
Add a morse generator and use it on Lenovo devices to beep the death message. Using a morse-to-text application like "Morse Tools" the message can be easily analysed using a mobile phone and helps a lot more than just flashing LEDs.
Signed-off-by: Patrick Rudolph siro@das-labor.org Change-Id: Iccf6a43a28d0eb515051b5be0a0f23d40e82c2d2 --- M src/console/die.c A src/drivers/generic/morse.h M src/ec/lenovo/h8/Kconfig M src/ec/lenovo/h8/panic.c M src/include/console/console.h 5 files changed, 124 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/72/23072/1
diff --git a/src/console/die.c b/src/console/die.c index 79babec..21fe99f 100644 --- a/src/console/die.c +++ b/src/console/die.c @@ -27,15 +27,16 @@ * EC is capable of controlling LEDs or a buzzer the method can be overwritten * in EC directory instead. */ -__attribute__ ((weak)) void die_notify(void) +__attribute__ ((weak)) void die_notify(const char *msg) { + (void)msg; }
/* Report a fatal error */ void NORETURN die(const char *msg) { printk(BIOS_EMERG, "%s", msg); - die_notify(); + die_notify(msg); halt(); } #endif diff --git a/src/drivers/generic/morse.h b/src/drivers/generic/morse.h new file mode 100644 index 0000000..4d25cb4 --- /dev/null +++ b/src/drivers/generic/morse.h @@ -0,0 +1,92 @@ +/*Morse.c + A crude hack to generate morse code in what should be a fairly OS + independent way, but which may in fact be completely non-portable. + + Author: Tom Russo + russo@swcp.com + + Copyright 1999, Thomas V. Russo, KM5VY, All rights reserved. + + You may freely distribute this software so long as you retain this notice + and provide a detailed description of any changes you might have made. + + This software provided with absolutely no warranty whatsoever. Use it if it + is useful, file it in your circular hacks file if not. +*/ +/* Define dahs and dits for the International Morse Code for letters, + numbers and punctuation/prosigns. */ +/* code is the letters [a-z], num is the numbers [0-9], punct is the rest */ + +#ifndef MORSE_ENCODER_H +#define MORSE_ENCODER_H + +#include <string.h> +#include <delay.h> + +/* + * Encodes one ASCII character as morse sign. + * Possible morse signs: + * * dit: '.' + * * dat: '-' + * * pause of one dit: ' ' + * + * After every sign there's a pause of one dit. + * Between two characters there's a pause of three dit. + * Whitespace is encoded as pause of four dit. + */ +static void encode_morse(const char c, const char **out) +{ + static const char *code[] = { ".-", "-...", "-.-.", "-..", ".", "..-.", + "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", + ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", + "-.--", "--.." }; + static const char *num[] = { "-----", ".----", "..---", "...--", + "....-", ".....", "-....", "--...", "---..", "----." }; + static const char *punct[] = { "-.-.-.", ".-.-.-", "---...", + "-.--.", "-.--.-", "-..-.", "--..--", ".-.-.-", "..--..", + "-...-", ".-.-.", "-.--.", "...-.-" }; + static const char punct_ascii[] = { ';', '.', ':', '(', ')', '/', + ',', '-', '?', '=', '+', '#', '$' }; + + if (c >= 'a' && c <= 'z') { + *out = code[c - 'a']; + } else if (c >= 'A' && c <= 'Z') { + *out = code[c - 'A']; + } else if (c >= '0' && c <= '9') { + *out = num[c - '0']; + } else if (c == ' ') { + *out = " "; + } else { + for (size_t i = 0; i < sizeof(punct_ascii); i++) { + if (punct_ascii[i] == c) { + *out = punct[i]; + return; + } + } + /* fall-back for unknown characters: '?' */ + *out = punct[8]; + } +} + +/* + * Beep the message using beep_morse as tone generator. + * beep_morse has to beep 3 * 125msec on longbeep and 125msec on short beep. + * beep_morse has to block for the time the beep is being played. + */ +static void panic_morse(const char *msg, void (*beep_morse)(u8 longbeep)) +{ + const char *enc; + + for (size_t i = 0; i < strlen(msg); i++) { + encode_morse(msg[i], &enc); + for (size_t j = 0; j < strlen(enc); j++) { + if (enc[j] == '-' || enc[j] == '.') + beep_morse(enc[j] == '-'); + mdelay(125); + } + mdelay(125 * 3); + } + delay(3); +} + +#endif /* MORSE_ENCODER_H */ diff --git a/src/ec/lenovo/h8/Kconfig b/src/ec/lenovo/h8/Kconfig index 190f4a9..5b1c209 100644 --- a/src/ec/lenovo/h8/Kconfig +++ b/src/ec/lenovo/h8/Kconfig @@ -21,6 +21,13 @@ help Flash all LEDs when encountered a fatal error.
+config H8_MORSE_DEATH + bool "Morse death message using beeps" + default n + depends on !H8_BEEP_ON_DEATH + help + Beep the fatal message using international MORSE code. + endif
config H8_DOCK_EARLY_INIT diff --git a/src/ec/lenovo/h8/panic.c b/src/ec/lenovo/h8/panic.c index fbe0dc0..b252510 100644 --- a/src/ec/lenovo/h8/panic.c +++ b/src/ec/lenovo/h8/panic.c @@ -14,10 +14,21 @@ */ #include <console/console.h> #include <ec/acpi/ec.h> +#include <drivers/generic/morse.h> +#include <delay.h>
#include "h8.h"
-static void h8_panic(void) +static void h8_beep_morse(u8 longbeep) +{ + for (size_t i = 0; i < (1 + longbeep * 2); i++) { + ec_write(H8_SOUND_REG, 11); + mdelay(125); + ec_write(H8_SOUND_REG, 0); + } +} + +static void h8_panic(const char *msg) { if (IS_ENABLED(CONFIG_H8_FLASH_LEDS_ON_DEATH)) { static const u8 leds[] = { @@ -43,9 +54,16 @@ ec_write(H8_SOUND_REPEAT, 1); ec_write(H8_SOUND_REG, 10); } + if (IS_ENABLED(CONFIG_H8_MORSE_DEATH)) { + ec_write(H8_SOUND_ENABLE1, 0x8); + ec_write(H8_SOUND_REPEAT, 1); + while (1) { + panic_morse(msg, h8_beep_morse); + }; + } }
-void die_notify(void) +void die_notify(const char *msg) { - h8_panic(); + h8_panic(msg); } diff --git a/src/include/console/console.h b/src/include/console/console.h index aa935e4..98973c3 100644 --- a/src/include/console/console.h +++ b/src/include/console/console.h @@ -46,7 +46,7 @@ * This function is weak and can be overridden to provide additional * feedback to the user. Possible use case: Play a beep. */ -void die_notify(void); +void die_notify(const char *msg);
#define __CONSOLE_ENABLE__ \ ((ENV_BOOTBLOCK && IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) || \