ACPI AML decompiler w/ CFG recovery and structured pseudocode
1#include "t.h"
2
3#include <sys/wait.h>
4
5#ifndef TOBI_BIN
6#define TOBI_BIN "./tobi"
7#endif
8#ifndef TOBI_SRC_DIR
9#define TOBI_SRC_DIR "."
10#endif
11
12static int write_blob(const char *path, const unsigned char *data, size_t len) {
13 FILE *fp = fopen(path, "wb");
14 if (!fp) {
15 return 0;
16 }
17 int ok = fwrite(data, 1, len, fp) == len;
18 return fclose(fp) == 0 && ok;
19}
20
21static char *run_capture(const char *args, int *status) {
22 char cmd[1024];
23 snprintf(cmd, sizeof(cmd), "%s %s 2>/dev/null", TOBI_BIN, args);
24 FILE *fp = popen(cmd, "r");
25 if (!fp) {
26 *status = 99;
27 return NULL;
28 }
29 size_t cap = 4096;
30 size_t len = 0;
31 char *buf = malloc(cap);
32 if (!buf) {
33 (void)pclose(fp);
34 *status = 99;
35 return NULL;
36 }
37 int c = 0;
38 while ((c = fgetc(fp)) != EOF) {
39 if (len + 1 == cap) {
40 cap *= 2;
41 char *nb = realloc(buf, cap);
42 if (!nb) {
43 free(buf);
44 (void)pclose(fp);
45 *status = 99;
46 return NULL;
47 }
48 buf = nb;
49 }
50 buf[len++] = (char)c;
51 }
52 buf[len] = '\0';
53 int rc = pclose(fp);
54 *status = WIFEXITED(rc) ? WEXITSTATUS(rc) : 99;
55 return buf;
56}
57
58int t_cli(void) {
59 int st = 0;
60 char path[512];
61 snprintf(path, sizeof(path), "%s/sam/m0.aml", TOBI_SRC_DIR);
62 char args[700];
63 snprintf(args, sizeof(args), "%s", path);
64 char *s = run_capture(args, &st);
65 T_CHECK(st == 0);
66 T_STR(s, "method MTH0");
67 T_STR(s, "return Local0");
68 free(s);
69 snprintf(args, sizeof(args), "--dis %s", path);
70 s = run_capture(args, &st);
71 T_CHECK(st == 0);
72 T_STR(s, "0x0000");
73 T_STR(s, "MethodOp");
74 free(s);
75 snprintf(args, sizeof(args), "--json %s", path);
76 s = run_capture(args, &st);
77 T_CHECK(st == 0);
78 T_STR(s, "\"ir\"");
79 T_STR(s, "\"kind\":\"method\"");
80 free(s);
81 snprintf(args, sizeof(args), "--dot %s", path);
82 s = run_capture(args, &st);
83 T_CHECK(st == 0);
84 T_STR(s, "digraph tobi_cfg");
85 T_STR(s, "method");
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);
93 {
94 unsigned char use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05};
95 unsigned char cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68};
96 const char *use_path = "/tmp/tobi_cli_use.aml";
97 const char *cal_path = "/tmp/tobi_cli_cal.aml";
98 T_CHECK(write_blob(use_path, use_file, sizeof(use_file)));
99 T_CHECK(write_blob(cal_path, cal_file, sizeof(cal_file)));
100 snprintf(args, sizeof(args), "%s %s", use_path, cal_path);
101 s = run_capture(args, &st);
102 T_CHECK(st == 0);
103 T_STR(s, "method USE0");
104 T_STR(s, "CAL0(0x5)");
105 free(s);
106 }
107 s = run_capture("--help", &st);
108 T_CHECK(st == 0);
109 T_STR(s, "usage: tobi");
110 free(s);
111 s = run_capture("--version", &st);
112 T_CHECK(st == 0);
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);
122 free(s);
123 snprintf(path, sizeof(path), "%s/sam/bad0.aml", TOBI_SRC_DIR);
124 snprintf(args, sizeof(args), "--strict %s", path);
125 s = run_capture(args, &st);
126 T_CHECK(st != 0);
127 free(s);
128 return 0;
129}