13 bool activeLow =
false;
16 static bool parse(
const uint8_t* aml,
size_t size,
Route routes[32][4]) {
17 if (!aml || !size || !routes) {
20 for (
size_t slot = 0; slot < 32; ++slot) {
21 for (
size_t pin = 0; pin < 4; ++pin) {
22 routes[slot][pin] = {};
27 return parsePackage(aml, size,
"_PRT", routes) || parsePackage(aml, size,
"PRTA", routes);
31 static bool equal(
const uint8_t* bytes,
const char* name) {
32 for (
size_t i = 0; i < 4; ++i) {
33 if (bytes[i] !=
static_cast<uint8_t
>(name[i])) {
40 static bool package(
const uint8_t* bytes,
size_t size,
size_t& cursor,
size_t& end) {
44 const uint8_t lead = bytes[cursor];
45 const size_t follow = lead >> 6;
46 if (follow >= size - cursor) {
49 uint32_t length = follow ? lead & 0x0f : lead & 0x3f;
50 for (
size_t i = 0; i < follow; ++i) {
51 length |= uint32_t(bytes[cursor + 1 + i]) << (4 + i * 8);
53 if (length < follow + 1 || length > size - cursor) {
56 end = cursor + length;
61 static bool integer(
const uint8_t* bytes,
size_t end,
size_t& cursor, uint64_t& value) {
65 const uint8_t op = bytes[cursor++];
70 const size_t width = op == 0x0a ? 1 : op == 0x0b ? 2 : op == 0x0c ? 4 : op == 0x0e ? 8 : 0;
71 if (!width || width > end - cursor) {
75 for (
size_t i = 0; i < width; ++i) {
76 value |= uint64_t(bytes[cursor++]) << (i * 8);
81 static bool link(
const uint8_t* aml,
size_t size,
const char source[4], Route& route) {
82 for (
size_t i = 0; i + 8 < size; ++i) {
83 if (aml[i] != 0x5b || aml[i + 1] != 0x82) {
86 size_t body = i + 2, deviceEnd = 0;
87 if (!package(aml, size, body, deviceEnd) || deviceEnd - body < 4 ||
88 !equal(aml + body, source)) {
92 for (
size_t j = body; j + 7 < deviceEnd; ++j) {
93 if (aml[j] != 0x08 || !equal(aml + j + 1,
"_CRS") || aml[j + 5] != 0x11) {
96 size_t data = j + 6, bufferEnd = 0;
97 uint64_t declared = 0;
98 if (!package(aml, deviceEnd, data, bufferEnd) || !integer(aml, bufferEnd, data, declared) ||
99 declared > bufferEnd - data) {
102 const size_t end = data +
static_cast<size_t>(declared);
104 const uint8_t tag = aml[data++];
107 if (end - data < 2) {
110 length = size_t(aml[data]) | (size_t(aml[data + 1]) << 8);
115 if (length > end - data) {
118 if (tag == 0x89 && length == 6 && aml[data + 1] == 1 && !(aml[data] & 2)) {
119 route.gsi = uint32_t(aml[data + 2]) | (uint32_t(aml[data + 3]) << 8) |
120 (uint32_t(aml[data + 4]) << 16) | (uint32_t(aml[data + 5]) << 24);
121 route.activeLow = (aml[data] & 4) != 0;
122 return route.gsi >= 16;
131 static bool parsePackage(
const uint8_t* aml,
size_t size,
const char* name, Route routes[32][4]) {
132 for (
size_t i = 0; i + 7 < size; ++i) {
133 if (aml[i] != 0x08 || !equal(aml + i + 1, name) || aml[i + 5] != 0x12) {
136 size_t body = i + 6, end = 0;
137 if (!package(aml, size, body, end) || body >= end) {
140 const uint8_t count = aml[body++];
141 Route parsed[32][4] = {};
142 bool valid =
true, found =
false;
143 for (
size_t entry = 0; entry < count; ++entry) {
144 if (body >= end || aml[body++] != 0x12) {
149 if (!package(aml, end, body, itemEnd) || body >= itemEnd || aml[body++] != 4) {
153 uint64_t address = 0, pin = 0, sourceIndex = 0;
154 if (!integer(aml, itemEnd, body, address) || !integer(aml, itemEnd, body, pin) ||
161 const bool direct = aml[body] == 0;
164 }
else if (itemEnd - body >= 4) {
165 for (
size_t c = 0; c < 4; ++c) {
166 source[c] = aml[body++];
172 if (!integer(aml, itemEnd, body, sourceIndex) || (address & 0xffff) != 0xffff || pin > 3 ||
173 sourceIndex > UINT32_MAX) {
178 route.gsi =
static_cast<uint32_t
>(sourceIndex);
179 route.activeLow =
true;
180 }
else if (sourceIndex == 0) {
181 link(aml, size, source, route);
183 const uint32_t slot = (address >> 16) & 0xffff;
184 if (slot < 32 && route.gsi >= 16) {
185 if (parsed[slot][pin].gsi && (parsed[slot][pin].gsi != route.gsi ||
186 parsed[slot][pin].activeLow != route.activeLow)) {
190 parsed[slot][pin] = route;
195 if (valid && found && body == end) {
196 for (
size_t slot = 0; slot < 32; ++slot) {
197 for (
size_t pin = 0; pin < 4; ++pin) {
198 routes[slot][pin] = parsed[slot][pin];