linux/arch/blackfin/kernel/shadow_console.c
<<
>>
Prefs
   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