shadow_console.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. #include <linux/kernel.h>
  10. #include <linux/init.h>
  11. #include <linux/console.h>
  12. #include <linux/string.h>
  13. #include <asm/blackfin.h>
  14. #include <asm/irq_handler.h>
  15. #include <asm/early_printk.h>
  16. #define SHADOW_CONSOLE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x500)
  17. #define SHADOW_CONSOLE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x1000)
  18. #define SHADOW_CONSOLE_MAGIC_LOC (CONFIG_PHY_RAM_BASE_ADDRESS + 0x4F0)
  19. #define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
  20. static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
  21. __init void early_shadow_write(struct console *con, const char *s,
  22. unsigned int n)
  23. {
  24. unsigned int i;
  25. /*
  26. * save 2 bytes for the double null at the end
  27. * once we fail on a long line, make sure we don't write a short line afterwards
  28. */
  29. if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
  30. /* can't use memcpy - it may not be relocated yet */
  31. for (i = 0; i <= n; i++)
  32. shadow_console_buffer[i] = s[i];
  33. shadow_console_buffer += n;
  34. shadow_console_buffer[0] = 0;
  35. shadow_console_buffer[1] = 0;
  36. } else
  37. shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
  38. }
  39. static __initdata struct console early_shadow_console = {
  40. .name = "early_shadow",
  41. .write = early_shadow_write,
  42. .flags = CON_BOOT | CON_PRINTBUFFER,
  43. .index = -1,
  44. .device = 0,
  45. };
  46. __init int shadow_console_enabled(void)
  47. {
  48. return early_shadow_console.flags & CON_ENABLED;
  49. }
  50. __init void mark_shadow_error(void)
  51. {
  52. int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
  53. loc[0] = SHADOW_CONSOLE_MAGIC;
  54. loc[1] = SHADOW_CONSOLE_START;
  55. }
  56. __init void enable_shadow_console(void)
  57. {
  58. if (!shadow_console_enabled()) {
  59. register_console(&early_shadow_console);
  60. /* for now, assume things are going to fail */
  61. mark_shadow_error();
  62. }
  63. }
  64. static __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. loc[0] = 0;
  74. return 0;
  75. }
  76. pure_initcall(disable_shadow_console);
  77. /*
  78. * since we can't use printk, dump numbers (as hex), n = # bits
  79. */
  80. __init void early_shadow_reg(unsigned long reg, unsigned int n)
  81. {
  82. /*
  83. * can't use any "normal" kernel features, since thay
  84. * may not be relocated to their execute address yet
  85. */
  86. int i;
  87. char ascii[11] = " 0x";
  88. n = n / 4;
  89. reg = reg << ((8 - n) * 4);
  90. n += 3;
  91. for (i = 3; i <= n ; i++) {
  92. ascii[i] = hex_asc_lo(reg >> 28);
  93. reg <<= 4;
  94. }
  95. early_shadow_write(NULL, ascii, n);
  96. }