2.5.59 morse code panics
PATCH 1/1 2.5.59 morse code panics
Here's the initial port of Andrew Rodland's morse code panics to 2.5. It's probably got a few issues that need to be sorted out:
at least the acquisition of the atkbd handle is a shameful hack. The original regular blinking code from ac has been removed, because it's no use when we've got morse about. :)
Any comments appreciated, patch against 2.5.59.
Signature · 237 lines
Tomas Szepe <[email protected]> diff -urN a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- a/drivers/input/keyboard/atkbd.c 2002-12-08 20:06:16.000000000 +0100 +++ b/drivers/input/keyboard/atkbd.c 2003-01-30 15:19:50.000000000 +0100 @@ -445,6 +445,23 @@ atkbd_command(atkbd, &atkbd->oldset, ATKBD_CMD_SSCANSET); } +#ifdef CONFIG_MORSE_PANICS +static struct atkbd *atkbd_blinkdev = NULL; +int atkbd_blink(char led) { + char param[2] = "\0\0"; + led = led ? (0x01 | 0x04) : 0x00; + *param = led; + + if (atkbd_blinkdev == NULL) + return -1; + + if (atkbd_command(atkbd_blinkdev, param, ATKBD_CMD_SETLEDS)) + return -1; + + return 0; +} +#endif + /* * atkbd_disconnect() closes and frees. */ @@ -543,11 +560,12 @@ set_bit(atkbd->keycode[i], atkbd->dev.keybit); input_register_device(&atkbd->dev); - +#ifdef CONFIG_MORSE_PANICS + atkbd_blinkdev = atkbd; +#endif printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys); } - static struct serio_dev atkbd_dev = { .interrupt = atkbd_interrupt, .connect = atkbd_connect, diff -urN a/init/Kconfig b/init/Kconfig --- a/init/Kconfig 2003-01-17 04:27:10.000000000 +0100 +++ b/init/Kconfig 2003-01-30 15:15:56.000000000 +0100 @@ -98,6 +98,17 @@ 13 => 8 KB 12 => 4 KB +config MORSE_PANICS + bool "Morse code panics" + depends on KEYBOARD_ATKBD || VT + help + When enabled, this code will make a panicking kernel scream for + help in morse code, signalling on the leds of a possibly attached + AT keyboard and/or a bleeper. You can enable/disable your morse + output devices of choice using the "panicmorse" kernel boot + parameter. + If unsure, say Y. + endmenu @@ -159,4 +170,3 @@ in <file:Documentation/kmod.txt>. endmenu - diff -urN a/kernel/panic.c b/kernel/panic.c --- a/kernel/panic.c 2003-01-09 14:25:40.000000000 +0100 +++ b/kernel/panic.c 2003-01-30 15:46:11.000000000 +0100 @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/sysrq.h> #include <linux/interrupt.h> +#include <linux/vt_kern.h> asmlinkage void sys_sync(void); /* it's really int */ @@ -31,6 +32,142 @@ __setup("panic=", panic_setup); +#ifdef CONFIG_MORSE_PANICS + +#ifdef CONFIG_KEYBOARD_ATKBD + extern int atkbd_blink(char led); /* drivers/input/keyboards/atkbd.c */ + #define do_blink(x) atkbd_blink(x) +#else + #define do_blink(x) 0 +#endif + +static int morse_setting = 1; + +static const unsigned char morsetable[] = { + 0122, 0, 0310, 0, 0, 0163, /* "#$%&' */ + 055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */ + 077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */ + 0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */ + 006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */ + 036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */ + 010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */ + 0, 0, 0, 0, 0154 /* [\]^_ */ +}; + +static inline unsigned char tomorse(char c) { + if (c >= 'a' && c <= 'z') + c = c - 'a' + 'A'; + if (c >= '"' && c <= '_') { + return morsetable[c - '"']; + } else + return 0; +} + +#define DITLEN (HZ / 5) +#define DAHLEN (3 * DITLEN) +#define SPACELEN (7 * DITLEN) + +#define FREQ 844 + +/* Tell the user who may be running in X and not see the console that + * we have panic'd. This is to distingush panics from "real lockups." + * Could in theory send the panic message as morse, but that is left + * as an exercise for the reader. + * + * And now it's done! LED and speaker morse code by Andrew Rodland + * <[email protected]>, with improvements based on suggestions from + * [email protected] and a host of others. + * + * Initial 2.5 morsepanics port by Tomas Szepe <[email protected]>, + * January 2003. + */ +void panic_morseblink(char *buf) +{ + static unsigned long next_jiffie = 0; + static char * bufpos = 0; + static unsigned char morse = 0; + static char state = 1; + + if (!morse_setting) + return; + + if (!buf) + buf = "Uh oh, we lost the panic msg."; + + /* Waiting for something? */ + if (bufpos && time_after(next_jiffie, jiffies)) + return; + + if (state) { /* Coming off of a blink. */ + if (morse_setting & 0x01) + do_blink(0); + + state = 0; + + if (morse > 1) { + /* Not done yet, just a one-dit pause. */ + next_jiffie = jiffies + DITLEN; + } else { + /* Get a new char, figure out how much space. */ + + /* First time through */ + if (!bufpos) + bufpos = (char *) buf; + + if (!*bufpos) { + /* Repeating */ + bufpos = (char *) buf; + next_jiffie = jiffies + SPACELEN; + } else { + /* Inter-letter space */ + next_jiffie = jiffies + DAHLEN; + } + + if (!(morse = tomorse(*bufpos))) { + next_jiffie = jiffies + SPACELEN; + state = 1; /* And get us back here */ + } + bufpos++; + } + } else { + /* Starting a new blink. We have a valid code in morse. */ + int len; + + len = (morse & 001) ? DAHLEN : DITLEN; + +#ifdef CONFIG_VT + if (morse_setting & 0x02) + kd_mksound(FREQ, len); +#endif + + next_jiffie = jiffies + len; + + if (morse_setting & 0x01) + do_blink(1); + + state = 1; + morse >>= 1; + } +} + +static int __init panicmorse_setup(char *str) +{ + int par; + if (get_option(&str, &par)) + morse_setting = par; + return 1; +} + +/* "panicmorse=0" disables the blinking as it caused problems with + * certain console switches. + * + * "panicmorse | 1" does the show using kbd leds. + * "panicmorse | 2" throws in bleeping via kd_mksound(). + */ +__setup("panicmorse=", panicmorse_setup); + +#endif /* CONFIG_MORSE_PANICS */ + /** * panic - halt the system * @fmt: The text string to print @@ -95,7 +232,10 @@ disabled_wait(caller); #endif local_irq_enable(); - for(;;) { + for (;;) { +#if defined(CONFIG_MORSE_PANICS) + panic_morseblink(buf); +#endif CHECK_EMERGENCY_SYNC } }
Quoted 7 lines · Tomas Szepe
Here's the initial port of Andrew Rodland's morse code panics to 2.5. It's probably got a few issues that need to be sorted out:
at least the acquisition of the atkbd handle is a shameful hack. The original regular blinking code from ac has been removed, because it's no use when we've got morse about. :)Any comments appreciated, patch against 2.5.59.
I forwarded Linus a copy of Andi Kleens original 'blink leds on panic' patch circa 2.5.3 or so. He rejected it due to not wanting PC-isms in kernel/
As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.
Dave
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
Quoted 3 lines · Dave Jones
As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.
If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want morse_ops 8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)
Quoted 8 lines
Quoted 3 lines · Dave Jones
As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.
Quoted 7 lines
If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want
morse_ops8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)
Of course we want morseops. :)
v2 follows.
Signature · 284 lines
Tomas Szepe <[email protected]> drivers/input/keyboard/atkbd.c | 22 +++++- include/linux/morseops.h | 26 +++++++ init/Kconfig | 14 +++- kernel/Makefile | 1 kernel/morse.c | 137 +++++++++++++++++++++++++++++++++++++++++ kernel/panic.c | 4 - 6 files changed, 200 insertions(+), 4 deletions(-) diff -urN b/drivers/input/keyboard/atkbd.c a/drivers/input/keyboard/atkbd.c --- b/drivers/input/keyboard/atkbd.c 2002-12-08 20:06:16.000000000 +0100 +++ a/drivers/input/keyboard/atkbd.c 2003-01-31 10:20:56.000000000 +0100 @@ -445,6 +445,23 @@ atkbd_command(atkbd, &atkbd->oldset, ATKBD_CMD_SSCANSET); } +#ifdef CONFIG_MORSE_PANICS +static struct atkbd *atkbd_blinkdev = NULL; +int atkbd_blink(char led) { + char param[2] = "\0\0"; + led = led ? (0x01 | 0x04) : 0x00; + *param = led; + + if (atkbd_blinkdev == NULL) + return -1; + + if (atkbd_command(atkbd_blinkdev, param, ATKBD_CMD_SETLEDS)) + return -1; + + return 0; +} +#endif + /* * atkbd_disconnect() closes and frees. */ @@ -543,11 +560,12 @@ set_bit(atkbd->keycode[i], atkbd->dev.keybit); input_register_device(&atkbd->dev); - +#ifdef CONFIG_MORSE_PANICS + atkbd_blinkdev = atkbd; +#endif printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys); } - static struct serio_dev atkbd_dev = { .interrupt = atkbd_interrupt, .connect = atkbd_connect, diff -urN b/include/linux/morseops.h a/include/linux/morseops.h --- b/include/linux/morseops.h 1970-01-01 01:00:00.000000000 +0100 +++ a/include/linux/morseops.h 2003-01-31 11:20:05.000000000 +0100 @@ -0,0 +1,26 @@ +/* Yes, it's morse code ops indeed. */ + +#ifndef _LINUX_MORSEOPS_H +#define _LINUX_MORSEOPS_H + +#include <linux/config.h> + +#if defined(CONFIG_MORSE_PANICS) + +extern const unsigned char morsetable[]; /* in kernel/morse.c */ +void panic_morseblink(char *buf); /* in kernel/morse.c */ + +static inline unsigned char tomorse(char c) { + if (c >= 'a' && c <= 'z') + c = c - 'a' + 'A'; + if (c >= '"' && c <= '_') { + return morsetable[c - '"']; + } else + return 0; +} + +#else /* CONFIG_MORSE_PANICS */ + #define panic_morseblink(buf) +#endif /* CONFIG_MORSE_PANICS */ + +#endif /* _LINUX_MORSEOPS_H */ diff -urN b/init/Kconfig a/init/Kconfig --- b/init/Kconfig 2003-01-17 04:27:43.000000000 +0100 +++ a/init/Kconfig 2003-01-31 11:06:31.000000000 +0100 @@ -98,6 +98,19 @@ 13 => 8 KB 12 => 4 KB +config MORSE_PANICS + bool "Morse code panics" + depends on KEYBOARD_ATKBD || VT + help + When enabled, this code will make a panicking kernel cry for + help in morse code, signalling on the leds of a possibly attached + AT keyboard and/or a bleeper. You can enable/disable your morse + output devices of choice using the "panicmorse" kernel boot + parameter. + + If unsure, say Y. This feature is very helpful for those who + spend most of their time in X. + endmenu @@ -159,4 +172,3 @@ in <file:Documentation/kmod.txt>. endmenu - diff -urN b/kernel/Makefile a/kernel/Makefile --- b/kernel/Makefile 2003-01-09 10:59:41.000000000 +0100 +++ a/kernel/Makefile 2003-01-31 10:28:04.000000000 +0100 @@ -22,6 +22,7 @@ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj-$(CONFIG_COMPAT) += compat.o +obj-$(CONFIG_MORSE_PANICS) += morse.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is diff -urN b/kernel/morse.c a/kernel/morse.c --- b/kernel/morse.c 1970-01-01 01:00:00.000000000 +0100 +++ a/kernel/morse.c 2003-01-31 11:19:54.000000000 +0100 @@ -0,0 +1,137 @@ +/* + * kernel/morse.c + * + * Copyright (C) 2002 Andrew Rodland <[email protected]> + * Copyright (C) 2003 Tomas Szepe <[email protected]> + * + * Tell the user who may be running in X and not see the console that + * we have panic'd. This is to distingush panics from "real lockups." + * Could in theory send the panic message as morse, but that is left + * as an exercise for the reader. + * + * And now it's done! LED and speaker morse code by Andrew Rodland + * <[email protected]>, with improvements based on suggestions from + * [email protected] and a host of others. + * + * Initial 2.5 morsepanics port and cleanup by + * Tomas Szepe <[email protected]>, January 2003. + */ + +#include <linux/config.h> +#include <linux/morseops.h> +#include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/vt_kern.h> + +#define DITLEN (HZ / 5) +#define DAHLEN (3 * DITLEN) +#define SPACELEN (7 * DITLEN) +#define FREQ 844 + +/* Only blink by default if AT keyboard is available, + * go for beeping if it isn't. + */ +#ifdef CONFIG_KEYBOARD_ATKBD +extern int atkbd_blink(char led); /* drivers/input/keyboards/atkbd.c */ +#define do_blink(x) atkbd_blink(x) +static int morse_setting = 1; +#else +#define do_blink(x) +static int morse_setting = 2; +#endif + +const unsigned char morsetable[] = { + 0122, 0, 0310, 0, 0, 0163, /* "#$%&' */ + 055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */ + 077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */ + 0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */ + 006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */ + 036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */ + 010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */ + 0, 0, 0, 0, 0154 /* [\]^_ */ +}; + +void panic_morseblink(char *buf) +{ + static unsigned long next_jiffie = 0; + static char * bufpos = 0; + static unsigned char morse = 0; + static char state = 1; + + if (!morse_setting) + return; + + if (!buf) + buf = "Uh oh, we lost the panic msg."; + + /* Waiting for something? */ + if (bufpos && time_after(next_jiffie, jiffies)) + return; + + if (state) { /* Coming off of a blink. */ + if (morse_setting & 0x01) + do_blink(0); + + state = 0; + + if (morse > 1) { + /* Not done yet, just a one-dit pause. */ + next_jiffie = jiffies + DITLEN; + } else { + /* Get a new char, figure out how much space. */ + + /* First time through */ + if (!bufpos) + bufpos = (char *) buf; + + if (!*bufpos) { + /* Repeating */ + bufpos = (char *) buf; + next_jiffie = jiffies + SPACELEN; + } else { + /* Inter-letter space */ + next_jiffie = jiffies + DAHLEN; + } + + if (!(morse = tomorse(*bufpos))) { + next_jiffie = jiffies + SPACELEN; + state = 1; /* And get us back here */ + } + bufpos++; + } + } else { + /* Starting a new blink. We have a valid code in morse. */ + int len; + + len = (morse & 001) ? DAHLEN : DITLEN; + +#ifdef CONFIG_VT + if (morse_setting & 0x02) + kd_mksound(FREQ, len); +#endif + + next_jiffie = jiffies + len; + + if (morse_setting & 0x01) + do_blink(1); + + state = 1; + morse >>= 1; + } +} + +static int __init panicmorse_setup(char *str) +{ + int par; + if (get_option(&str, &par)) + morse_setting = par; + return 1; +} + +/* "panicmorse=0" disables the blinking as it caused problems with + * certain console switches. + * + * "panicmorse | 1" does the show using kbd leds. + * "panicmorse | 2" throws in bleeping via kd_mksound(). + */ +__setup("panicmorse=", panicmorse_setup); diff -urN b/kernel/panic.c a/kernel/panic.c --- b/kernel/panic.c 2003-01-09 10:59:41.000000000 +0100 +++ a/kernel/panic.c 2003-01-31 10:36:50.000000000 +0100 @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/sysrq.h> #include <linux/interrupt.h> +#include <linux/morseops.h> asmlinkage void sys_sync(void); /* it's really int */ @@ -95,7 +96,8 @@ disabled_wait(caller); #endif local_irq_enable(); - for(;;) { + for (;;) { + panic_morseblink(buf); CHECK_EMERGENCY_SYNC } }
Quoted 11 lines
Quoted 11 lines
Quoted 3 lines
As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.
If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want
morse_ops8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)
Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box. The PC speaker may well be too quiet to do that. It should be fairly straightforward to get a simple bleep out of any card that implements the Adlib registers.
John.
Quoted 4 lines · John Bradford
Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box.
Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).
Dave
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
Quoted 3 lines · Dave Jones
Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).
A lot of newer laptops do not have serial ports. While morse code may be a little silly the general purpose hook it needs to be done cleanly is considerably more useful
Quoted 3 lines
A lot of newer laptops do not have serial ports. While morse code may be a little silly the general purpose hook it needs to be done cleanly is considerably more useful
Exactly.
The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.
John.
Quoted 7 lines · John Bradford
The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.
That must be a pretty quiet datacentre. And what happens when more than one box starts beeping ?
Dave
Signature · 1 line
| Dave Jones. http://www.codemonkey.org.uk
Quoted 1 line · Alan Cox
A lot of newer laptops do not have serial ports.
so use something sensible like a crashdump to floppy.
Quoted 3 lines
While morse code may
be a little silly the general purpose hook it needs to be done cleanly is considerably more useful
sure. things like lkcd,netconsole etc could all use that
infrastructure. The beyond-silly bit was the 'other machine
to decode morse' argument.
Dave
Signature · 1 line
| Dave Jones. http://www.codemonkey.org.uk
Quoted 3 lines
Quoted 1 line
A lot of newer laptops do not have serial ports.
so use something sensible like a crashdump to floppy.
A lot of newer laptops do not have floppy drives :-)
Seriously, though, I agree that morse isn't the most ideal way to get data out of a crashed system.
Quoted 7 lines
Quoted 3 lines
While morse code may
be a little silly the general purpose hook it needs to be done cleanly is considerably more usefulsure. things like lkcd,netconsole etc could all use that
infrastructure. The beyond-silly bit was the 'other machine
to decode morse' argument.
Depends on how good your morse is, I suppose, I wouldn't really want to decode a oops from morse by ear.
Quoted 10 lines
Quoted 7 lines
The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.
That must be a pretty quiet datacentre. And what happens when more than one box starts beeping ?
OK, point taken, that *was* a beyond-silly suggestion :-)
John.
Quoted 3 lines · Dave Jones
Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).
There's a classic Monty Python skit where John Cleese is organizing an expedition to build a bridge between the two peaks of Mt Kilamanjaro.
I have to do most of my kernel hacking at home, on my own time. So I'm sitting there with a laptop and no second machine. Now, if the intent is to say "Don't bother doing anything that might require debugging unless you can afford 2 machines", that's OK - but let's be open about that requirement. And has been pointed out, some laptops don't even *HAVE* a serial port.
There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.
Signature · 3 lines
Valdis Kletnieks Computer Systems Senior Engineer Virginia Tech
Quoted 3 lines
There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.
By the way, you can buy cards with LED displays on which monitor port 80h, and tell you how far through the boot process a box is getting. Not much use on a laptop, though :-).
John.
Quoted 5 lines · On Fri, Jan 31, 2003 at 09:40:27AM -0500, [email protected] wrote:
I have to do most of my kernel hacking at home, on my own time. So I'm sitting there with a laptop and no second machine. Now, if the intent is to say "Don't bother doing anything that might require debugging unless you can afford 2 machines", that's OK - but let's be open about that requirement. And has been pointed out, some laptops don't even *HAVE* a serial port.
So go see Ingo's netconsole. (Which admittedly only supports certain net drivers). Or one of the crashdump facilities. All of which is far more reliable and useful than sitting there with a microphone.
Quoted 3 lines
There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.
There's no reason to trust morse panic output more than console output. If something has scribbled over kernel space memory, you're screwed anyway. It's hit or miss whether your panic-method-de-jour has been stomped on.
Dave
Signature · 1 line
| Dave Jones. http://www.codemonkey.org.uk
Quoted 3 lines · Dave Jones
So go see Ingo's netconsole. (Which admittedly only supports certain net drivers). Or one of the crashdump facilities. All of which is far more reliable and useful than sitting there with a microphone.
If I don't have a second box to run a serial cable to, I probably don't have a second box to run cat5 to, so netconsole probably doesn't do me any good.
crashdump might be usable, I'll have to look...
Quoted 4 lines
There's no reason to trust morse panic output more than console output. If something has scribbled over kernel space memory, you're screwed anyway. It's hit or miss whether your panic-method-de-jour has been stomped on.
The real solution is probably to get Ingo's netconsole, the morse-panic patch, the current serial-console support, and abstract it all into some infrastructure with output hooks - netconsole, serial, morse, whatever.
But we're alledgedly in a feature freeze, so that's a 2.7-ish I guess...
Signature · 3 lines
Valdis Kletnieks Computer Systems Senior Engineer Virginia Tech
Quoted 4 lines · John Bradford
Quoted 4 lines
Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box.
And Dave Jones replied:
Quoted 3 lines
Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).
Oh, come now, Dave; be nice! This is fun stuff.
A voice synthesizer would be even better than morse code.
"I'm sorry Dave. I can't boot."
Think Hal 9000, from 2001/2010! The kernel could detect a sound card at boot, and then tell us what broke. Very 22nd century, if you ask me.
If sound is broken or nonexistent, we could fall back to Morse! Or electric shocks via a serial connection! The possibilities are endless.
...Scott (Who thinks people here are much too serious sometimes)
Quoted 5 lines · Alan Cox
Quoted 3 lines · Dave Jones
As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.
Quoted 7 lines
If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want
morse_ops8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)
It should be in the keyboard.c file, using input_event() to blink the LEDs. This way it'll work on all archs in 2.5.
I will not accept it as a patch for atkbd.c, unless there is a strong reason to do it there.
Signature · 2 lines
Vojtech Pavlik SuSE Labs
Quoted 4 lines
It should be in the
keyboard.cfile, usinginput_event()to blink the LEDs. This way it'll work on all archs in 2.5.
Oh, thanks for pointing this out, Vojtech, I'll certainly fix it.
Signature · 1 line
Tomas Szepe <[email protected]>
Quoted 4 lines
It should be in the
keyboard.cfile, usinginput_event()to blink the LEDs. This way it'll work on all archs in 2.5.
This change
a) allows for other cleanups, too.
b) probably makes the gazillion leds on sparc keyboards blink. EVIL!!
So here's v3.
Signature · 273 lines
Tomas Szepe <[email protected]> drivers/char/keyboard.c | 21 +++++++ include/linux/morseops.h | 26 +++++++++ include/linux/vt_kern.h | 3 + init/Kconfig | 15 +++++ kernel/Makefile | 1 kernel/morse.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/panic.c | 4 + 7 files changed, 194 insertions(+), 1 deletion(-) diff -urN a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c 2002-12-16 07:01:47.000000000 +0100 +++ b/drivers/char/keyboard.c 2003-01-31 20:24:33.000000000 +0100 @@ -262,6 +262,27 @@ } /* + * Turn all possible leds on or off. + */ +void kd_turn_all_leds(int on_or_off) +{ + struct list_head *node; + on_or_off = on_or_off ? 1 : 0; + + list_for_each(node, &kbd_handler.h_list) { + struct input_handle *handle = to_handle_h(node); + if (test_bit(EV_LED, handle->dev->evbit)) { + int led; + for (led = 0; led <= LED_MAX; led++) { + if (test_bit(led, handle->dev->ledbit)) + input_event(handle->dev, EV_LED, led, + on_or_off); + } + } + } +} + +/* * Setting the keyboard rate. */ static inline unsigned int ms_to_jiffies(unsigned int ms) { diff -urN a/include/linux/morseops.h b/include/linux/morseops.h --- a/include/linux/morseops.h 1970-01-01 01:00:00.000000000 +0100 +++ b/include/linux/morseops.h 2003-01-31 20:24:33.000000000 +0100 @@ -0,0 +1,26 @@ +/* Yes, it's morse code ops indeed. */ + +#ifndef _LINUX_MORSEOPS_H +#define _LINUX_MORSEOPS_H + +#include <linux/config.h> + +#if defined(CONFIG_MORSE_PANICS) + +extern const unsigned char morsetable[]; /* in kernel/morse.c */ +void panic_morseblink(char *buf); /* in kernel/morse.c */ + +static inline unsigned char tomorse(char c) { + if (c >= 'a' && c <= 'z') + c = c - 'a' + 'A'; + if (c >= '"' && c <= '_') { + return morsetable[c - '"']; + } else + return 0; +} + +#else /* CONFIG_MORSE_PANICS */ + #define panic_morseblink(buf) +#endif /* CONFIG_MORSE_PANICS */ + +#endif /* _LINUX_MORSEOPS_H */ diff -urN a/include/linux/vt_kern.h b/include/linux/vt_kern.h --- a/include/linux/vt_kern.h 2002-12-16 07:01:55.000000000 +0100 +++ b/include/linux/vt_kern.h 2003-01-31 20:24:33.000000000 +0100 @@ -33,7 +33,10 @@ wait_queue_head_t paste_wait; } *vt_cons[MAX_NR_CONSOLES]; +/* keyboard.c */ + extern void kd_mksound(unsigned int hz, unsigned int ticks); +extern void kd_turn_all_leds(int on_or_off); extern int kbd_rate(struct kbd_repeat *rep); /* console.c */ diff -urN a/init/Kconfig b/init/Kconfig --- a/init/Kconfig 2003-01-17 04:27:10.000000000 +0100 +++ b/init/Kconfig 2003-01-31 20:24:33.000000000 +0100 @@ -98,6 +98,21 @@ 13 => 8 KB 12 => 4 KB +config MORSE_PANICS + bool "Morse code panics" + depends on VT + help + When enabled, this code will make a panicking kernel cry for + help in morse code, signalling on the leds of a possibly attached + keyboard and/or a bleeper. You can enable/disable your morse + output devices of choice using the "panicmorse" kernel boot + parameter. Currently, "panicmorse=0" will disable the signalling + completely, "panicmorse=1" (the default) will only blink the leds, + "panicmorse=2" will only beep, and "panicmorse=3" will do both. + + If unsure, say Y. This feature is very helpful for those who + spend most of their time in X. + endmenu diff -urN a/kernel/Makefile b/kernel/Makefile --- a/kernel/Makefile 2003-01-09 14:25:40.000000000 +0100 +++ b/kernel/Makefile 2003-01-31 20:24:33.000000000 +0100 @@ -22,6 +22,7 @@ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj-$(CONFIG_COMPAT) += compat.o +obj-$(CONFIG_MORSE_PANICS) += morse.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is diff -urN a/kernel/morse.c b/kernel/morse.c --- a/kernel/morse.c 1970-01-01 01:00:00.000000000 +0100 +++ b/kernel/morse.c 2003-01-31 20:24:33.000000000 +0100 @@ -0,0 +1,125 @@ +/* + * kernel/morse.c + * + * Copyright (C) 2002 Andrew Rodland <[email protected]> + * Copyright (C) 2003 Tomas Szepe <[email protected]> + * + * Tell the user who may be running in X and not see the console that + * we have panic'd. This is to distingush panics from "real lockups." + * Could in theory send the panic message as morse, but that is left + * as an exercise for the reader. + * + * And now it's done! LED and speaker morse code by Andrew Rodland + * <[email protected]>, with improvements based on suggestions from + * [email protected] and a host of others. + * + * Initial 2.5 morsepanics port and cleanup by + * Tomas Szepe <[email protected]>, January 2003. + */ + +#include <linux/config.h> +#include <linux/morseops.h> +#include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/vt_kern.h> + +#define DITLEN (HZ / 5) +#define DAHLEN (3 * DITLEN) +#define SPACELEN (7 * DITLEN) +#define FREQ 844 + +static int morse_setting = 1; + +const unsigned char morsetable[] = { + 0122, 0, 0310, 0, 0, 0163, /* "#$%&' */ + 055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */ + 077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */ + 0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */ + 006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */ + 036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */ + 010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */ + 0, 0, 0, 0, 0154 /* [\]^_ */ +}; + +void panic_morseblink(char *buf) +{ + static unsigned long next_jiffie = 0; + static char * bufpos = 0; + static unsigned char morse = 0; + static char state = 1; + + if (!morse_setting) + return; + + if (!buf) + buf = "Uh oh, we lost the panic msg."; + + /* Waiting for something? */ + if (bufpos && time_after(next_jiffie, jiffies)) + return; + + if (state) { /* Coming off of a blink. */ + if (morse_setting & 0x01) + kd_turn_all_leds(0); + + state = 0; + + if (morse > 1) { + /* Not done yet, just a one-dit pause. */ + next_jiffie = jiffies + DITLEN; + } else { + /* Get a new char, figure out how much space. */ + + /* First time through */ + if (!bufpos) + bufpos = (char *) buf; + + if (!*bufpos) { + /* Repeating */ + bufpos = (char *) buf; + next_jiffie = jiffies + SPACELEN; + } else { + /* Inter-letter space */ + next_jiffie = jiffies + DAHLEN; + } + + if (!(morse = tomorse(*bufpos))) { + next_jiffie = jiffies + SPACELEN; + state = 1; /* And get us back here */ + } + bufpos++; + } + } else { + /* Starting a new blink. We have a valid code in morse. */ + int len; + + len = (morse & 001) ? DAHLEN : DITLEN; + + if (morse_setting & 0x02) + kd_mksound(FREQ, len); + + next_jiffie = jiffies + len; + + if (morse_setting & 0x01) + kd_turn_all_leds(1); + + state = 1; + morse >>= 1; + } +} + +static int __init panicmorse_setup(char *str) +{ + int par; + if (get_option(&str, &par)) + morse_setting = par; + return 1; +} + +/* "panicmorse=0" disables the blinking as it caused problems with + * certain console switches. + * + * "panicmorse | 1" does the show using kbd leds. + * "panicmorse | 2" throws in bleeping via kd_mksound(). + */ +__setup("panicmorse=", panicmorse_setup); diff -urN a/kernel/panic.c b/kernel/panic.c --- a/kernel/panic.c 2003-01-09 14:25:40.000000000 +0100 +++ b/kernel/panic.c 2003-01-31 20:24:33.000000000 +0100 @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/sysrq.h> #include <linux/interrupt.h> +#include <linux/morseops.h> asmlinkage void sys_sync(void); /* it's really int */ @@ -95,7 +96,8 @@ disabled_wait(caller); #endif local_irq_enable(); - for(;;) { + for (;;) { + panic_morseblink(buf); CHECK_EMERGENCY_SYNC } }