ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

Resolve operation region address spaces and field byte layout semantics

+96 -10
+2 -1
src/dc.c
··· 258 258 break; 259 259 case TOBI_IR_OPREGION: 260 260 indent(sb, ind); 261 - tobi_sb_printf(sb, "opregion %s space=%llu offset=", n->path ? n->path : n->name, (unsigned long long)n->value); 261 + tobi_sb_printf(sb, "opregion %s space=%s(%llu) offset=", n->path ? n->path : n->name, 262 + n->str ? n->str : "unknown", (unsigned long long)n->value); 262 263 expr(sb, n->child_len > 0 ? n->child[0] : NULL); 263 264 tobi_sb_add(sb, " length="); 264 265 expr(sb, n->child_len > 1 ? n->child[1] : NULL);
+3
src/nm.h
··· 28 28 char *target; 29 29 tobi_ns_kind kind; 30 30 size_t off; 31 + uint64_t region_offset; 32 + uint64_t region_len; 31 33 unsigned args; 32 34 unsigned flags; 35 + int has_region_range; 33 36 int external; 34 37 } tobi_ns_ent; 35 38
+82 -7
src/p.c
··· 89 89 } 90 90 } 91 91 92 + static const char *region_space_name(unsigned space) { 93 + switch (space) { 94 + case 0x00: return "SystemMemory"; 95 + case 0x01: return "SystemIO"; 96 + case 0x02: return "PCI_Config"; 97 + case 0x03: return "EmbeddedControl"; 98 + case 0x04: return "SMBus"; 99 + case 0x05: return "SystemCMOS"; 100 + case 0x06: return "PCIBarTarget"; 101 + case 0x07: return "IPMI"; 102 + case 0x08: return "GPIO"; 103 + case 0x09: return "GenericSerialBus"; 104 + case 0x0a: return "PCC"; 105 + default: return "OEM"; 106 + } 107 + } 108 + 92 109 static void ns_declare_path(parser *p, tobi_ns_kind kind, const char *path, size_t off, 93 110 unsigned args, unsigned flags, int external, const char *target) { 94 111 if (!p->ns || !path || path[0] == '\0') { ··· 100 117 diag(p, p->strict ? TOBI_DIAG_ERROR : TOBI_DIAG_WARN, off, 101 118 "duplicate namespace object %s at %s", tobi_ns_kind_name(kind), path); 102 119 } 120 + } 121 + 122 + static void ns_set_region_range(parser *p, const char *path, uint64_t off, uint64_t len) { 123 + tobi_ns_ent *e = tobi_ns_find(p->ns, path); 124 + if (!e) { 125 + return; 126 + } 127 + e->region_offset = off; 128 + e->region_len = len; 129 + e->has_region_range = 1; 103 130 } 104 131 105 132 static void ns_declare_name(parser *p, tobi_ns_kind kind, const char *name, size_t off, ··· 365 392 e->update_rule = (flags >> 5) & 0x03u; 366 393 } 367 394 368 - static void parse_field_list(parser *p, tobi_rd *body, tobi_ir *n, uint8_t flags) { 395 + static char *field_target_meta(parser *p, const char *prefix, const char *path) { 396 + const tobi_ns_ent *e = tobi_ns_find_const(p->ns, path); 397 + tobi_sb sb; 398 + tobi_sb_init(&sb); 399 + tobi_sb_add(&sb, prefix); 400 + tobi_sb_add(&sb, path); 401 + if (e && e->kind == TOBI_NS_OPREGION) { 402 + tobi_sb_printf(&sb, " space=%s", region_space_name(e->flags)); 403 + if (e->has_region_range) { 404 + tobi_sb_printf(&sb, " byte_offset=0x%llx byte_length=0x%llx", 405 + (unsigned long long)e->region_offset, 406 + (unsigned long long)e->region_len); 407 + } 408 + } 409 + return tobi_sb_take(&sb); 410 + } 411 + 412 + static void parse_field_list(parser *p, tobi_rd *body, tobi_ir *n, uint8_t flags, 413 + const tobi_ns_ent *region) { 369 414 uint64_t bit_pos = 0; 370 415 while (tobi_rd_left(body) > 0) { 371 416 size_t foff = tobi_rd_off(body); ··· 440 485 tobi_ir_set_name(e, fname); 441 486 e->value = bits; 442 487 apply_field_meta(e, bit_pos, bits, flags); 488 + if (n->target) { 489 + tobi_sb target; 490 + tobi_sb_init(&target); 491 + tobi_sb_add(&target, n->target); 492 + tobi_sb_printf(&target, " field_bit=%llu field_bytes=%llu", 493 + (unsigned long long)bit_pos, 494 + (unsigned long long)((bits + 7u) / 8u)); 495 + if (region && region->has_region_range && 496 + region->region_offset <= UINT64_MAX / 8u && 497 + bit_pos <= UINT64_MAX - (region->region_offset * 8u)) { 498 + uint64_t abs_bit = (region->region_offset * 8u) + bit_pos; 499 + tobi_sb_printf(&target, " absolute_bit=0x%llx absolute_byte=0x%llx absolute_bytes=0x%llx", 500 + (unsigned long long)abs_bit, 501 + (unsigned long long)(abs_bit / 8u), 502 + (unsigned long long)((bits + 7u) / 8u)); 503 + } 504 + tobi_ir_set_target(e, target.buf); 505 + tobi_sb_free(&target); 506 + } 443 507 ns_declare_name(p, TOBI_NS_FIELD, fname, foff, 0, 0, 0, NULL); 444 508 tobi_ir_add(n, e); 445 509 bit_pos += bits; ··· 463 527 } 464 528 tobi_ir *n = tobi_ir_new(TOBI_IR_FIELD, op_start, whole_len); 465 529 tobi_ir_set_str(n, label); 530 + const tobi_ns_ent *backing_region = NULL; 466 531 if (raw == 0x5b81u) { 467 532 tobi_ir_set_name(n, first); 468 533 char *path = tobi_ns_resolve_path(p->ns, p->scope, first); 469 - tobi_ir_set_target(n, path); 534 + char *target = field_target_meta(p, "region=", path); 535 + tobi_ir_set_target(n, target); 536 + backing_region = tobi_ns_find_const(p->ns, path); 537 + free(target); 470 538 free(path); 471 539 } else if (raw == 0x5b86u) { 472 540 char *data = NULL; ··· 485 553 tobi_sb_init(&target); 486 554 char *idx_path = tobi_ns_resolve_path(p->ns, p->scope, first); 487 555 char *data_path = tobi_ns_resolve_path(p->ns, p->scope, data); 488 - tobi_sb_add(&target, "index="); 489 - tobi_sb_add(&target, idx_path); 556 + char *idx_meta = field_target_meta(p, "index=", idx_path); 557 + tobi_sb_add(&target, idx_meta); 490 558 tobi_sb_add(&target, " data="); 491 559 tobi_sb_add(&target, data_path); 492 560 tobi_ir_set_target(n, target.buf); 561 + free(idx_meta); 493 562 free(idx_path); 494 563 free(data_path); 495 564 tobi_sb_free(&target); ··· 512 581 tobi_sb_init(&target); 513 582 char *region_path = tobi_ns_resolve_path(p->ns, p->scope, first); 514 583 char *bank_path = tobi_ns_resolve_path(p->ns, p->scope, bank); 515 - tobi_sb_add(&target, "region="); 516 - tobi_sb_add(&target, region_path); 584 + char *region_meta = field_target_meta(p, "region=", region_path); 585 + backing_region = tobi_ns_find_const(p->ns, region_path); 586 + tobi_sb_add(&target, region_meta); 517 587 tobi_sb_add(&target, " bank="); 518 588 tobi_sb_add(&target, bank_path); 519 589 tobi_ir_set_target(n, target.buf); 590 + free(region_meta); 520 591 free(region_path); 521 592 free(bank_path); 522 593 tobi_sb_free(&target); ··· 535 606 n->access_type = flags & 0x0fu; 536 607 n->lock_rule = (flags >> 4) & 0x01u; 537 608 n->update_rule = (flags >> 5) & 0x03u; 538 - parse_field_list(p, &body, n, flags); 609 + parse_field_list(p, &body, n, flags, backing_region); 539 610 rd->pos = body_start + body_len; 540 611 free(first); 541 612 return n; ··· 704 775 tobi_ir_set_path(n, path); 705 776 ns_declare_path(p, TOBI_NS_OPREGION, path, op_start, 0, space, 0, NULL); 706 777 n->value = space; 778 + tobi_ir_set_str(n, region_space_name(space)); 707 779 tobi_ir *off = parse_expr(p, rd, depth + 1); 708 780 tobi_ir *len = parse_expr(p, rd, depth + 1); 709 781 if (off) { ··· 711 783 } 712 784 if (len) { 713 785 tobi_ir_add(n, len); 786 + } 787 + if (n->child_len >= 2 && n->child[0]->kind == TOBI_IR_INTEGER && n->child[1]->kind == TOBI_IR_INTEGER) { 788 + ns_set_region_range(p, path, n->child[0]->value, n->child[1]->value); 714 789 } 715 790 n->len = tobi_rd_off(rd) - op_start; 716 791 free(path);
+2 -1
test/t_js.c
··· 39 39 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}; 40 40 T_CHECK(tobi_parse(fld, sizeof(fld), 0, &r)); 41 41 s = tobi_js_emit(&r); 42 - T_STR(s, "\"target\":\"\\\\REG0\""); 42 + T_STR(s, "\"target\":\"region=\\\\REG0 space=SystemIO"); 43 43 T_STR(s, "\"bit_offset\":0"); 44 44 T_STR(s, "\"bit_length\":8"); 45 45 T_STR(s, "\"access_type\":0"); 46 + T_STR(s, "absolute_byte=0x10"); 46 47 T_CHECK(strstr(s, ",}") == NULL); 47 48 T_CHECK(strstr(s, ",]") == NULL); 48 49 free(s);
+7 -1
test/t_p.c
··· 96 96 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}; 97 97 T_CHECK(parse_ok(fld, sizeof(fld), &r)); 98 98 T_CHECK(r.root->child_len == 2); 99 + T_STR(r.root->child[0]->str, "SystemIO"); 99 100 T_CHECK(r.root->child[1]->kind == TOBI_IR_FIELD); 100 101 T_CHECK(r.root->child[1]->child_len == 1); 101 102 T_STR(r.root->child[1]->target, "\\REG0"); 103 + T_STR(r.root->child[1]->target, "space=SystemIO"); 104 + T_STR(r.root->child[1]->target, "byte_offset=0x10"); 102 105 T_CHECK(r.root->child[1]->access_type == 0); 103 106 T_CHECK(tobi_ns_find_const(&r.ns, "\\REG0") != NULL); 104 107 const tobi_ns_ent *fe = tobi_ns_find_const(&r.ns, "\\FLD0"); 105 108 T_CHECK(fe != NULL && fe->kind == TOBI_NS_FIELD); 106 109 T_CHECK(r.root->child[1]->child[0]->bit_off == 0); 107 110 T_CHECK(r.root->child[1]->child[0]->bit_len == 8); 111 + T_STR(r.root->child[1]->child[0]->target, "field_bit=0"); 112 + T_STR(r.root->child[1]->child[0]->target, "absolute_byte=0x10"); 108 113 T_CHECK(r.diag.len == 0); 109 114 tobi_parse_result_free(&r); 110 115 ··· 124 129 T_CHECK(r.root->child_len == 1); 125 130 T_CHECK(r.root->child[0]->kind == TOBI_IR_FIELD); 126 131 T_CHECK(strcmp(r.root->child[0]->str, "BankField") == 0); 127 - T_STR(r.root->child[0]->target, "region=\\REG0 bank=\\BNK0"); 132 + T_STR(r.root->child[0]->target, "region=\\REG0"); 133 + T_STR(r.root->child[0]->target, "bank=\\BNK0"); 128 134 T_CHECK(r.root->child[0]->child_len == 2); 129 135 T_CHECK(r.root->child[0]->child[0]->kind == TOBI_IR_INTEGER); 130 136 T_CHECK(r.root->child[0]->child[1]->kind == TOBI_IR_FIELD_ELEM);