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