ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

Model AML field units with bit offsets widths access policy and backing regions

+104 -6
+9 -4
src/dc.c
··· 266 266 break; 267 267 case TOBI_IR_FIELD: 268 268 indent(sb, ind); 269 - tobi_sb_printf(sb, "%s %s flags=0x%llx {\n", n->str ? n->str : "field", 270 - n->name ? n->name : "<field>", (unsigned long long)n->value); 269 + tobi_sb_printf(sb, "%s %s", n->str ? n->str : "field", n->name ? n->name : "<field>"); 270 + if (n->target) { 271 + tobi_sb_printf(sb, " backing=%s", n->target); 272 + } 273 + tobi_sb_printf(sb, " flags=0x%llx access=%u lock=%u update=%u {\n", 274 + (unsigned long long)n->value, n->access_type, n->lock_rule, n->update_rule); 271 275 for (size_t i = 0; i < n->child_len; i++) { 272 276 indent(sb, ind + 1); 273 277 if (n->child[i]->kind == TOBI_IR_FIELD_ELEM) { 274 - tobi_sb_printf(sb, "%s: %llu", n->child[i]->name ? n->child[i]->name : "<field>", 275 - (unsigned long long)n->child[i]->value); 278 + tobi_sb_printf(sb, "%s @%llu:%llu", n->child[i]->name ? n->child[i]->name : "<field>", 279 + (unsigned long long)n->child[i]->bit_off, 280 + (unsigned long long)n->child[i]->bit_len); 276 281 if (n->child[i]->str) { 277 282 tobi_sb_printf(sb, " /* %s */", n->child[i]->str); 278 283 }
+6
src/ir.c
··· 23 23 free(node->name); 24 24 free(node->path); 25 25 free(node->str); 26 + free(node->target); 26 27 free(node); 27 28 } 28 29 ··· 50 51 void tobi_ir_set_str(tobi_ir *node, const char *s) { 51 52 free(node->str); 52 53 node->str = tobi_xstrdup(s ? s : ""); 54 + } 55 + 56 + void tobi_ir_set_target(tobi_ir *node, const char *s) { 57 + free(node->target); 58 + node->target = tobi_xstrdup(s ? s : ""); 53 59 } 54 60 55 61 const char *tobi_ir_kind_name(tobi_ir_kind kind) {
+8
src/ir.h
··· 43 43 char *name; 44 44 char *path; 45 45 char *str; 46 + char *target; 46 47 uint64_t value; 48 + uint64_t bit_off; 49 + uint64_t bit_len; 47 50 uint32_t raw_op; 51 + unsigned access_type; 52 + unsigned lock_rule; 53 + unsigned update_rule; 48 54 unsigned method_args; 49 55 unsigned method_serialized; 50 56 unsigned method_sync; ··· 64 70 void tobi_ir_set_path(tobi_ir *node, const char *s); 65 71 66 72 void tobi_ir_set_str(tobi_ir *node, const char *s); 73 + 74 + void tobi_ir_set_target(tobi_ir *node, const char *s); 67 75 68 76 const char *tobi_ir_kind_name(tobi_ir_kind kind); 69 77
+17
src/js.c
··· 35 35 tobi_sb_add(sb, "\"string\":"); 36 36 tobi_json_string(sb, n->str); 37 37 } 38 + if (n->target) { 39 + comma(sb, &first); 40 + tobi_sb_add(sb, "\"target\":"); 41 + tobi_json_string(sb, n->target); 42 + } 38 43 if (n->kind == TOBI_IR_INTEGER || n->kind == TOBI_IR_PACKAGE || n->kind == TOBI_IR_FIELD || 39 44 n->kind == TOBI_IR_FIELD_ELEM || n->kind == TOBI_IR_CALL || n->kind == TOBI_IR_OPREGION || 40 45 n->kind == TOBI_IR_RESOURCE) { ··· 52 57 tobi_sb_printf(sb, "\"serialized\":%s", n->method_serialized ? "true" : "false"); 53 58 comma(sb, &first); 54 59 tobi_sb_printf(sb, "\"sync\":%u", n->method_sync); 60 + } 61 + if (n->bit_len || n->access_type || n->lock_rule || n->update_rule) { 62 + comma(sb, &first); 63 + tobi_sb_printf(sb, "\"bit_offset\":%llu", (unsigned long long)n->bit_off); 64 + comma(sb, &first); 65 + tobi_sb_printf(sb, "\"bit_length\":%llu", (unsigned long long)n->bit_len); 66 + comma(sb, &first); 67 + tobi_sb_printf(sb, "\"access_type\":%u", n->access_type); 68 + comma(sb, &first); 69 + tobi_sb_printf(sb, "\"lock_rule\":%u", n->lock_rule); 70 + comma(sb, &first); 71 + tobi_sb_printf(sb, "\"update_rule\":%u", n->update_rule); 55 72 } 56 73 comma(sb, &first); 57 74 tobi_sb_add(sb, "\"children\":[");
+45 -2
src/p.c
··· 324 324 return n; 325 325 } 326 326 327 - static void parse_field_list(parser *p, tobi_rd *body, tobi_ir *n) { 327 + static void apply_field_meta(tobi_ir *e, uint64_t bit_off, uint64_t bit_len, uint8_t flags) { 328 + e->bit_off = bit_off; 329 + e->bit_len = bit_len; 330 + e->access_type = flags & 0x0fu; 331 + e->lock_rule = (flags >> 4) & 0x01u; 332 + e->update_rule = (flags >> 5) & 0x03u; 333 + } 334 + 335 + static void parse_field_list(parser *p, tobi_rd *body, tobi_ir *n, uint8_t flags) { 336 + uint64_t bit_pos = 0; 328 337 while (tobi_rd_left(body) > 0) { 329 338 size_t foff = tobi_rd_off(body); 330 339 uint8_t b = 0; ··· 342 351 tobi_ir *e = tobi_ir_new(TOBI_IR_FIELD_ELEM, foff, tobi_rd_off(body) - foff); 343 352 tobi_ir_set_name(e, "<reserved>"); 344 353 e->value = bits; 354 + apply_field_meta(e, bit_pos, bits, flags); 345 355 tobi_ir_add(n, e); 356 + bit_pos += bits; 346 357 continue; 347 358 } 348 359 if (b == 0x01) { ··· 395 406 tobi_ir *e = tobi_ir_new(TOBI_IR_FIELD_ELEM, foff, tobi_rd_off(body) - foff); 396 407 tobi_ir_set_name(e, fname); 397 408 e->value = bits; 409 + apply_field_meta(e, bit_pos, bits, flags); 398 410 ns_declare_name(p, TOBI_NS_FIELD, fname, foff, 0, 0, 0, NULL); 399 411 tobi_ir_add(n, e); 412 + bit_pos += bits; 400 413 free(fname); 401 414 } 402 415 } ··· 419 432 tobi_ir_set_str(n, label); 420 433 if (raw == 0x5b81u) { 421 434 tobi_ir_set_name(n, first); 435 + char *path = tobi_ns_resolve_path(p->ns, p->scope, first); 436 + tobi_ir_set_target(n, path); 437 + free(path); 422 438 } else if (raw == 0x5b86u) { 423 439 char *data = NULL; 424 440 if (!parse_namestring_diag(p, &body, &data)) { ··· 432 448 tobi_sb_add(&nm, ","); 433 449 tobi_sb_add(&nm, data); 434 450 tobi_ir_set_name(n, nm.buf); 451 + tobi_sb target; 452 + tobi_sb_init(&target); 453 + char *idx_path = tobi_ns_resolve_path(p->ns, p->scope, first); 454 + char *data_path = tobi_ns_resolve_path(p->ns, p->scope, data); 455 + tobi_sb_add(&target, "index="); 456 + tobi_sb_add(&target, idx_path); 457 + tobi_sb_add(&target, " data="); 458 + tobi_sb_add(&target, data_path); 459 + tobi_ir_set_target(n, target.buf); 460 + free(idx_path); 461 + free(data_path); 462 + tobi_sb_free(&target); 435 463 tobi_sb_free(&nm); 436 464 free(data); 437 465 } else { ··· 447 475 tobi_sb_add(&nm, ","); 448 476 tobi_sb_add(&nm, bank); 449 477 tobi_ir_set_name(n, nm.buf); 478 + tobi_sb target; 479 + tobi_sb_init(&target); 480 + char *region_path = tobi_ns_resolve_path(p->ns, p->scope, first); 481 + char *bank_path = tobi_ns_resolve_path(p->ns, p->scope, bank); 482 + tobi_sb_add(&target, "region="); 483 + tobi_sb_add(&target, region_path); 484 + tobi_sb_add(&target, " bank="); 485 + tobi_sb_add(&target, bank_path); 486 + tobi_ir_set_target(n, target.buf); 487 + free(region_path); 488 + free(bank_path); 489 + tobi_sb_free(&target); 450 490 tobi_sb_free(&nm); 451 491 free(bank); 452 492 tobi_ir *bank_value = parse_expr(p, &body, depth + 1); ··· 459 499 diag(p, TOBI_DIAG_ERROR, tobi_rd_off(&body), "truncated field flags"); 460 500 } 461 501 n->value = flags; 462 - parse_field_list(p, &body, n); 502 + n->access_type = flags & 0x0fu; 503 + n->lock_rule = (flags >> 4) & 0x01u; 504 + n->update_rule = (flags >> 5) & 0x03u; 505 + parse_field_list(p, &body, n, flags); 463 506 rd->pos = body_start + body_len; 464 507 free(first); 465 508 return n;
+12
test/t_js.c
··· 31 31 T_CHECK(strstr(s, ",]") == NULL); 32 32 free(s); 33 33 tobi_parse_result_free(&r); 34 + 35 + uint8_t fld[] = {0x5b,0x80,'R','E','G','0',0x01,0x0a,0x10,0x0a,0x04,0x5b,0x81,0x0b,'R','E','G','0',0x00,'F','L','D','0',0x08}; 36 + T_CHECK(tobi_parse(fld, sizeof(fld), 0, &r)); 37 + s = tobi_js_emit(&r); 38 + T_STR(s, "\"target\":\"\\\\REG0\""); 39 + T_STR(s, "\"bit_offset\":0"); 40 + T_STR(s, "\"bit_length\":8"); 41 + T_STR(s, "\"access_type\":0"); 42 + T_CHECK(strstr(s, ",}") == NULL); 43 + T_CHECK(strstr(s, ",]") == NULL); 44 + free(s); 45 + tobi_parse_result_free(&r); 34 46 return 0; 35 47 }
+7
test/t_p.c
··· 84 84 T_CHECK(r.root->child_len == 2); 85 85 T_CHECK(r.root->child[1]->kind == TOBI_IR_FIELD); 86 86 T_CHECK(r.root->child[1]->child_len == 1); 87 + T_STR(r.root->child[1]->target, "\\REG0"); 88 + T_CHECK(r.root->child[1]->access_type == 0); 87 89 T_CHECK(tobi_ns_find_const(&r.ns, "\\REG0") != NULL); 88 90 const tobi_ns_ent *fe = tobi_ns_find_const(&r.ns, "\\FLD0"); 89 91 T_CHECK(fe != NULL && fe->kind == TOBI_NS_FIELD); 92 + T_CHECK(r.root->child[1]->child[0]->bit_off == 0); 93 + T_CHECK(r.root->child[1]->child[0]->bit_len == 8); 90 94 T_CHECK(r.diag.len == 0); 91 95 tobi_parse_result_free(&r); 92 96 ··· 95 99 T_CHECK(r.root->child_len == 1); 96 100 T_CHECK(r.root->child[0]->kind == TOBI_IR_FIELD); 97 101 T_CHECK(strcmp(r.root->child[0]->str, "IndexField") == 0); 102 + T_STR(r.root->child[0]->target, "index=\\IDX0 data=\\DAT0"); 98 103 T_CHECK(r.root->child[0]->child_len == 1); 99 104 T_CHECK(strcmp(r.root->child[0]->child[0]->name, "IFLD") == 0); 105 + T_CHECK(r.root->child[0]->child[0]->bit_len == 8); 100 106 tobi_parse_result_free(&r); 101 107 102 108 uint8_t bfld[] = {0x5b,0x87,0x11,'R','E','G','0','B','N','K','0',0x0a,0x01,0x00,'B','F','L','D',0x08}; ··· 104 110 T_CHECK(r.root->child_len == 1); 105 111 T_CHECK(r.root->child[0]->kind == TOBI_IR_FIELD); 106 112 T_CHECK(strcmp(r.root->child[0]->str, "BankField") == 0); 113 + T_STR(r.root->child[0]->target, "region=\\REG0 bank=\\BNK0"); 107 114 T_CHECK(r.root->child[0]->child_len == 2); 108 115 T_CHECK(r.root->child[0]->child[0]->kind == TOBI_IR_INTEGER); 109 116 T_CHECK(r.root->child[0]->child[1]->kind == TOBI_IR_FIELD_ELEM);