aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/shadow_console.c
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-07-06 10:53:19 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:31:43 -0400
commit3f871feaf3390c6d6e578818f867917c2e4738a2 (patch)
tree3b7ebc72793903361bb4b108bd829b21ede3fc01 /arch/blackfin/kernel/shadow_console.c
parent53e18df745b6f833df07ead62ded09ebae3b0303 (diff)
Blackfin: add an early shadow console
Add a memory based shadow console to keep a copy of the printk buffer in a location which can be found externally. This allows bootloaders to locate and utilize the log buffer in case of silent (early/resume/etc...) crashes. Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/shadow_console.c')
-rw-r--r--arch/blackfin/kernel/shadow_console.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c
new file mode 100644
index 000000000000..15819ff10573
--- /dev/null
+++ b/arch/blackfin/kernel/shadow_console.c
@@ -0,0 +1,78 @@
1/*
2 * manage a small early shadow of the log buffer which we can pass between the
3 * bootloader so early crash messages are communicated properly and easily
4 *
5 * Copyright 2009 Analog Devices Inc.
6 *
7 * Enter bugs at http://blackfin.uclinux.org/
8 *
9 * Licensed under the GPL-2 or later.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/console.h>
15#include <linux/string.h>
16#include <asm/blackfin.h>
17#include <asm/irq_handler.h>
18#include <asm/early_printk.h>
19
20#define SHADOW_CONSOLE_START (0x500)
21#define SHADOW_CONSOLE_END (0x1000)
22#define SHADOW_CONSOLE_MAGIC_LOC (0x4F0)
23#define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
24
25static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
26
27static __init void early_shadow_write(struct console *con, const char *s,
28 unsigned int n)
29{
30 /*
31 * save 2 bytes for the double null at the end
32 * once we fail on a long line, make sure we don't write a short line afterwards
33 */
34 if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
35 memcpy(shadow_console_buffer, s, n);
36 shadow_console_buffer += n;
37 shadow_console_buffer[0] = 0;
38 shadow_console_buffer[1] = 0;
39 } else
40 shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
41}
42
43static __initdata struct console early_shadow_console = {
44 .name = "early_shadow",
45 .write = early_shadow_write,
46 .flags = CON_BOOT | CON_PRINTBUFFER,
47 .index = -1,
48 .device = 0,
49};
50
51__init void enable_shadow_console(void)
52{
53 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
54
55 if (!(early_shadow_console.flags & CON_ENABLED)) {
56 register_console(&early_shadow_console);
57 /* for now, assume things are going to fail */
58 *loc = SHADOW_CONSOLE_MAGIC;
59 loc++;
60 *loc = SHADOW_CONSOLE_START;
61 }
62}
63
64static __init int disable_shadow_console(void)
65{
66 /*
67 * by the time pure_initcall runs, the standard console is enabled,
68 * and the early_console is off, so unset the magic numbers
69 * unregistering the console is taken care of in common code (See
70 * ./kernel/printk:disable_boot_consoles() )
71 */
72 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
73
74 *loc = 0;
75
76 return 0;
77}
78pure_initcall(disable_shadow_console);