ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

tobi / test / t_p.c
14 kB 328 lines
1#include "t.h" 2 3#include "p.h" 4 5static int parse_ok(const uint8_t *b, size_t n, tobi_parse_result *r) { 6 return tobi_parse(b, n, 0, r) && r->root != NULL; 7} 8 9static void fix_checksum(uint8_t *b, size_t n) { 10 unsigned sum = 0; 11 b[9] = 0; 12 for (size_t i = 0; i < n; i++) { 13 sum = (sum + b[i]) & 0xffu; 14 } 15 b[9] = (uint8_t)((256u - sum) & 0xffu); 16} 17 18int t_p(void) { 19 uint8_t m0[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 20 tobi_parse_result r; 21 T_CHECK(parse_ok(m0, sizeof(m0), &r)); 22 T_CHECK(r.root->child_len == 1); 23 tobi_ir *m = r.root->child[0]; 24 T_CHECK(m->kind == TOBI_IR_METHOD && m->method_args == 1); 25 T_CHECK(m->child_len == 1 && m->child[0]->child_len == 2); 26 T_CHECK(m->child[0]->child[0]->kind == TOBI_IR_STORE); 27 T_CHECK(m->child[0]->child[1]->kind == TOBI_IR_RETURN); 28 tobi_parse_result_free(&r); 29 30 uint8_t table[36 + sizeof(m0)]; 31 memset(table, 0, sizeof(table)); 32 memcpy(table, "DSDT", 4); 33 uint32_t table_len = (uint32_t)sizeof(table); 34 table[4] = (uint8_t)(table_len & 0xffu); 35 table[5] = (uint8_t)((table_len >> 8) & 0xffu); 36 table[6] = (uint8_t)((table_len >> 16) & 0xffu); 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; 44 memcpy(table + 36, m0, sizeof(m0)); 45 fix_checksum(table, sizeof(table)); 46 T_CHECK(parse_ok(table, sizeof(table), &r)); 47 T_CHECK(r.meta.is_table && r.meta.aml_off == 36 && r.meta.aml_len == sizeof(m0)); 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); 57 T_CHECK(r.root->child_len == 1 && r.root->child[0]->kind == TOBI_IR_METHOD); 58 T_CHECK(r.root->child[0]->off == 36); 59 T_CHECK(r.diag.len == 0); 60 tobi_parse_result_free(&r); 61 62 uint8_t nested[] = {0x10,0x14,'\\','_','S','B','_',0x5b,0x82,0x0c,'D','E','V','0',0x14,0x06,'M','0','0','0',0x00}; 63 T_CHECK(parse_ok(nested, sizeof(nested), &r)); 64 T_CHECK(r.root->child[0]->kind == TOBI_IR_SCOPE); 65 T_CHECK(r.root->child[0]->child[0]->child[0]->kind == TOBI_IR_DEVICE); 66 tobi_parse_result_free(&r); 67 68 uint8_t objs[] = {0x08,'B','U','F','0',0x11,0x05,0x0a,0x02,0xaa,0xbb,0x08,'P','K','G','0',0x12,0x06,0x02,0x0a,0x01,0x0a,0x02}; 69 T_CHECK(parse_ok(objs, sizeof(objs), &r)); 70 T_CHECK(r.root->child_len == 2); 71 T_CHECK(r.root->child[0]->child[0]->kind == TOBI_IR_BUFFER); 72 T_CHECK(r.root->child[1]->child[0]->kind == TOBI_IR_PACKAGE); 73 tobi_parse_result_free(&r); 74 75 uint8_t crs[] = {0x08,'C','R','S','0',0x11,0x05,0x0a,0x02,0x79,0x00}; 76 T_CHECK(parse_ok(crs, sizeof(crs), &r)); 77 T_CHECK(r.root->child_len == 1); 78 T_CHECK(r.root->child[0]->child[0]->kind == TOBI_IR_BUFFER); 79 T_STR(r.root->child[0]->child[0]->str, "EndTag"); 80 T_CHECK(r.root->child[0]->child[0]->child_len == 2); 81 T_CHECK(r.root->child[0]->child[0]->child[1]->kind == TOBI_IR_RESOURCE); 82 T_CHECK(strcmp(r.root->child[0]->child[0]->child[1]->name, "EndTag") == 0); 83 T_STR(r.root->child[0]->child[0]->child[1]->str, "checksum=0x0"); 84 tobi_parse_result_free(&r); 85 86 uint8_t io_res[] = {0x11,0x0d,0x0a,0x09,0x47,0x01,0x00,0x10,0xff,0x10,0x01,0x08,0x79,0x00}; 87 T_CHECK(parse_ok(io_res, sizeof(io_res), &r)); 88 T_CHECK(r.root->child_len == 1); 89 T_CHECK(r.root->child[0]->kind == TOBI_IR_BUFFER); 90 T_CHECK(r.root->child[0]->child_len == 3); 91 T_CHECK(r.root->child[0]->child[1]->kind == TOBI_IR_RESOURCE); 92 T_CHECK(strcmp(r.root->child[0]->child[1]->name, "IO") == 0); 93 T_STR(r.root->child[0]->child[1]->str, "min=0x1000"); 94 tobi_parse_result_free(&r); 95 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 T_CHECK(parse_ok(fld, sizeof(fld), &r)); 98 T_CHECK(r.root->child_len == 2); 99 T_STR(r.root->child[0]->str, "SystemIO"); 100 T_CHECK(r.root->child[1]->kind == TOBI_IR_FIELD); 101 T_CHECK(r.root->child[1]->child_len == 1); 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"); 105 T_CHECK(r.root->child[1]->access_type == 0); 106 T_CHECK(tobi_ns_find_const(&r.ns, "\\REG0") != NULL); 107 const tobi_ns_ent *fe = tobi_ns_find_const(&r.ns, "\\FLD0"); 108 T_CHECK(fe != NULL && fe->kind == TOBI_NS_FIELD); 109 T_CHECK(r.root->child[1]->child[0]->bit_off == 0); 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"); 113 T_CHECK(r.diag.len == 0); 114 tobi_parse_result_free(&r); 115 116 uint8_t ifld[] = {0x5b,0x86,0x0f,'I','D','X','0','D','A','T','0',0x00,'I','F','L','D',0x08}; 117 T_CHECK(parse_ok(ifld, sizeof(ifld), &r)); 118 T_CHECK(r.root->child_len == 1); 119 T_CHECK(r.root->child[0]->kind == TOBI_IR_FIELD); 120 T_CHECK(strcmp(r.root->child[0]->str, "IndexField") == 0); 121 T_STR(r.root->child[0]->target, "index=\\IDX0 data=\\DAT0"); 122 T_CHECK(r.root->child[0]->child_len == 1); 123 T_CHECK(strcmp(r.root->child[0]->child[0]->name, "IFLD") == 0); 124 T_CHECK(r.root->child[0]->child[0]->bit_len == 8); 125 tobi_parse_result_free(&r); 126 127 uint8_t bfld[] = {0x5b,0x87,0x11,'R','E','G','0','B','N','K','0',0x0a,0x01,0x00,'B','F','L','D',0x08}; 128 T_CHECK(parse_ok(bfld, sizeof(bfld), &r)); 129 T_CHECK(r.root->child_len == 1); 130 T_CHECK(r.root->child[0]->kind == TOBI_IR_FIELD); 131 T_CHECK(strcmp(r.root->child[0]->str, "BankField") == 0); 132 T_STR(r.root->child[0]->target, "region=\\REG0"); 133 T_STR(r.root->child[0]->target, "bank=\\BNK0"); 134 T_CHECK(r.root->child[0]->child_len == 2); 135 T_CHECK(r.root->child[0]->child[0]->kind == TOBI_IR_INTEGER); 136 T_CHECK(r.root->child[0]->child[1]->kind == TOBI_IR_FIELD_ELEM); 137 tobi_parse_result_free(&r); 138 139 uint8_t call[] = { 140 0x14,0x08,'C','A','L','0',0x01,0xa4,0x68, 141 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05 142 }; 143 T_CHECK(parse_ok(call, sizeof(call), &r)); 144 T_CHECK(r.root->child_len == 2); 145 tobi_ir *use = r.root->child[1]; 146 T_CHECK(use->child_len == 1 && use->child[0]->child_len == 1); 147 T_CHECK(use->child[0]->child[0]->kind == TOBI_IR_RETURN); 148 T_CHECK(use->child[0]->child[0]->child_len == 1); 149 T_CHECK(use->child[0]->child[0]->child[0]->kind == TOBI_IR_CALL); 150 T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 151 tobi_parse_result_free(&r); 152 153 uint8_t ext_call[] = { 154 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','X',0x0a,0x05, 155 0x15,'C','A','L','X',0x08,0x01 156 }; 157 T_CHECK(parse_ok(ext_call, sizeof(ext_call), &r)); 158 T_CHECK(r.root->child_len == 2); 159 use = r.root->child[0]; 160 T_CHECK(use->child[0]->child[0]->child[0]->kind == TOBI_IR_CALL); 161 T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 162 T_CHECK(r.root->child[1]->kind == TOBI_IR_EXPR); 163 T_CHECK(strcmp(r.root->child[1]->name, "external") == 0); 164 fe = tobi_ns_find_method(&r.ns, "CALX"); 165 T_CHECK(fe != NULL && fe->external && fe->args == 1); 166 tobi_parse_result_free(&r); 167 168 uint8_t use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05}; 169 uint8_t cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68}; 170 tobi_parse_input inputs[] = { 171 {use_file, sizeof(use_file), "use.aml"}, 172 {cal_file, sizeof(cal_file), "cal.aml"} 173 }; 174 T_CHECK(tobi_parse_multi(inputs, 2, 0, &r)); 175 T_CHECK(r.root->child_len == 2); 176 T_CHECK(strcmp(r.root->child[0]->name, "use.aml") == 0); 177 use = r.root->child[0]->child[0]; 178 T_CHECK(use->child[0]->child[0]->kind == TOBI_IR_RETURN); 179 T_CHECK(use->child[0]->child[0]->child[0]->kind == TOBI_IR_CALL); 180 T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 181 fe = tobi_ns_find_method(&r.ns, "CAL0"); 182 T_CHECK(fe != NULL && !fe->external && fe->args == 1); 183 tobi_parse_result_free(&r); 184 185 uint8_t scoped_call[] = { 186 0x10,0x23,'\\','_','S','B','_', 187 0x14,0x08,'C','A','L','0',0x01,0xa4,0x68, 188 0x5b,0x82,0x12,'D','E','V','0', 189 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05 190 }; 191 T_CHECK(parse_ok(scoped_call, sizeof(scoped_call), &r)); 192 use = r.root->child[0]->child[0]->child[1]->child[0]->child[0]; 193 T_CHECK(use->kind == TOBI_IR_METHOD); 194 tobi_ir *scall = use->child[0]->child[0]->child[0]; 195 T_CHECK(scall->kind == TOBI_IR_CALL); 196 T_CHECK(strcmp(scall->path, "\\_SB_.CAL0") == 0); 197 T_CHECK(scall->child_len == 1); 198 tobi_parse_result_free(&r); 199 200 uint8_t fwd[] = { 201 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05, 202 0x14,0x08,'C','A','L','0',0x01,0xa4,0x68 203 }; 204 T_CHECK(parse_ok(fwd, sizeof(fwd), &r)); 205 T_CHECK(r.root->child_len == 2); 206 use = r.root->child[0]; 207 T_CHECK(use->child[0]->child[0]->kind == TOBI_IR_RETURN); 208 T_CHECK(use->child[0]->child[0]->child[0]->kind == TOBI_IR_CALL); 209 T_CHECK(use->child[0]->child[0]->child[0]->child_len == 1); 210 tobi_parse_result_free(&r); 211 212 uint8_t ops[] = { 213 0x14,0x24,'O','P','S','0',0x00, 214 0x5b,0x22,0x0a,0x01, 215 0x8c,'B','U','F','0',0x0a,0x00,'B','Y','T','0', 216 0x70,0x5b,0x30,0x60, 217 0x5b,0x32,0x0a,0x01,0x0c,0x34,0x12,0x00,0x00,0x0a,0x02 218 }; 219 T_CHECK(parse_ok(ops, sizeof(ops), &r)); 220 T_CHECK(!tobi_diag_has_error(&r.diag)); 221 T_CHECK(r.diag.len == 0); 222 tobi_ir *blk = r.root->child[0]->child[0]; 223 T_CHECK(blk->child_len == 4); 224 T_CHECK(blk->child[0]->kind == TOBI_IR_EXPR); 225 T_CHECK(strcmp(blk->child[0]->name, "sleep") == 0); 226 T_CHECK(blk->child[1]->kind == TOBI_IR_EXPR); 227 T_CHECK(strcmp(blk->child[1]->name, "create_byte_field") == 0); 228 T_CHECK(blk->child[2]->kind == TOBI_IR_STORE); 229 T_CHECK(blk->child[2]->child[0]->kind == TOBI_IR_INTEGER); 230 T_CHECK(blk->child[3]->kind == TOBI_IR_EXPR); 231 T_CHECK(strcmp(blk->child[3]->name, "fatal") == 0); 232 tobi_parse_result_free(&r); 233 234 uint8_t ext_obj[] = { 235 0x5b,0x88,'D','R','G','0',0x0d,'S','I','G',0x00,0x0d,'O','E','M',0x00,0x0d,'D','A','T',0x00, 236 0x5b,0x23,'M','T','X','0',0x0b,0xff,0xff, 237 0x5b,0x31 238 }; 239 T_CHECK(parse_ok(ext_obj, sizeof(ext_obj), &r)); 240 T_CHECK(r.diag.len == 0); 241 T_CHECK(r.root->child_len == 3); 242 T_CHECK(r.root->child[0]->kind == TOBI_IR_OPREGION); 243 T_CHECK(strcmp(r.root->child[0]->str, "DataRegion") == 0); 244 T_CHECK(r.root->child[1]->kind == TOBI_IR_EXPR); 245 T_CHECK(strcmp(r.root->child[1]->name, "acquire") == 0); 246 T_CHECK(r.root->child[2]->kind == TOBI_IR_REF); 247 T_CHECK(strcmp(r.root->child[2]->name, "Debug") == 0); 248 tobi_parse_result_free(&r); 249 250 uint8_t more_ext[] = { 251 0x5b,0x20,'T','B','L','0',0x60, 252 0x5b,0x33, 253 0x5b,0x1f, 254 0x0d,'D','S','D','T',0x00, 255 0x0d,'O','E','M',0x00, 256 0x0d,'T','A','B','L','E',0x00, 257 0x0d,'\\',0x00, 258 0x0d,'P','A','R','M',0x00, 259 0x60 260 }; 261 T_CHECK(parse_ok(more_ext, sizeof(more_ext), &r)); 262 T_CHECK(r.diag.len == 0); 263 T_CHECK(r.root->child_len == 3); 264 T_CHECK(strcmp(r.root->child[0]->name, "load") == 0); 265 T_CHECK(r.root->child[0]->child_len == 2); 266 T_CHECK(strcmp(r.root->child[1]->name, "timer") == 0); 267 T_CHECK(strcmp(r.root->child[2]->name, "load_table") == 0); 268 T_CHECK(r.root->child[2]->child_len == 6); 269 tobi_parse_result_free(&r); 270 271 uint8_t divop[] = {0x78,0x0a,0x07,0x0a,0x02,0x60,0x61}; 272 T_CHECK(parse_ok(divop, sizeof(divop), &r)); 273 T_CHECK(r.root->child_len == 1); 274 T_CHECK(r.root->child[0]->kind == TOBI_IR_EXPR); 275 T_CHECK(strcmp(r.root->child[0]->name, "div") == 0); 276 T_CHECK(r.root->child[0]->child_len == 4); 277 tobi_parse_result_free(&r); 278 279 uint8_t dup_name[] = { 280 0x08,'D','U','P','0',0x01, 281 0x08,'D','U','P','0',0x00 282 }; 283 T_CHECK(tobi_parse(dup_name, sizeof(dup_name), 0, &r)); 284 T_CHECK(r.diag.len == 1); 285 T_CHECK(r.diag.items[0].level == TOBI_DIAG_WARN); 286 tobi_parse_result_free(&r); 287 T_CHECK(!tobi_parse(dup_name, sizeof(dup_name), 1, &r)); 288 T_CHECK(tobi_diag_has_error(&r.diag)); 289 tobi_parse_result_free(&r); 290 291 uint8_t unresolved_ref[] = {0x14,0x0b,'U','N','R','0',0x00,0xa4,'N','O','P','E'}; 292 T_CHECK(tobi_parse(unresolved_ref, sizeof(unresolved_ref), 0, &r)); 293 T_CHECK(r.diag.len == 1); 294 T_CHECK(r.diag.items[0].level == TOBI_DIAG_WARN); 295 T_STR(r.diag.items[0].msg, "unresolved AML namespace reference"); 296 tobi_parse_result_free(&r); 297 T_CHECK(!tobi_parse(unresolved_ref, sizeof(unresolved_ref), 1, &r)); 298 T_CHECK(tobi_diag_has_error(&r.diag)); 299 tobi_parse_result_free(&r); 300 301 uint8_t alias_cycle[] = { 302 0x06,'A','L','B','0','A','L','A','0', 303 0x06,'A','L','A','0','A','L','B','0' 304 }; 305 T_CHECK(tobi_parse(alias_cycle, sizeof(alias_cycle), 0, &r)); 306 T_CHECK(r.diag.len >= 1); 307 T_STR(r.diag.items[0].msg, "alias cycle"); 308 tobi_parse_result_free(&r); 309 310 uint8_t symbols[] = { 311 0x14,0x0a,'S','Y','M','0',0x01, 312 0xa4,0x60,0xa4,0x69 313 }; 314 T_CHECK(tobi_parse(symbols, sizeof(symbols), 0, &r)); 315 T_CHECK(r.diag.len >= 2); 316 T_STR(r.diag.items[0].msg, "Local0 may be read before"); 317 T_STR(r.diag.items[1].msg, "Arg1 read exceeds declared argument count"); 318 T_STR(r.root->child[0]->target, "method_symbols"); 319 T_STR(r.root->child[0]->target, "local_reads=0x1"); 320 T_STR(r.root->child[0]->target, "arg_reads=0x2"); 321 T_STR(r.root->child[0]->target, "warnings=2"); 322 tobi_ir *sym_ret = r.root->child[0]->child[0]->child[0]; 323 T_CHECK(sym_ret->kind == TOBI_IR_RETURN); 324 T_STR(sym_ret->child[0]->str, "uninitialised"); 325 T_STR(r.root->child[0]->child[0]->child[1]->child[0]->str, "out_of_range"); 326 tobi_parse_result_free(&r); 327 return 0; 328}