ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

Select the types of activity you want to include in your feed.

Expose ACPI table provenance source identity checksums and AML body hashing

+100 -12
+16 -2
src/js.c
··· 112 112 tobi_sb_init(&sb); 113 113 tobi_sb_add(&sb, "{\"meta\":{"); 114 114 tobi_sb_printf(&sb, "\"is_table\":%s,", res->meta.is_table ? "true" : "false"); 115 + tobi_sb_add(&sb, "\"source\":"); 116 + tobi_json_string(&sb, res->meta.source); 117 + tobi_sb_add(&sb, ","); 115 118 tobi_sb_add(&sb, "\"signature\":"); 116 119 tobi_json_string(&sb, res->meta.signature); 117 120 tobi_sb_printf(&sb, ",\"table_length\":%zu,\"aml_offset\":%zu,\"aml_length\":%zu," 118 - "\"checksum_sum\":%u,\"checksum_valid\":%s},", 121 + "\"revision\":%u,\"checksum_byte\":%u,\"checksum_sum\":%u," 122 + "\"checksum_valid\":%s,\"header_hash\":%u,\"aml_hash\":%u,", 119 123 res->meta.table_len, res->meta.aml_off, res->meta.aml_len, 120 - (unsigned)res->meta.checksum_sum, res->meta.checksum_valid ? "true" : "false"); 124 + (unsigned)res->meta.revision, (unsigned)res->meta.checksum_byte, 125 + (unsigned)res->meta.checksum_sum, res->meta.checksum_valid ? "true" : "false", 126 + res->meta.header_hash, res->meta.aml_hash); 127 + tobi_sb_add(&sb, "\"oem_id\":"); 128 + tobi_json_string(&sb, res->meta.oem_id); 129 + tobi_sb_add(&sb, ",\"oem_table_id\":"); 130 + tobi_json_string(&sb, res->meta.oem_table_id); 131 + tobi_sb_printf(&sb, ",\"oem_revision\":%u,", res->meta.oem_revision); 132 + tobi_sb_add(&sb, "\"creator_id\":"); 133 + tobi_json_string(&sb, res->meta.creator_id); 134 + tobi_sb_printf(&sb, ",\"creator_revision\":%u},", res->meta.creator_revision); 121 135 tobi_sb_add(&sb, "\"diagnostics\":["); 122 136 for (size_t i = 0; i < res->diag.len; i++) { 123 137 if (i) {
+22 -10
src/main.c
··· 63 63 } 64 64 } 65 65 66 + static void set_source(tobi_input_meta *meta, const char *path) { 67 + if (!path) { 68 + return; 69 + } 70 + (void)snprintf(meta->source, sizeof(meta->source), "%s", path); 71 + } 72 + 73 + static void print_raw_meta(const char *input, const tobi_parse_result *res) { 74 + printf("input=%s\nsource=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\nrevision=%u\nchecksum_byte=0x%02x\nchecksum_sum=0x%02x\nchecksum_valid=%s\noem_id=%s\noem_table_id=%s\noem_revision=%u\ncreator_id=%s\ncreator_revision=%u\nheader_hash=0x%08x\naml_hash=0x%08x\nnamespace_objects=%zu\n", 75 + input, res->meta.source, res->meta.signature, res->meta.is_table ? "true" : "false", 76 + res->meta.table_len, res->meta.aml_off, res->meta.aml_len, 77 + (unsigned)res->meta.revision, (unsigned)res->meta.checksum_byte, 78 + (unsigned)res->meta.checksum_sum, res->meta.checksum_valid ? "true" : "false", 79 + res->meta.oem_id, res->meta.oem_table_id, res->meta.oem_revision, 80 + res->meta.creator_id, res->meta.creator_revision, res->meta.header_hash, 81 + res->meta.aml_hash, res->ns.len); 82 + } 83 + 66 84 int main(int argc, char **argv) { 67 85 int mode_dis = 0; 68 86 int mode_json = 0; ··· 134 152 for (size_t i = 0; i < file_len; i++) { 135 153 tobi_parse_result one; 136 154 int ok = tobi_parse(data[i], lens[i], strict, &one); 155 + set_source(&one.meta, files[i]); 137 156 if (mode_raw) { 138 - printf("input=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\nchecksum_sum=0x%02x\nchecksum_valid=%s\nnamespace_objects=%zu\n", 139 - files[i], one.meta.signature, one.meta.is_table ? "true" : "false", 140 - one.meta.table_len, one.meta.aml_off, one.meta.aml_len, 141 - (unsigned)one.meta.checksum_sum, one.meta.checksum_valid ? "true" : "false", 142 - one.ns.len); 157 + print_raw_meta(files[i], &one); 143 158 } else { 144 159 if (file_len > 1) { 145 160 printf("== %s ==\n", files[i]); ··· 166 181 int ok = 0; 167 182 if (file_len == 1) { 168 183 ok = tobi_parse(data[0], lens[0], strict, &res); 184 + set_source(&res.meta, files[0]); 169 185 } else { 170 186 tobi_parse_input *inputs = tobi_xcalloc(file_len, sizeof(inputs[0])); 171 187 for (size_t i = 0; i < file_len; i++) { ··· 189 205 } 190 206 (void)tobi_cf_recover(res.root, &res.diag); 191 207 if (mode_raw) { 192 - printf("input=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\nchecksum_sum=0x%02x\nchecksum_valid=%s\nnamespace_objects=%zu\n", 193 - files[0], res.meta.signature, res.meta.is_table ? "true" : "false", 194 - res.meta.table_len, res.meta.aml_off, res.meta.aml_len, 195 - (unsigned)res.meta.checksum_sum, res.meta.checksum_valid ? "true" : "false", 196 - res.ns.len); 208 + print_raw_meta(files[0], &res); 197 209 } else if (mode_json) { 198 210 char *s = tobi_js_emit(&res); 199 211 fputs(s, stdout);
+34
src/p.c
··· 43 43 return (uint32_t)d[0] | ((uint32_t)d[1] << 8) | ((uint32_t)d[2] << 16) | ((uint32_t)d[3] << 24); 44 44 } 45 45 46 + static void copy_trim(char *dst, size_t dst_len, const uint8_t *src, size_t src_len) { 47 + size_t n = src_len; 48 + while (n > 0 && src[n - 1u] == ' ') { 49 + n--; 50 + } 51 + if (n >= dst_len) { 52 + n = dst_len - 1u; 53 + } 54 + memcpy(dst, src, n); 55 + dst[n] = '\0'; 56 + } 57 + 58 + static uint32_t hash32(const uint8_t *data, size_t len) { 59 + uint32_t h = 2166136261u; 60 + for (size_t i = 0; i < len; i++) { 61 + h ^= data[i]; 62 + h *= 16777619u; 63 + } 64 + return h; 65 + } 66 + 46 67 static int is_table_sig(const uint8_t *d) { 47 68 return memcmp(d, "DSDT", 4) == 0 || memcmp(d, "SSDT", 4) == 0; 48 69 } ··· 102 123 meta->aml_len = len; 103 124 memcpy(meta->signature, "RAW", 4); 104 125 meta->signature[4] = '\0'; 126 + memcpy(meta->source, "raw", 4); 105 127 if (len >= 4 && is_table_sig(data)) { 106 128 memcpy(meta->signature, data, 4); 107 129 meta->signature[4] = '\0'; ··· 116 138 tobi_diag_add(diag_list, TOBI_DIAG_ERROR, 4, "invalid ACPI table length %u for file size %zu", table_len, len); 117 139 return !strict; 118 140 } 141 + meta->revision = data[8]; 142 + meta->checksum_byte = data[9]; 143 + copy_trim(meta->oem_id, sizeof(meta->oem_id), data + 10, 6); 144 + copy_trim(meta->oem_table_id, sizeof(meta->oem_table_id), data + 16, 8); 145 + meta->oem_revision = le32_at(data + 24); 146 + copy_trim(meta->creator_id, sizeof(meta->creator_id), data + 28, 4); 147 + meta->creator_revision = le32_at(data + 32); 148 + meta->header_hash = hash32(data, 36); 119 149 uint8_t sum = table_sum8(data, table_len); 120 150 meta->checksum_sum = sum; 121 151 meta->checksum_valid = sum == 0; ··· 128 158 } 129 159 meta->aml_off = 36; 130 160 meta->aml_len = (size_t)table_len - 36; 161 + } 162 + if (meta->aml_off <= len && meta->aml_len <= len - meta->aml_off) { 163 + meta->aml_hash = hash32(data + meta->aml_off, meta->aml_len); 131 164 } 132 165 return 1; 133 166 } ··· 1861 1894 tobi_ns_init(&out->ns); 1862 1895 memcpy(out->meta.signature, "MULT", 4); 1863 1896 out->meta.signature[4] = '\0'; 1897 + memcpy(out->meta.source, "multi", 6); 1864 1898 out->root = tobi_ir_new(TOBI_IR_ROOT, 0, 0); 1865 1899 if (!inputs || count == 0) { 1866 1900 tobi_diag_add(&out->diag, TOBI_DIAG_ERROR, 0, "no AML inputs");
+10
src/p.h
··· 11 11 typedef struct tobi_input_meta { 12 12 int is_table; 13 13 char signature[5]; 14 + char source[128]; 15 + char oem_id[7]; 16 + char oem_table_id[9]; 17 + char creator_id[5]; 14 18 size_t table_len; 15 19 size_t aml_off; 16 20 size_t aml_len; 21 + uint32_t oem_revision; 22 + uint32_t creator_revision; 23 + uint32_t header_hash; 24 + uint32_t aml_hash; 25 + uint8_t revision; 26 + uint8_t checksum_byte; 17 27 uint8_t checksum_sum; 18 28 int checksum_valid; 19 29 } tobi_input_meta;
+4
test/t_js.c
··· 9 9 T_CHECK(tobi_parse(data, sizeof(data), 0, &r)); 10 10 char *s = tobi_js_emit(&r); 11 11 T_STR(s, "\"kind\":\"root\""); 12 + T_STR(s, "\"source\":\"raw\""); 12 13 T_STR(s, "\"checksum_sum\":0"); 13 14 T_STR(s, "\"checksum_valid\":false"); 15 + T_STR(s, "\"header_hash\":0"); 16 + T_STR(s, "\"aml_hash\":"); 17 + T_STR(s, "\"oem_id\":\"\""); 14 18 T_STR(s, "\"namespace\":["); 15 19 T_STR(s, "\"path\":\"\\\\STR0\""); 16 20 T_STR(s, "\"kind\":\"name\"");
+14
test/t_p.c
··· 35 35 table[5] = (uint8_t)((table_len >> 8) & 0xffu); 36 36 table[6] = (uint8_t)((table_len >> 16) & 0xffu); 37 37 table[7] = (uint8_t)((table_len >> 24) & 0xffu); 38 + table[8] = 2; 39 + memcpy(table + 10, "TOBI ", 6); 40 + memcpy(table + 16, "TBLTEST ", 8); 41 + table[24] = 7; 42 + memcpy(table + 28, "CODX", 4); 43 + table[32] = 9; 38 44 memcpy(table + 36, m0, sizeof(m0)); 39 45 fix_checksum(table, sizeof(table)); 40 46 T_CHECK(parse_ok(table, sizeof(table), &r)); 41 47 T_CHECK(r.meta.is_table && r.meta.aml_off == 36 && r.meta.aml_len == sizeof(m0)); 42 48 T_CHECK(r.meta.checksum_valid && r.meta.checksum_sum == 0); 49 + T_CHECK(r.meta.revision == 2); 50 + T_CHECK(strcmp(r.meta.oem_id, "TOBI") == 0); 51 + T_CHECK(strcmp(r.meta.oem_table_id, "TBLTEST") == 0); 52 + T_CHECK(r.meta.oem_revision == 7); 53 + T_CHECK(strcmp(r.meta.creator_id, "CODX") == 0); 54 + T_CHECK(r.meta.creator_revision == 9); 55 + T_CHECK(r.meta.header_hash != 0); 56 + T_CHECK(r.meta.aml_hash != 0); 43 57 T_CHECK(r.root->child_len == 1 && r.root->child[0]->kind == TOBI_IR_METHOD); 44 58 T_CHECK(r.root->child[0]->off == 36); 45 59 T_CHECK(r.diag.len == 0);