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 * 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 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) 21#define SHADOW_CONSOLE_MAGIC (0xDEADBEEF) 22 23static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; 24 25__init void early_shadow_write(struct console *con, const char *s, 26 unsigned int n) 27{ 28 unsigned int i; 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)) { 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]; 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 44static __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 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) 58{ 59 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; 60 loc[0] = SHADOW_CONSOLE_MAGIC; 61 loc[1] = SHADOW_CONSOLE_START; 62} 63 64__init void enable_shadow_console(void) 65{ 66 if (!shadow_console_enabled()) { 67 register_console(&early_shadow_console); 68 /* for now, assume things are going to fail */ 69 mark_shadow_error(); 70 } 71} 72 73static __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 83 loc[0] = 0; 84 85 return 0; 86} 87pure_initcall(disable_shadow_console); 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} 112