rtkit-crashlog.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /*
  3. * Apple RTKit IPC library
  4. * Copyright (C) The Asahi Linux Contributors
  5. */
  6. #include "rtkit-internal.h"
  7. #define FOURCC(a, b, c, d) \
  8. (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d)))
  9. #define APPLE_RTKIT_CRASHLOG_HEADER FOURCC('C', 'L', 'H', 'E')
  10. #define APPLE_RTKIT_CRASHLOG_STR FOURCC('C', 's', 't', 'r')
  11. #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r')
  12. #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x')
  13. #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm')
  14. struct apple_rtkit_crashlog_header {
  15. u32 fourcc;
  16. u32 version;
  17. u32 size;
  18. u32 flags;
  19. u8 _unk[16];
  20. };
  21. static_assert(sizeof(struct apple_rtkit_crashlog_header) == 0x20);
  22. struct apple_rtkit_crashlog_mbox_entry {
  23. u64 msg0;
  24. u64 msg1;
  25. u32 timestamp;
  26. u8 _unk[4];
  27. };
  28. static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);
  29. static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
  30. size_t size)
  31. {
  32. u32 idx;
  33. u8 *ptr, *end;
  34. memcpy(&idx, bfr, 4);
  35. ptr = bfr + 4;
  36. end = bfr + size;
  37. while (ptr < end) {
  38. u8 *newline = memchr(ptr, '\n', end - ptr);
  39. if (newline) {
  40. u8 tmp = *newline;
  41. *newline = '\0';
  42. dev_warn(rtk->dev, "RTKit: Message (id=%x): %s\n", idx,
  43. ptr);
  44. *newline = tmp;
  45. ptr = newline + 1;
  46. } else {
  47. dev_warn(rtk->dev, "RTKit: Message (id=%x): %s", idx,
  48. ptr);
  49. break;
  50. }
  51. }
  52. }
  53. static void apple_rtkit_crashlog_dump_version(struct apple_rtkit *rtk, u8 *bfr,
  54. size_t size)
  55. {
  56. dev_warn(rtk->dev, "RTKit: Version: %s", bfr + 16);
  57. }
  58. static void apple_rtkit_crashlog_dump_time(struct apple_rtkit *rtk, u8 *bfr,
  59. size_t size)
  60. {
  61. u64 crash_time;
  62. memcpy(&crash_time, bfr, 8);
  63. dev_warn(rtk->dev, "RTKit: Crash time: %lld", crash_time);
  64. }
  65. static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
  66. size_t size)
  67. {
  68. u32 type, index, i;
  69. size_t n_messages;
  70. struct apple_rtkit_crashlog_mbox_entry entry;
  71. memcpy(&type, bfr + 16, 4);
  72. memcpy(&index, bfr + 24, 4);
  73. n_messages = (size - 28) / sizeof(entry);
  74. dev_warn(rtk->dev, "RTKit: Mailbox history (type = %d, index = %d)",
  75. type, index);
  76. for (i = 0; i < n_messages; ++i) {
  77. memcpy(&entry, bfr + 28 + i * sizeof(entry), sizeof(entry));
  78. dev_warn(rtk->dev, "RTKit: #%03d@%08x: %016llx %016llx", i,
  79. entry.timestamp, entry.msg0, entry.msg1);
  80. }
  81. }
  82. void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
  83. {
  84. size_t offset;
  85. u32 section_fourcc, section_size;
  86. struct apple_rtkit_crashlog_header header;
  87. memcpy(&header, bfr, sizeof(header));
  88. if (header.fourcc != APPLE_RTKIT_CRASHLOG_HEADER) {
  89. dev_warn(rtk->dev, "RTKit: Expected crashlog header but got %x",
  90. header.fourcc);
  91. return;
  92. }
  93. if (header.size > size) {
  94. dev_warn(rtk->dev, "RTKit: Crashlog size (%x) is too large",
  95. header.size);
  96. return;
  97. }
  98. size = header.size;
  99. offset = sizeof(header);
  100. while (offset < size) {
  101. memcpy(&section_fourcc, bfr + offset, 4);
  102. memcpy(&section_size, bfr + offset + 12, 4);
  103. switch (section_fourcc) {
  104. case APPLE_RTKIT_CRASHLOG_HEADER:
  105. dev_dbg(rtk->dev, "RTKit: End of crashlog reached");
  106. return;
  107. case APPLE_RTKIT_CRASHLOG_STR:
  108. apple_rtkit_crashlog_dump_str(rtk, bfr + offset + 16,
  109. section_size);
  110. break;
  111. case APPLE_RTKIT_CRASHLOG_VERSION:
  112. apple_rtkit_crashlog_dump_version(
  113. rtk, bfr + offset + 16, section_size);
  114. break;
  115. case APPLE_RTKIT_CRASHLOG_MBOX:
  116. apple_rtkit_crashlog_dump_mailbox(
  117. rtk, bfr + offset + 16, section_size);
  118. break;
  119. case APPLE_RTKIT_CRASHLOG_TIME:
  120. apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16,
  121. section_size);
  122. break;
  123. default:
  124. dev_warn(rtk->dev,
  125. "RTKit: Unknown crashlog section: %x",
  126. section_fourcc);
  127. }
  128. offset += section_size;
  129. }
  130. dev_warn(rtk->dev,
  131. "RTKit: End of crashlog reached but no footer present");
  132. }