ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

Expand AML semantic coverage w/ namespace externals + table provenance metadata

+329 -46
+3 -2
CMakeLists.txt
··· 40 40 41 41 add_executable(tobi_test 42 42 test/main.c test/t_rd.c test/t_nm.c test/t_p.c test/t_ir.c 43 - test/t_cf.c test/t_da.c test/t_dc.c test/t_js.c test/t_bad.c test/t_cli.c) 43 + test/t_cf.c test/t_da.c test/t_dc.c test/t_js.c test/t_bad.c test/t_cli.c 44 + test/t_prod.c) 44 45 target_link_libraries(tobi_test PRIVATE tobilib) 45 46 target_compile_options(tobi_test PRIVATE ${TOBI_WARN}) 46 47 target_compile_definitions(tobi_test PRIVATE ··· 51 52 target_link_options(tobi_test PRIVATE ${SAN_FLAGS}) 52 53 endif() 53 54 54 - foreach(t rd nm p ir cf da dc js bad cli) 55 + foreach(t rd nm p ir cf da dc js bad cli prod) 55 56 add_test(NAME ${t} COMMAND tobi_test ${t}) 56 57 endforeach() 57 58
-5
src/cf.c
··· 49 49 tobi_diag_add(diag, TOBI_DIAG_WARN, n->off, "%s outside loop kept as explicit statement", 50 50 n->kind == TOBI_IR_BREAK ? "break" : "continue"); 51 51 } 52 - /* 53 - * AML IfOp, ElseOp, and WhileOp carry bounded package bodies, so those 54 - * become structured directly. Remaining branch-like residue is labelled 55 - * only when there is no bounded package evidence to justify a rewrite. 56 - */ 57 52 size_t original_children = n->child_len; 58 53 unsigned child_loop_depth = loop_depth + (n->kind == TOBI_IR_WHILE ? 1u : 0u); 59 54 for (size_t i = 0; i < original_children; i++) {
+33 -2
src/da.c
··· 24 24 } 25 25 } 26 26 27 + static void skip_simple_arg(tobi_rd *rd) { 28 + uint8_t op = 0; 29 + if (!tobi_rd_u8(rd, &op)) { 30 + return; 31 + } 32 + if (op == 0x0a) { 33 + (void)tobi_rd_skip(rd, 1); 34 + } else if (op == 0x0b) { 35 + (void)tobi_rd_skip(rd, 2); 36 + } else if (op == 0x0c) { 37 + (void)tobi_rd_skip(rd, 4); 38 + } else if (op == 0x0e) { 39 + (void)tobi_rd_skip(rd, 8); 40 + } else if (op == 0x0d) { 41 + while (tobi_rd_left(rd) > 0) { 42 + uint8_t c = 0; 43 + (void)tobi_rd_u8(rd, &c); 44 + if (c == 0) { 45 + break; 46 + } 47 + } 48 + } 49 + } 50 + 27 51 static void walk(tobi_sb *sb, tobi_rd *rd, unsigned depth) { 28 52 if (depth > 64) { 29 53 tobi_sb_printf(sb, "0x%04zx: <nesting limit>\n", tobi_rd_off(rd)); ··· 153 177 tobi_sb_ch(sb, '\n'); 154 178 tobi_rd sub; 155 179 tobi_rd_init(&sub, rd->data + body_start, end - body_start, rd->base + body_start); 156 - if (code == 0x14) { 180 + if (code == 0x11) { 181 + skip_simple_arg(&sub); 182 + tobi_sb_printf(sb, "0x%04zx: BufferData len=%zu ", tobi_rd_off(&sub), tobi_rd_left(&sub)); 183 + raw_bytes(sb, &sub, sub.pos, sub.len); 184 + tobi_sb_ch(sb, '\n'); 185 + } else if (code == 0x14) { 157 186 char *nm = NULL; 158 187 if (tobi_nm_namestring(&sub, &nm)) { 159 188 free(nm); ··· 173 202 } else if (code == 0xa0 || code == 0xa2) { 174 203 (void)tobi_rd_skip(&sub, 1); 175 204 } 176 - walk(sb, &sub, depth + 1); 205 + if (code != 0x11) { 206 + walk(sb, &sub, depth + 1); 207 + } 177 208 rd->pos = end; 178 209 } else { 179 210 tobi_sb_add(sb, extra);
+4 -2
src/js.c
··· 70 70 tobi_sb_printf(&sb, "\"is_table\":%s,", res->meta.is_table ? "true" : "false"); 71 71 tobi_sb_add(&sb, "\"signature\":"); 72 72 tobi_json_string(&sb, res->meta.signature); 73 - tobi_sb_printf(&sb, ",\"table_length\":%zu,\"aml_offset\":%zu,\"aml_length\":%zu},", 74 - res->meta.table_len, res->meta.aml_off, res->meta.aml_len); 73 + tobi_sb_printf(&sb, ",\"table_length\":%zu,\"aml_offset\":%zu,\"aml_length\":%zu," 74 + "\"checksum_sum\":%u,\"checksum_valid\":%s},", 75 + res->meta.table_len, res->meta.aml_off, res->meta.aml_len, 76 + (unsigned)res->meta.checksum_sum, res->meta.checksum_valid ? "true" : "false"); 75 77 tobi_sb_add(&sb, "\"diagnostics\":["); 76 78 for (size_t i = 0; i < res->diag.len; i++) { 77 79 if (i) {
+6 -4
src/main.c
··· 135 135 tobi_parse_result one; 136 136 int ok = tobi_parse(data[i], lens[i], strict, &one); 137 137 if (mode_raw) { 138 - printf("input=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\n", 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\n", 139 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); 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"); 141 142 } else { 142 143 if (file_len > 1) { 143 144 printf("== %s ==\n", files[i]); ··· 187 188 } 188 189 (void)tobi_cf_recover(res.root, &res.diag); 189 190 if (mode_raw) { 190 - printf("input=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\n", 191 + printf("input=%s\nformat=%s\nis_table=%s\ntable_length=%zu\naml_offset=%zu\naml_length=%zu\nchecksum_sum=0x%02x\nchecksum_valid=%s\n", 191 192 files[0], res.meta.signature, res.meta.is_table ? "true" : "false", 192 - res.meta.table_len, res.meta.aml_off, res.meta.aml_len); 193 + res.meta.table_len, res.meta.aml_off, res.meta.aml_len, 194 + (unsigned)res.meta.checksum_sum, res.meta.checksum_valid ? "true" : "false"); 193 195 } else if (mode_json) { 194 196 char *s = tobi_js_emit(&res); 195 197 fputs(s, stdout);
+6
src/op.c
··· 17 17 {0x12, "PackageOp", TOBI_OP_PKG, 1}, 18 18 {0x13, "VarPackageOp", TOBI_OP_PKG, 1}, 19 19 {0x14, "MethodOp", TOBI_OP_PKG, 1}, 20 + {0x15, "ExternalOp", TOBI_OP_NAMED, 0}, 20 21 {0x2e, "DualNamePrefix", TOBI_OP_NAMED, 0}, 21 22 {0x2f, "MultiNamePrefix", TOBI_OP_NAMED, 0}, 22 23 {0x5b, "ExtOpPrefix", TOBI_OP_EXT, 0}, ··· 96 97 {0x5b02, "EventOp", TOBI_OP_EXT, 0}, 97 98 {0x5b12, "CondRefOfOp", TOBI_OP_EXT, 0}, 98 99 {0x5b13, "CreateFieldOp", TOBI_OP_EXT, 0}, 100 + {0x5b1f, "LoadTableOp", TOBI_OP_EXT, 0}, 99 101 {0x5b20, "LoadOp", TOBI_OP_EXT, 0}, 100 102 {0x5b21, "StallOp", TOBI_OP_EXT, 0}, 101 103 {0x5b22, "SleepOp", TOBI_OP_EXT, 0}, ··· 110 112 {0x5b30, "RevisionOp", TOBI_OP_EXT, 0}, 111 113 {0x5b31, "DebugOp", TOBI_OP_EXT, 0}, 112 114 {0x5b32, "FatalOp", TOBI_OP_EXT, 0}, 115 + {0x5b33, "TimerOp", TOBI_OP_EXT, 0}, 113 116 {0x5b80, "OpRegionOp", TOBI_OP_EXT, 0}, 114 117 {0x5b81, "FieldOp", TOBI_OP_EXT, 1}, 115 118 {0x5b82, "DeviceOp", TOBI_OP_EXT, 1}, ··· 134 137 {0x12, "PkgLength NumElements PackageElements"}, 135 138 {0x13, "PkgLength VarNumElements PackageElements"}, 136 139 {0x14, "PkgLength NameString MethodFlags TermList"}, 140 + {0x15, "NameString ObjectType ArgumentCount"}, 137 141 {0x70, "TermArg SuperName"}, 138 142 {0x71, "SuperName"}, 139 143 {0x72, "TermArg TermArg Target"}, ··· 189 193 {0x5b02, "NameString"}, 190 194 {0x5b12, "SuperName Target"}, 191 195 {0x5b13, "SourceBuff BitIndex NumBits NameString"}, 196 + {0x5b1f, "Signature OemId OemTableId RootPath ParameterPath Target"}, 192 197 {0x5b20, "NameString Target"}, 193 198 {0x5b21, "TermArg"}, 194 199 {0x5b22, "TermArg"}, ··· 203 208 {0x5b30, ""}, 204 209 {0x5b31, ""}, 205 210 {0x5b32, "FatalType FatalCode FatalArg"}, 211 + {0x5b33, ""}, 206 212 {0x5b80, "NameString RegionSpace RegionOffset RegionLen"}, 207 213 {0x5b81, "PkgLength NameString FieldFlags FieldList"}, 208 214 {0x5b82, "PkgLength NameString TermList"},
+110 -31
src/p.c
··· 128 128 return !strict; 129 129 } 130 130 uint8_t sum = table_sum8(data, table_len); 131 + meta->checksum_sum = sum; 132 + meta->checksum_valid = sum == 0; 131 133 if (sum != 0) { 132 134 tobi_diag_add(diag_list, strict ? TOBI_DIAG_ERROR : TOBI_DIAG_WARN, 9, 133 135 "ACPI table checksum mismatch: byte sum is 0x%02x", sum); ··· 300 302 return n; 301 303 } 302 304 305 + static tobi_ir *parse_external(parser *p, tobi_rd *rd, size_t op_start) { 306 + char *name = NULL; 307 + if (!parse_namestring_diag(p, rd, &name)) { 308 + return unknown_node(p, op_start, 0x15, 1, "bad ExternalOp name"); 309 + } 310 + uint8_t obj_type = 0; 311 + uint8_t argc = 0; 312 + if (!tobi_rd_u8(rd, &obj_type) || !tobi_rd_u8(rd, &argc)) { 313 + free(name); 314 + diag(p, TOBI_DIAG_ERROR, tobi_rd_off(rd), "truncated ExternalOp metadata"); 315 + return unknown_node(p, op_start, 0x15, tobi_rd_off(rd) - op_start, "bad ExternalOp metadata"); 316 + } 317 + tobi_ir *n = tobi_ir_new(TOBI_IR_EXPR, op_start, tobi_rd_off(rd) - op_start); 318 + n->raw_op = 0x15; 319 + n->value = argc; 320 + tobi_ir_set_name(n, "external"); 321 + char *path = tobi_nm_resolve(p->scope, name); 322 + tobi_ir_set_path(n, path); 323 + tobi_ir *typ = tobi_ir_new(TOBI_IR_INTEGER, op_start + n->len - 2u, 1); 324 + typ->value = obj_type; 325 + tobi_ir_add(n, typ); 326 + if (obj_type == 0x08u) { 327 + method_add(p, path, name, argc & 0x07u); 328 + } 329 + free(path); 330 + free(name); 331 + return n; 332 + } 333 + 303 334 static void parse_field_list(parser *p, tobi_rd *body, tobi_ir *n) { 304 335 while (tobi_rd_left(body) > 0) { 305 336 size_t foff = tobi_rd_off(body); ··· 481 512 return n; 482 513 } 483 514 515 + static tobi_ir *parse_ext_load(parser *p, tobi_rd *rd, unsigned depth, size_t op_start) { 516 + tobi_ir *n = tobi_ir_new(TOBI_IR_EXPR, op_start, 0); 517 + n->raw_op = 0x5b20u; 518 + tobi_ir_set_name(n, "load"); 519 + tobi_ir *src = ref_from_name(p, rd, op_start, "bad LoadOp source name"); 520 + if (src) { 521 + tobi_ir_add(n, src); 522 + } 523 + tobi_ir *target = parse_expr(p, rd, depth + 1); 524 + if (target) { 525 + tobi_ir_add(n, target); 526 + } 527 + n->len = tobi_rd_off(rd) - op_start; 528 + return n; 529 + } 530 + 531 + static tobi_ir *parse_ext_load_table(parser *p, tobi_rd *rd, unsigned depth, size_t op_start) { 532 + tobi_ir *n = tobi_ir_new(TOBI_IR_EXPR, op_start, 0); 533 + n->raw_op = 0x5b1fu; 534 + tobi_ir_set_name(n, "load_table"); 535 + add_expr_children(p, rd, depth, n, 6); 536 + n->len = tobi_rd_off(rd) - op_start; 537 + return n; 538 + } 539 + 484 540 static tobi_ir *parse_ext_pkg_scope(parser *p, tobi_rd *rd, unsigned depth, size_t op_start, 485 541 uint32_t raw, tobi_ir_kind kind, const char *kind_name, 486 542 unsigned prefix_bytes) { ··· 602 658 return parse_named_ext_expr(p, rd, depth, op_start, raw, "cond_ref_of", 1, 1); 603 659 case 0x13: 604 660 return parse_named_ext_expr(p, rd, depth, op_start, raw, "create_field", 3, 1); 661 + case 0x1f: 662 + return parse_ext_load_table(p, rd, depth, op_start); 605 663 case 0x20: 606 - return parse_named_ext_expr(p, rd, depth, op_start, raw, "load", 1, 0); 664 + return parse_ext_load(p, rd, depth, op_start); 607 665 case 0x21: 608 666 return parse_named_ext_expr(p, rd, depth, op_start, raw, "stall", 1, 0); 609 667 case 0x22: ··· 637 695 } 638 696 case 0x32: 639 697 return parse_named_ext_expr(p, rd, depth, op_start, raw, "fatal", 3, 0); 698 + case 0x33: { 699 + tobi_ir *n = tobi_ir_new(TOBI_IR_EXPR, op_start, tobi_rd_off(rd) - op_start); 700 + n->raw_op = raw; 701 + tobi_ir_set_name(n, "timer"); 702 + return n; 703 + } 640 704 case 0x88: { 641 705 char *name = NULL; 642 706 if (!parse_namestring_diag(p, rd, &name)) { ··· 734 798 return n; 735 799 } 736 800 737 - static int expr_opcode_arity(uint8_t op, int *has_target, const char **name) { 738 - *has_target = 0; 801 + static int expr_opcode_arity(uint8_t op, int *target_count, const char **name) { 802 + *target_count = 0; 739 803 switch (op) { 740 804 case 0x71: *name = "ref_of"; return 1; 741 - case 0x72: *has_target = 1; *name = "add"; return 2; 742 - case 0x73: *has_target = 1; *name = "concat"; return 2; 743 - case 0x74: *has_target = 1; *name = "sub"; return 2; 805 + case 0x72: *target_count = 1; *name = "add"; return 2; 806 + case 0x73: *target_count = 1; *name = "concat"; return 2; 807 + case 0x74: *target_count = 1; *name = "sub"; return 2; 744 808 case 0x75: *name = "inc"; return 1; 745 809 case 0x76: *name = "dec"; return 1; 746 - case 0x77: *has_target = 1; *name = "mul"; return 2; 747 - case 0x78: *has_target = 1; *name = "div"; return 2; 748 - case 0x79: *has_target = 1; *name = "shl"; return 2; 749 - case 0x7a: *has_target = 1; *name = "shr"; return 2; 750 - case 0x7b: *has_target = 1; *name = "and"; return 2; 751 - case 0x7c: *has_target = 1; *name = "nand"; return 2; 752 - case 0x7d: *has_target = 1; *name = "or"; return 2; 753 - case 0x7e: *has_target = 1; *name = "nor"; return 2; 754 - case 0x7f: *has_target = 1; *name = "xor"; return 2; 755 - case 0x80: *has_target = 1; *name = "not"; return 1; 756 - case 0x81: *has_target = 1; *name = "find_set_left_bit"; return 1; 757 - case 0x82: *has_target = 1; *name = "find_set_right_bit"; return 1; 810 + case 0x77: *target_count = 1; *name = "mul"; return 2; 811 + case 0x78: *target_count = 2; *name = "div"; return 2; 812 + case 0x79: *target_count = 1; *name = "shl"; return 2; 813 + case 0x7a: *target_count = 1; *name = "shr"; return 2; 814 + case 0x7b: *target_count = 1; *name = "and"; return 2; 815 + case 0x7c: *target_count = 1; *name = "nand"; return 2; 816 + case 0x7d: *target_count = 1; *name = "or"; return 2; 817 + case 0x7e: *target_count = 1; *name = "nor"; return 2; 818 + case 0x7f: *target_count = 1; *name = "xor"; return 2; 819 + case 0x80: *target_count = 1; *name = "not"; return 1; 820 + case 0x81: *target_count = 1; *name = "find_set_left_bit"; return 1; 821 + case 0x82: *target_count = 1; *name = "find_set_right_bit"; return 1; 758 822 case 0x83: *name = "deref_of"; return 1; 759 - case 0x84: *has_target = 1; *name = "concat_res"; return 2; 760 - case 0x85: *has_target = 1; *name = "mod"; return 2; 823 + case 0x84: *target_count = 1; *name = "concat_res"; return 2; 824 + case 0x85: *target_count = 1; *name = "mod"; return 2; 761 825 case 0x86: *name = "notify"; return 2; 762 826 case 0x87: *name = "size_of"; return 1; 763 - case 0x88: *has_target = 1; *name = "index"; return 2; 827 + case 0x88: *target_count = 1; *name = "index"; return 2; 764 828 case 0x89: *name = "match"; return 6; 765 829 case 0x8e: *name = "object_type"; return 1; 766 830 case 0x90: *name = "land"; return 2; ··· 769 833 case 0x93: *name = "eq"; return 2; 770 834 case 0x94: *name = "gt"; return 2; 771 835 case 0x95: *name = "lt"; return 2; 772 - case 0x96: *has_target = 1; *name = "to_buffer"; return 1; 773 - case 0x97: *has_target = 1; *name = "to_decimal_string"; return 1; 774 - case 0x98: *has_target = 1; *name = "to_hex_string"; return 1; 775 - case 0x99: *has_target = 1; *name = "to_integer"; return 1; 776 - case 0x9c: *has_target = 1; *name = "to_string"; return 2; 777 - case 0x9d: *has_target = 1; *name = "copy_object"; return 1; 778 - case 0x9e: *has_target = 1; *name = "mid"; return 3; 836 + case 0x96: *target_count = 1; *name = "to_buffer"; return 1; 837 + case 0x97: *target_count = 1; *name = "to_decimal_string"; return 1; 838 + case 0x98: *target_count = 1; *name = "to_hex_string"; return 1; 839 + case 0x99: *target_count = 1; *name = "to_integer"; return 1; 840 + case 0x9c: *target_count = 1; *name = "to_string"; return 2; 841 + case 0x9d: *target_count = 1; *name = "copy_object"; return 1; 842 + case 0x9e: *target_count = 1; *name = "mid"; return 3; 779 843 default: return -1; 780 844 } 781 845 } ··· 1101 1165 n->len = tobi_rd_off(rd) - off; 1102 1166 return n; 1103 1167 } 1104 - int has_target = 0; 1168 + int target_count = 0; 1105 1169 const char *ename = NULL; 1106 - int arity = expr_opcode_arity(op, &has_target, &ename); 1170 + int arity = expr_opcode_arity(op, &target_count, &ename); 1107 1171 if (arity >= 0) { 1108 1172 tobi_ir *n = tobi_ir_new(TOBI_IR_EXPR, off, 0); 1109 1173 tobi_ir_set_name(n, ename); ··· 1114 1178 tobi_ir_add(n, arg); 1115 1179 } 1116 1180 } 1117 - if (has_target) { 1181 + for (int i = 0; i < target_count; i++) { 1118 1182 tobi_ir *target = parse_expr(p, rd, depth + 1); 1119 1183 if (target) { 1120 1184 tobi_ir_add(n, target); ··· 1165 1229 case 0x08: return parse_name(p, rd, depth, off); 1166 1230 case 0x10: return parse_pkg_named(p, rd, depth, TOBI_IR_SCOPE, "ScopeOp", off); 1167 1231 case 0x14: return parse_method(p, rd, depth, off); 1232 + case 0x15: return parse_external(p, rd, off); 1168 1233 case 0x5b: return parse_ext(p, rd, depth, off); 1169 1234 case 0x70: 1170 1235 rd->pos--; ··· 1266 1331 free(path); 1267 1332 free(name); 1268 1333 rd->pos = body_start + body_len; 1334 + continue; 1335 + } 1336 + if (op == 0x15) { 1337 + char *name = NULL; 1338 + if (tobi_nm_namestring(rd, &name)) { 1339 + uint8_t obj_type = 0; 1340 + uint8_t argc = 0; 1341 + if (tobi_rd_u8(rd, &obj_type) && tobi_rd_u8(rd, &argc) && obj_type == 0x08u) { 1342 + char *path = tobi_nm_resolve(p->scope, name); 1343 + method_add(p, path, name, argc & 0x07u); 1344 + free(path); 1345 + } 1346 + free(name); 1347 + } 1269 1348 continue; 1270 1349 } 1271 1350 if (op == 0x5b) {
+2
src/p.h
··· 13 13 size_t table_len; 14 14 size_t aml_off; 15 15 size_t aml_len; 16 + uint8_t checksum_sum; 17 + int checksum_valid; 16 18 } tobi_input_meta; 17 19 18 20 typedef struct tobi_parse_result {
+1
test/main.c
··· 4 4 struct ent { const char *name; int (*fn)(void); } tests[] = { 5 5 {"rd", t_rd}, {"nm", t_nm}, {"p", t_p}, {"ir", t_ir}, {"cf", t_cf}, 6 6 {"da", t_da}, {"dc", t_dc}, {"js", t_js}, {"bad", t_bad}, {"cli", t_cli}, 7 + {"prod", t_prod}, 7 8 }; 8 9 if (argc == 2) { 9 10 for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+1
test/t.h
··· 18 18 int t_js(void); 19 19 int t_bad(void); 20 20 int t_cli(void); 21 + int t_prod(void); 21 22 22 23 #endif
+14
test/t_cli.c
··· 84 84 T_STR(s, "digraph tobi_cfg"); 85 85 T_STR(s, "method"); 86 86 free(s); 87 + snprintf(args, sizeof(args), "--raw %s", path); 88 + s = run_capture(args, &st); 89 + T_CHECK(st == 0); 90 + T_STR(s, "checksum_sum=0x00"); 91 + T_STR(s, "checksum_valid=false"); 92 + free(s); 87 93 { 88 94 unsigned char use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05}; 89 95 unsigned char cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68}; ··· 105 111 s = run_capture("--version", &st); 106 112 T_CHECK(st == 0); 107 113 T_STR(s, "tobi"); 114 + free(s); 115 + snprintf(path, sizeof(path), "%s/sam/m0.aml", TOBI_SRC_DIR); 116 + snprintf(args, sizeof(args), "--json --dis %s", path); 117 + s = run_capture(args, &st); 118 + T_CHECK(st == 2); 119 + free(s); 120 + s = run_capture("--definitely-not-real", &st); 121 + T_CHECK(st == 2); 108 122 free(s); 109 123 snprintf(path, sizeof(path), "%s/sam/bad0.aml", TOBI_SRC_DIR); 110 124 snprintf(args, sizeof(args), "--strict %s", path);
+8
test/t_da.c
··· 14 14 T_STR(s, "StoreOp"); 15 15 free(s); 16 16 tobi_parse_result_free(&r); 17 + uint8_t buf[] = {0x08,'B','U','F','0',0x11,0x05,0x0a,0x02,0xaa,0xbb}; 18 + T_CHECK(tobi_parse(buf, sizeof(buf), 0, &r)); 19 + s = tobi_da_emit(buf, sizeof(buf), &r.meta); 20 + T_STR(s, "BufferOp"); 21 + T_STR(s, "BufferData len=2"); 22 + T_CHECK(strstr(s, "UnknownOp opcode=0xaa") == NULL); 23 + free(s); 24 + tobi_parse_result_free(&r); 17 25 uint8_t bad[] = {0xfe,0x14,0xff}; 18 26 T_CHECK(tobi_parse(bad, sizeof(bad), 0, &r)); 19 27 s = tobi_da_emit(bad, sizeof(bad), &r.meta);
+2
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, "\"checksum_sum\":0"); 13 + T_STR(s, "\"checksum_valid\":false"); 12 14 T_STR(s, "a\\\"b\\\\c"); 13 15 T_STR(s, "\"raw_opcode\":254"); 14 16 T_CHECK(strstr(s, ",}") == NULL);
+43
test/t_p.c
··· 39 39 fix_checksum(table, sizeof(table)); 40 40 T_CHECK(parse_ok(table, sizeof(table), &r)); 41 41 T_CHECK(r.meta.is_table && r.meta.aml_off == 36 && r.meta.aml_len == sizeof(m0)); 42 + T_CHECK(r.meta.checksum_valid && r.meta.checksum_sum == 0); 42 43 T_CHECK(r.root->child_len == 1 && r.root->child[0]->kind == TOBI_IR_METHOD); 43 44 T_CHECK(r.root->child[0]->off == 36); 44 45 T_CHECK(r.diag.len == 0); ··· 104 105 T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 105 106 tobi_parse_result_free(&r); 106 107 108 + uint8_t ext_call[] = { 109 + 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','X',0x0a,0x05, 110 + 0x15,'C','A','L','X',0x08,0x01 111 + }; 112 + T_CHECK(parse_ok(ext_call, sizeof(ext_call), &r)); 113 + T_CHECK(r.root->child_len == 2); 114 + use = r.root->child[0]; 115 + T_CHECK(use->child[0]->child[0]->child[0]->kind == TOBI_IR_CALL); 116 + T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 117 + T_CHECK(r.root->child[1]->kind == TOBI_IR_EXPR); 118 + T_CHECK(strcmp(r.root->child[1]->name, "external") == 0); 119 + tobi_parse_result_free(&r); 120 + 107 121 uint8_t use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05}; 108 122 uint8_t cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68}; 109 123 tobi_parse_input inputs[] = { ··· 167 181 T_CHECK(strcmp(r.root->child[1]->name, "acquire") == 0); 168 182 T_CHECK(r.root->child[2]->kind == TOBI_IR_REF); 169 183 T_CHECK(strcmp(r.root->child[2]->name, "Debug") == 0); 184 + tobi_parse_result_free(&r); 185 + 186 + uint8_t more_ext[] = { 187 + 0x5b,0x20,'T','B','L','0',0x60, 188 + 0x5b,0x33, 189 + 0x5b,0x1f, 190 + 0x0d,'D','S','D','T',0x00, 191 + 0x0d,'O','E','M',0x00, 192 + 0x0d,'T','A','B','L','E',0x00, 193 + 0x0d,'\\',0x00, 194 + 0x0d,'P','A','R','M',0x00, 195 + 0x60 196 + }; 197 + T_CHECK(parse_ok(more_ext, sizeof(more_ext), &r)); 198 + T_CHECK(r.diag.len == 0); 199 + T_CHECK(r.root->child_len == 3); 200 + T_CHECK(strcmp(r.root->child[0]->name, "load") == 0); 201 + T_CHECK(r.root->child[0]->child_len == 2); 202 + T_CHECK(strcmp(r.root->child[1]->name, "timer") == 0); 203 + T_CHECK(strcmp(r.root->child[2]->name, "load_table") == 0); 204 + T_CHECK(r.root->child[2]->child_len == 6); 205 + tobi_parse_result_free(&r); 206 + 207 + uint8_t divop[] = {0x78,0x0a,0x07,0x0a,0x02,0x60,0x61}; 208 + T_CHECK(parse_ok(divop, sizeof(divop), &r)); 209 + T_CHECK(r.root->child_len == 1); 210 + T_CHECK(r.root->child[0]->kind == TOBI_IR_EXPR); 211 + T_CHECK(strcmp(r.root->child[0]->name, "div") == 0); 212 + T_CHECK(r.root->child[0]->child_len == 4); 170 213 tobi_parse_result_free(&r); 171 214 return 0; 172 215 }
+96
test/t_prod.c
··· 1 + #include "t.h" 2 + 3 + #include "cf.h" 4 + #include "dc.h" 5 + #include "js.h" 6 + #include "p.h" 7 + 8 + static void set_len(uint8_t *b, size_t n) { 9 + uint32_t v = (uint32_t)n; 10 + b[4] = (uint8_t)(v & 0xffu); 11 + b[5] = (uint8_t)((v >> 8) & 0xffu); 12 + b[6] = (uint8_t)((v >> 16) & 0xffu); 13 + b[7] = (uint8_t)((v >> 24) & 0xffu); 14 + } 15 + 16 + static void fix_sum(uint8_t *b, size_t n) { 17 + unsigned sum = 0; 18 + b[9] = 0; 19 + for (size_t i = 0; i < n; i++) { 20 + sum = (sum + b[i]) & 0xffu; 21 + } 22 + b[9] = (uint8_t)((256u - sum) & 0xffu); 23 + } 24 + 25 + int t_prod(void) { 26 + uint8_t m0[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 27 + uint8_t table[36 + sizeof(m0) + 4]; 28 + memset(table, 0, sizeof(table)); 29 + memcpy(table, "DSDT", 4); 30 + set_len(table, 36 + sizeof(m0)); 31 + memcpy(table + 36, m0, sizeof(m0)); 32 + table[36 + sizeof(m0)] = 0xfe; 33 + table[36 + sizeof(m0) + 1] = 0xfe; 34 + fix_sum(table, 36 + sizeof(m0)); 35 + tobi_parse_result r; 36 + T_CHECK(tobi_parse(table, sizeof(table), 1, &r)); 37 + T_CHECK(r.meta.is_table); 38 + T_CHECK(r.meta.table_len == 36 + sizeof(m0)); 39 + T_CHECK(r.meta.aml_len == sizeof(m0)); 40 + T_CHECK(r.root->child_len == 1); 41 + T_CHECK(!tobi_diag_has_error(&r.diag)); 42 + tobi_parse_result_free(&r); 43 + 44 + table[9] ^= 0x5au; 45 + T_CHECK(tobi_parse(table, sizeof(table), 0, &r)); 46 + T_CHECK(!tobi_diag_has_error(&r.diag)); 47 + T_CHECK(!r.meta.checksum_valid); 48 + T_CHECK(r.diag.len == 1); 49 + tobi_parse_result_free(&r); 50 + 51 + uint8_t m1[] = {0x14,0x15,'I','F','E','0',0x01,0xa0,0x06,0x68,0x70,0x0a,0x01,0x60,0xa1,0x05,0x70,0x0a,0x02,0x60,0xa4,0x60}; 52 + T_CHECK(tobi_parse(m1, sizeof(m1), 0, &r)); 53 + T_CHECK(tobi_cf_recover(r.root, &r.diag)); 54 + char *a = tobi_dc_emit(r.root, &r.diag); 55 + char *b = tobi_dc_emit(r.root, &r.diag); 56 + T_CHECK(strcmp(a, b) == 0); 57 + free(a); 58 + free(b); 59 + a = tobi_js_emit(&r); 60 + b = tobi_js_emit(&r); 61 + T_CHECK(strcmp(a, b) == 0); 62 + T_CHECK(strstr(a, ",}") == NULL); 63 + T_CHECK(strstr(a, ",]") == NULL); 64 + free(a); 65 + free(b); 66 + a = tobi_cf_dot(r.root); 67 + b = tobi_cf_dot(r.root); 68 + T_CHECK(strcmp(a, b) == 0); 69 + free(a); 70 + free(b); 71 + tobi_parse_result_free(&r); 72 + 73 + uint8_t hostile[256]; 74 + for (size_t i = 0; i < sizeof(hostile); i++) { 75 + hostile[i] = (uint8_t)i; 76 + } 77 + T_CHECK(tobi_parse(hostile, sizeof(hostile), 0, &r)); 78 + tobi_parse_result_free(&r); 79 + 80 + uint8_t use_file[] = {0x14,0x0d,'U','S','E','X',0x00,0xa4,'C','A','L','X',0x0a,0x33}; 81 + uint8_t ext_file[] = {0x15,'C','A','L','X',0x08,0x01}; 82 + tobi_parse_input inputs[] = { 83 + {use_file, sizeof(use_file), "usex.aml"}, 84 + {ext_file, sizeof(ext_file), "extern.aml"} 85 + }; 86 + T_CHECK(tobi_parse_multi(inputs, 2, 0, &r)); 87 + T_CHECK(r.root->child_len == 2); 88 + T_CHECK(r.root->child[0]->child_len == 1); 89 + tobi_ir *ret = r.root->child[0]->child[0]->child[0]->child[0]; 90 + T_CHECK(ret->kind == TOBI_IR_RETURN); 91 + T_CHECK(ret->child_len == 1); 92 + T_CHECK(ret->child[0]->kind == TOBI_IR_CALL); 93 + T_CHECK(ret->child[0]->child_len == 1); 94 + tobi_parse_result_free(&r); 95 + return 0; 96 + }