123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- /*
- * manage a small early shadow of the log buffer which we can pass between the
- * bootloader so early crash messages are communicated properly and easily
- *
- * Copyright 2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/console.h>
- #include <linux/string.h>
- #include <asm/blackfin.h>
- #include <asm/irq_handler.h>
- #include <asm/early_printk.h>
- #define SHADOW_CONSOLE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x500)
- #define SHADOW_CONSOLE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x1000)
- #define SHADOW_CONSOLE_MAGIC_LOC (CONFIG_PHY_RAM_BASE_ADDRESS + 0x4F0)
- #define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
- static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
- __init void early_shadow_write(struct console *con, const char *s,
- unsigned int n)
- {
- unsigned int i;
- /*
- * save 2 bytes for the double null at the end
- * once we fail on a long line, make sure we don't write a short line afterwards
- */
- if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
- /* can't use memcpy - it may not be relocated yet */
- for (i = 0; i <= n; i++)
- shadow_console_buffer[i] = s[i];
- shadow_console_buffer += n;
- shadow_console_buffer[0] = 0;
- shadow_console_buffer[1] = 0;
- } else
- shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
- }
- static __initdata struct console early_shadow_console = {
- .name = "early_shadow",
- .write = early_shadow_write,
- .flags = CON_BOOT | CON_PRINTBUFFER,
- .index = -1,
- .device = 0,
- };
- __init int shadow_console_enabled(void)
- {
- return early_shadow_console.flags & CON_ENABLED;
- }
- __init void mark_shadow_error(void)
- {
- int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
- loc[0] = SHADOW_CONSOLE_MAGIC;
- loc[1] = SHADOW_CONSOLE_START;
- }
- __init void enable_shadow_console(void)
- {
- if (!shadow_console_enabled()) {
- register_console(&early_shadow_console);
- /* for now, assume things are going to fail */
- mark_shadow_error();
- }
- }
- static __init int disable_shadow_console(void)
- {
- /*
- * by the time pure_initcall runs, the standard console is enabled,
- * and the early_console is off, so unset the magic numbers
- * unregistering the console is taken care of in common code (See
- * ./kernel/printk:disable_boot_consoles() )
- */
- int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
- loc[0] = 0;
- return 0;
- }
- pure_initcall(disable_shadow_console);
- /*
- * since we can't use printk, dump numbers (as hex), n = # bits
- */
- __init void early_shadow_reg(unsigned long reg, unsigned int n)
- {
- /*
- * can't use any "normal" kernel features, since thay
- * may not be relocated to their execute address yet
- */
- int i;
- char ascii[11] = " 0x";
- n = n / 4;
- reg = reg << ((8 - n) * 4);
- n += 3;
- for (i = 3; i <= n ; i++) {
- ascii[i] = hex_asc_lo(reg >> 28);
- reg <<= 4;
- }
- early_shadow_write(NULL, ascii, n);
- }
|