shadow_console.c 2.7 KB

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