Commit | Line | Data |
---|---|---|
3f871fea RG |
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 | * | |
3f871fea RG |
7 | * Licensed under the GPL-2 or later. |
8 | */ | |
9 | ||
10 | #include <linux/kernel.h> | |
11 | #include <linux/init.h> | |
12 | #include <linux/console.h> | |
13 | #include <linux/string.h> | |
14 | #include <asm/blackfin.h> | |
15 | #include <asm/irq_handler.h> | |
16 | #include <asm/early_printk.h> | |
17 | ||
b5affb01 BL |
18 | #define SHADOW_CONSOLE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x500) |
19 | #define SHADOW_CONSOLE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x1000) | |
20 | #define SHADOW_CONSOLE_MAGIC_LOC (CONFIG_PHY_RAM_BASE_ADDRESS + 0x4F0) | |
3f871fea RG |
21 | #define SHADOW_CONSOLE_MAGIC (0xDEADBEEF) |
22 | ||
23 | static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; | |
24 | ||
837ec2d5 | 25 | __init void early_shadow_write(struct console *con, const char *s, |
3f871fea RG |
26 | unsigned int n) |
27 | { | |
837ec2d5 | 28 | unsigned int i; |
3f871fea RG |
29 | /* |
30 | * save 2 bytes for the double null at the end | |
31 | * once we fail on a long line, make sure we don't write a short line afterwards | |
32 | */ | |
33 | if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) { | |
837ec2d5 RG |
34 | /* can't use memcpy - it may not be relocated yet */ |
35 | for (i = 0; i <= n; i++) | |
36 | shadow_console_buffer[i] = s[i]; | |
3f871fea RG |
37 | shadow_console_buffer += n; |
38 | shadow_console_buffer[0] = 0; | |
39 | shadow_console_buffer[1] = 0; | |
40 | } else | |
41 | shadow_console_buffer = (char *)SHADOW_CONSOLE_END; | |
42 | } | |
43 | ||
44 | static __initdata struct console early_shadow_console = { | |
45 | .name = "early_shadow", | |
46 | .write = early_shadow_write, | |
47 | .flags = CON_BOOT | CON_PRINTBUFFER, | |
48 | .index = -1, | |
49 | .device = 0, | |
50 | }; | |
51 | ||
837ec2d5 RG |
52 | __init int shadow_console_enabled(void) |
53 | { | |
54 | return early_shadow_console.flags & CON_ENABLED; | |
55 | } | |
56 | ||
57 | __init void mark_shadow_error(void) | |
3f871fea RG |
58 | { |
59 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; | |
837ec2d5 RG |
60 | loc[0] = SHADOW_CONSOLE_MAGIC; |
61 | loc[1] = SHADOW_CONSOLE_START; | |
62 | } | |
3f871fea | 63 | |
837ec2d5 RG |
64 | __init void enable_shadow_console(void) |
65 | { | |
66 | if (!shadow_console_enabled()) { | |
3f871fea RG |
67 | register_console(&early_shadow_console); |
68 | /* for now, assume things are going to fail */ | |
837ec2d5 | 69 | mark_shadow_error(); |
3f871fea RG |
70 | } |
71 | } | |
72 | ||
73 | static __init int disable_shadow_console(void) | |
74 | { | |
75 | /* | |
76 | * by the time pure_initcall runs, the standard console is enabled, | |
77 | * and the early_console is off, so unset the magic numbers | |
78 | * unregistering the console is taken care of in common code (See | |
79 | * ./kernel/printk:disable_boot_consoles() ) | |
80 | */ | |
81 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; | |
82 | ||
837ec2d5 | 83 | loc[0] = 0; |
3f871fea RG |
84 | |
85 | return 0; | |
86 | } | |
87 | pure_initcall(disable_shadow_console); | |
837ec2d5 RG |
88 | |
89 | /* | |
90 | * since we can't use printk, dump numbers (as hex), n = # bits | |
91 | */ | |
92 | __init void early_shadow_reg(unsigned long reg, unsigned int n) | |
93 | { | |
94 | /* | |
95 | * can't use any "normal" kernel features, since thay | |
96 | * may not be relocated to their execute address yet | |
97 | */ | |
98 | int i; | |
99 | char ascii[11] = " 0x"; | |
100 | ||
101 | n = n / 4; | |
102 | reg = reg << ((8 - n) * 4); | |
103 | n += 3; | |
104 | ||
105 | for (i = 3; i <= n ; i++) { | |
106 | ascii[i] = hex_asc_lo(reg >> 28); | |
107 | reg <<= 4; | |
108 | } | |
109 | early_shadow_write(NULL, ascii, n); | |
110 | ||
111 | } |