hwdet.h 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. /*
  2. * hwdet.h
  3. *
  4. * Copyright (C) 2023 bzt, GPLv3+
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. *
  20. * @brief Hardware Resource Detection single header library
  21. */
  22. enum { HWDET_NONE, HWDET_CPU, HWDET_IO, HWDET_IRQ, HWDET_DMA, HWDET_MMIO, HWDET_PCI, HWDET_EC, HWDET_SMB, HWDET_CMOS };
  23. /**
  24. * Public API, single function: pass a list of ACPI DSDT/SSDT tables, FDT (dtb) or GUDT blobs and it will call the two hooks
  25. */
  26. void HWDET_RESVMEM(uint64_t base, uint64_t size);
  27. void HWDET_RESOURCE(char *name, char *driver, char *altdriver, int type, uint64_t arg1, uint64_t arg2);
  28. void hwdet(int num, uint8_t **ds);
  29. /* Implementation */
  30. #ifndef AML_MAXLEVEL
  31. #define AML_MAXLEVEL 32
  32. #endif
  33. #ifndef AML_MAXSTR
  34. #define AML_MAXSTR 32
  35. #endif
  36. /*#define AML_MINNODES 768*/
  37. typedef struct {
  38. uint8_t magic[4];
  39. uint32_t size;
  40. uint8_t rev;
  41. uint8_t chksum;
  42. char OEM[6];
  43. char OEMtableid[8];
  44. uint32_t OEMrev;
  45. uint32_t creatid;
  46. uint32_t creatrev;
  47. } __attribute__((packed)) acpi_t;
  48. typedef struct {
  49. uint32_t type;
  50. uint32_t parent;
  51. uint8_t *name;
  52. union {
  53. uint8_t b[16];
  54. uint16_t w[8];
  55. uint32_t d[4];
  56. uint64_t q[2];
  57. uint8_t *p[2];
  58. } data;
  59. } aml_t;
  60. static struct {
  61. aml_t *node;
  62. uint64_t stack[AML_MAXLEVEL*16];
  63. uint32_t len, num, max, par, sp;
  64. uint32_t mtdidx, devidx, drvidx, altidx, regidx;
  65. uint8_t *memmin, *memmax;
  66. } aml;
  67. #define NODE aml.node[aml.num]
  68. typedef struct {
  69. uint8_t magic[4]; /* magic GUDT */
  70. uint16_t hdrsize; /* 8 + string table's size */
  71. uint16_t numnodes; /* number of nodes */
  72. } __attribute__((packed)) gudt_hdr_t;
  73. static uint8_t *aml_NameString(uint8_t *ptr);
  74. static uint8_t *aml_TermList(uint8_t *ptr, uint8_t *end, aml_t *node);
  75. #ifdef AML_DEBUG
  76. static uint32_t numchk, stkchk, stkmax;
  77. #define AML_STKENTER(s) do{ stkchk += s; if(stkchk > stkmax) stkmax = stkchk; }while(0)
  78. #define AML_STKLEAVE(s) stkchk -= s
  79. /**
  80. * AML node-ok listázása
  81. */
  82. void aml_dump(aml_t *node)
  83. {
  84. uint32_t i, j, n;
  85. if(node) n = 1; else { node = &aml.node[0]; n = aml.num; }
  86. for(i = 0; i < n; i++, node++) {
  87. printf("%4d parent %4d type %04x name '%c%c%c%c' data.q ", i, node->parent,node->type,
  88. node->name && node->name[0] > 32 && node->name[0] < 127 ? node->name[0] : '.',
  89. node->name && node->name[1] > 32 && node->name[1] < 127 ? node->name[1] : '.',
  90. node->name && node->name[2] > 32 && node->name[2] < 127 ? node->name[2] : '.',
  91. node->name && node->name[3] > 32 && node->name[3] < 127 ? node->name[3] : '.');
  92. for(j = 0; j < 2; j++) printf(" %lx", node->data.q[j]);
  93. printf(" data.d ");
  94. for(j = 0; j < 4; j++) printf(" %x", node->data.d[j]);
  95. printf("\n");
  96. }
  97. }
  98. #else
  99. #define AML_STKENTER(s)
  100. #define AML_STKLEAVE(s)
  101. #endif
  102. /**
  103. * AML node kikeresése
  104. */
  105. static uint32_t aml_lookup(uint8_t *name)
  106. {
  107. uint32_t parent = aml.par, i, n, c, a = 2;
  108. uint8_t *s;
  109. #ifdef AML_DEBUG
  110. if(stkchk + 32 > stkmax) stkmax = stkchk + 32;
  111. #endif
  112. if(name < aml.memmin || name >= aml.memmax) return 0;
  113. if(*name == '\\') { name++; parent = 0; }
  114. while(*name == '^' && parent) { name++; parent = aml.node[parent].parent; }
  115. switch(*name) {
  116. case 0x00: return 0;
  117. case 0x2E: name++; c = 2; break;
  118. case 0x2F: name++; c = *name++; break;
  119. default: c = 1; break;
  120. }
  121. /* gyors ellenőrzés, hogy a szülőre hivatkozik-e */
  122. i = aml.num - 1;
  123. if(c == 1 && (aml.node[i].parent == parent || aml.node[i].parent == aml.node[parent].parent) &&
  124. !memcmp(aml.node[i].name, name, 4)) return i;
  125. do {
  126. s = name; n = c;
  127. again: /* végigjárjuk a teljes path-ot */
  128. for(i = 1; i < aml.num; i++) {
  129. if(aml.node[i].parent == parent && !memcmp(aml.node[i].name, s, 4)) {
  130. n--; s += 4; parent = i;
  131. if(!n) return i; else goto again;
  132. }
  133. }
  134. /* bugos firmverek miatt csinálunk több ellenőrzést is, a szülőtől és a gyökértől is kiindulva */
  135. parent = a == 2 ? aml.node[aml.par].parent : 0;
  136. } while(a--);
  137. if(c == 1)
  138. for(i = aml.num - 1; i > 0; i--)
  139. if(!memcmp(aml.node[i].name, name, 4)) return i;
  140. #ifdef AML_DEBUG
  141. printf("node not found, parent %d '", aml.par);
  142. for(n = 0; n < c; n++)
  143. for(i = 0; i < 4; i++) {
  144. if(n) printf(".");
  145. if(name[i] > 32 && name[i] < 127) printf("%c", name[i]); else printf("\\x%02X", name[i]);
  146. }
  147. printf("'\n");
  148. #endif
  149. return 0;
  150. }
  151. /**
  152. * AML opkód beolvasása
  153. */
  154. static uint8_t *aml_opcode(uint8_t *ptr, uint16_t *op)
  155. {
  156. #ifdef AML_DEBUG
  157. if(stkchk + 16 > stkmax) stkmax = stkchk + 16;
  158. #endif
  159. if(ptr < aml.memmin || ptr >= aml.memmax) { *op = 0xffff; return ptr; }
  160. if(*ptr == '\\' || *ptr == '^' || *ptr == '/' || *ptr == '_' || *ptr == '.' || (*ptr >= 'A' && *ptr <= 'Z')) {
  161. *op = 9; ptr = aml_NameString(ptr);
  162. } else
  163. if(*ptr == 0x5B || (*ptr == 0x92 && ptr[1] >= 0x93 && ptr[1] <= 0x95)) { *op = *ptr++ << 8; *op |= *ptr++; }
  164. else *op = *ptr++;
  165. return ptr;
  166. }
  167. /**
  168. * AML packet értelmezése
  169. */
  170. static uint8_t *aml_pkg(uint8_t *ptr)
  171. {
  172. uint8_t imm = (*ptr & 0xC0) >> 6, i;
  173. aml.len = imm ? (*ptr++ & 0x0F) : (*ptr++ & 0x3F);
  174. for(i = 0; i < imm; i++) aml.len |= *ptr++ << (4 + (i << 3));
  175. return ptr;
  176. }
  177. /**
  178. * Meghatározza, maximum mennyi node-ra van szükség
  179. */
  180. static int aml_numnodes(int siz, acpi_t **tbl)
  181. {
  182. gudt_hdr_t *hdr;
  183. int i, n = 0, cur, l = 0, nodes[AML_MAXLEVEL] = { 0 }, skip = 0, skipbytes = 0, skip2 = 0, skip2bytes = 0;
  184. uint8_t *st, *ptr, *end, *scope[AML_MAXLEVEL] = { 0 };
  185. uint16_t op;
  186. /* egy a root node-nak, meg a biztonság kedvéért kis rátartással számolunk a dinamikus metódushívásoknak */
  187. cur = 1;
  188. memset(&aml, 0, sizeof(aml)); aml.memmin = (uint8_t*)-1UL;
  189. for(i = 0; i < siz && tbl; i++) {
  190. if(!tbl[i] || !tbl[i]->size) continue;
  191. if(tbl[i]->magic[0] == 0xD0 && tbl[i]->magic[1] == 0x0D) { n++; continue; }
  192. if(tbl[i]->magic[0] == 'G' && tbl[i]->magic[1] == 'U') {
  193. hdr = (gudt_hdr_t*)tbl[i];
  194. n += (((hdr->hdrsize + 7) & ~7) + hdr->numnodes * 16 + sizeof(aml_t) - 1) / sizeof(aml_t);
  195. continue;
  196. }
  197. ptr = (uint8_t*)tbl[i] + sizeof(acpi_t); end = ptr + tbl[i]->size;
  198. if(ptr[0] == 0xD0 && ptr[1] == 0x0D) { n++; continue; }
  199. if(aml.memmin > ptr) aml.memmin = ptr;
  200. if(aml.memmax < end) aml.memmax = end;
  201. while(ptr < end) {
  202. if(cur > n) n = cur;
  203. while(l > 0 && ptr >= scope[l - 1]) cur = nodes[--l];
  204. if(skip) { skip--; if(!skip) { ptr += skipbytes; skipbytes = 0; } }
  205. if(skip2) { skip2--; if(!skip2) { ptr += skip2bytes; skip2bytes = 0; } }
  206. st = ptr; ptr = aml_opcode(ptr, &op);
  207. switch(op) {
  208. case 0x0006: case 0x0008: ptr = aml_NameString(ptr); cur++; break;
  209. case 0x0009: break;
  210. case 0x000A: ptr++; break;
  211. case 0x000B: ptr += 2; break;
  212. case 0x000C: ptr += 4; break;
  213. case 0x000E: ptr += 8; break;
  214. case 0x000D: for(; ptr < end && ptr[-1]; ptr++); break;
  215. case 0x0011: case 0x0012: case 0x0013: case 0x5B83:
  216. ptr = aml_pkg(ptr); ptr = st + (op > 0xff ? 2 : 1) + aml.len; break;
  217. case 0x5B87: case 0x5B88:
  218. ptr = aml_pkg(ptr); ptr = st + (op > 0xff ? 2 : 1) + aml.len; cur++; break;
  219. case 0x0010: case 0x5B82:
  220. ptr = aml_pkg(ptr); cur++; if(l < AML_MAXLEVEL) { scope[l] = st + 1 + aml.len; nodes[l++] = cur; }
  221. break;
  222. case 0x0014:
  223. ptr = aml_pkg(ptr); cur++; st += 1 + aml.len;
  224. if(l < AML_MAXLEVEL && (!memcmp(ptr, "_HID", 4) || !memcmp(ptr, "_CID", 4) || !memcmp(ptr, "_CRS", 4))) {
  225. scope[l] = st; nodes[l++] = cur;
  226. } else ptr = st;
  227. break;
  228. case 0x0015: ptr = aml_NameString(ptr) + 2; break;
  229. case 0x00A0: case 0x00A1: case 0x00A2: ptr = aml_pkg(ptr); break;
  230. case 0x5B01: ptr = aml_NameString(ptr) + 1; break;
  231. case 0x5B02: ptr = aml_NameString(ptr); break;
  232. case 0x5B23: skip = 1; skipbytes = 2; break;
  233. case 0x5B80: ptr = aml_NameString(ptr) + 1; cur++; break;
  234. case 0x5B81: case 0x5B86: ptr = aml_pkg(ptr); st += 2 + aml.len;
  235. ptr = aml_NameString(ptr);
  236. if(op == 0x5B86) ptr = aml_NameString(ptr);
  237. ptr++;
  238. /* ptr - st FieldList */
  239. while(ptr < st) {
  240. switch(*ptr) {
  241. case 0: ptr++; ptr = aml_pkg(ptr); break;
  242. case 1: ptr += 3; break;
  243. case 2: ptr = aml_NameString(ptr + 1); break;
  244. case 3: ptr += 3 + ptr[2]; break;
  245. default: ptr += 4; ptr = aml_pkg(ptr); cur++; break;
  246. }
  247. }
  248. ptr = st; cur++;
  249. break;
  250. case 0x0089: skip = 1; skipbytes = 1; skip2 = 2; skip2bytes = 1; break;
  251. case 0x008A: case 0x008B: case 0x008C: case 0x008D: case 0x008F: case 0x5B13: cur++; break;
  252. default: break;
  253. }
  254. }
  255. }
  256. n += AML_MAXLEVEL*4;
  257. #ifdef AML_MINNODES
  258. if(n < AML_MINNODES) n = AML_MINNODES;
  259. #endif
  260. /* globális változók alaphelyzetbe állítása (érdemes globálist használni, mivel az aml_TermList rekurzív) */
  261. aml.num = 1; aml.max = n; aml.sp = AML_MAXLEVEL*16;
  262. aml.mtdidx = aml.devidx = aml.drvidx = aml.regidx = -1U;
  263. #ifdef AML_DEBUG
  264. numchk = 0; stkchk = stkmax = n * sizeof(aml_t) + 16;
  265. #endif
  266. return n;
  267. }
  268. /**
  269. * Path "fájlnév" részét adja vissza
  270. */
  271. static void aml_fn(aml_t *node)
  272. {
  273. int c;
  274. #ifdef AML_DEBUG
  275. if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
  276. #endif
  277. if(node->name[0] == '\\') { node->name++; node->parent = 0; }
  278. while(node->name[0] == '^' && node->parent) { node->name++; node->parent = aml.node[node->parent].parent; }
  279. if(node->name[0] == 0x2E) node->name += 4; else
  280. if(node->name[0] == 0x2F) { node->name++; c = (node->name[0] - 1) << 2; node->name += 1 + c; }
  281. }
  282. /**
  283. * AML node értékének betöltése
  284. */
  285. static void aml_get(aml_t *val, aml_t *in)
  286. {
  287. uint32_t idx;
  288. #ifdef AML_DEBUG
  289. if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
  290. #endif
  291. /* ha a forrás LocalX vagy ArgX */
  292. if(in->type >= 0x0060 && in->type <= 0x006F) {
  293. idx = aml.sp + in->type - 0x60;
  294. val->data.q[0] = idx < AML_MAXLEVEL*16 ? aml.stack[idx] : 0;
  295. val->type = 0x000E;
  296. } else
  297. /* ha a forrás egy FieldOp */
  298. if(in->type == 0x5B13) {
  299. val->data.q[0] = 0;
  300. val->type = 0x000E;
  301. if(in->data.p[0] >= aml.memmin && in->data.p[0] < aml.memmax) {
  302. if(!(in->data.d[2] & 7) && !(in->data.d[3] & 7))
  303. /* bájthatárra esik, és a mérete is bájttöbbszörös */
  304. memcpy(&val->data, (void*)(in->data.q[0] + (in->data.d[2] >> 3)),
  305. (in->data.d[3] >= 64 ? 64 : in->data.d[3]) >> 3);
  306. else {
  307. /* nem, tehát shiftelünk és maszkolunk */
  308. val->data.q[0] = *((uint64_t*)(in->data.q[0] + (in->data.d[2] >> 3))) >> (in->data.d[2] & 7);
  309. }
  310. }
  311. } else
  312. /* a forrás egy buffer vagy packet */
  313. if(in->type == 0x0011 || in->type == 0x0012 || in->type == 0x0013) {
  314. val->data.q[0] = 0;
  315. val->type = 0x000E;
  316. if(in->data.p[0] >= aml.memmin && in->data.p[0] < aml.memmax)
  317. memcpy(&val->data, in->data.p[0], in->data.d[2] >= 8 ? 8 : in->data.d[2]);
  318. } else
  319. if(val != in) memcpy(val, in, sizeof(aml_t));
  320. }
  321. /**
  322. * AML node értékének beállítása
  323. */
  324. static void aml_set(aml_t *out, aml_t *val)
  325. {
  326. uint64_t num;
  327. #ifdef AML_DEBUG
  328. if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
  329. #endif
  330. /* ha a cél a NULL */
  331. if(out->type == 0x000D && !out->data.p[0]) return;
  332. /* ha a cél LocalX vagy ArgX */
  333. if(out->type >= 0x0060 && out->type <= 0x006F) {
  334. num = aml.sp + out->type - 0x60;
  335. if(num < AML_MAXLEVEL*16) aml.stack[num] = val->data.q[0];
  336. out->data.q[0] = val->data.q[0];
  337. } else
  338. /* ha a cél egy FieldOp */
  339. if(out->type == 0x5B13) {
  340. if(out->data.p[0] >= aml.memmin && out->data.p[0] < aml.memmax) {
  341. if(!(out->data.d[2] & 7) && !(out->data.d[3] & 7))
  342. /* bájthatárra esik, és a mérete is bájttöbbszörös */
  343. memcpy((void*)(out->data.q[0] + (out->data.d[2] >> 3)), &val->data, out->data.d[3] >> 3);
  344. else {
  345. /* nem, tehát shiftelünk és maszkolunk */
  346. num = *((uint64_t*)(out->data.q[0] + (out->data.d[2] >> 3)));
  347. num &= ~(~(-1UL << (out->data.d[3])) << (out->data.d[2] & 7));
  348. num |= (val->data.q[0] & ~(-1UL << (out->data.d[3]))) << (out->data.d[2] & 7);
  349. *((uint64_t*)(out->data.q[0] + (out->data.d[2] >> 3))) = num;
  350. }
  351. }
  352. } else
  353. /* ha a cél egy buffer vagy packet */
  354. if(out->type == 0x0011 || out->type == 0x0012 || out->type == 0x0013) {
  355. if(out->data.p[0] >= aml.memmin && out->data.p[0] < aml.memmax)
  356. memcpy(out->data.p[0], &val->data, out->data.d[2] >= 8 ? 8 : out->data.d[2]);
  357. } else
  358. /* ha cél és forrás típusa megegyezik, vagy mindkettő integer */
  359. if(out->type == val->type || (out->type ==0x000E && val->type >= 0x60 && val->type <= 0x006F))
  360. memcpy(&out->data, &val->data, sizeof(out->data));
  361. #ifdef AML_DEBUG
  362. /* a feloldatlan referenciákat csendben kihagyjuk. Nem szabadna megtörténnie, de például a saját gépem DSDT-je is
  363. * bugos, olyan field-re hivatkozik, ami nem mindig van definiálva... */
  364. else if(out->type != 0x0009) { printf("Bad lvalue\n"); aml_dump(out); exit(1); }
  365. #endif
  366. }
  367. /**
  368. * Átkonvertálja az AML kódot olvasható sztringgé
  369. */
  370. static void aml_drvname(uint32_t idx, char *str)
  371. {
  372. int i;
  373. if(idx < 1 || idx >= aml.num) return;
  374. if(aml.node[idx].type == 0x000C) {
  375. /* Eisa Id */
  376. str[0] = '@' + ((aml.node[idx].data.d[0] >> 2) & 0x1F);
  377. str[1] = '@' + ((aml.node[idx].data.d[0] << 3) & 0x18) + ((aml.node[idx].data.d[0] >> 13) & 0x7);
  378. str[2] = '@' + ((aml.node[idx].data.d[0] >> 8) & 0x1F);
  379. i = (aml.node[idx].data.d[0] >> 20) & 0xF; str[3] = i < 10 ? '0' + i : 'A' + i - 10;
  380. i = (aml.node[idx].data.d[0] >> 16) & 0xF; str[4] = i < 10 ? '0' + i : 'A' + i - 10;
  381. i = (aml.node[idx].data.d[0] >> 28) & 0xF; str[5] = i < 10 ? '0' + i : 'A' + i - 10;
  382. i = (aml.node[idx].data.d[0] >> 24) & 0xF; str[6] = i < 10 ? '0' + i : 'A' + i - 10;
  383. } else
  384. if(aml.node[idx].type == 0x000D && aml.node[idx].data.p[0] >= aml.memmin &&
  385. aml.node[idx].data.p[0] < aml.memmax) {
  386. for(i = 0; i < 30 && aml.node[idx].data.p[0][i]; i++)
  387. str[i] = (char)aml.node[idx].data.p[0][i];
  388. }
  389. }
  390. /**
  391. * Akkor hívódik, ha egy erőforrást talált
  392. */
  393. static void aml_ResourceTemplate(void)
  394. {
  395. uint8_t *ptr, *end, t;
  396. uint16_t s, n;
  397. uint64_t rs, re, ra, rt, rl;
  398. char name[8], drv[AML_MAXSTR], alt[AML_MAXSTR];
  399. int i;
  400. memset(name, 0, sizeof(name)); memset(drv, 0, sizeof(drv)); memset(alt, 0, sizeof(alt));
  401. if(aml.node[aml.devidx].name >= aml.memmin && aml.node[aml.devidx].name < aml.memmax)
  402. memcpy(name, aml.node[aml.devidx].name, 4);
  403. aml_drvname(aml.drvidx, drv); aml_drvname(aml.altidx, alt);
  404. if(!memcmp(drv, alt, sizeof(alt))) memset(alt, 0, sizeof(alt));
  405. #ifdef AML_DEBUG
  406. printf("-----------------add resource dev %d '%s' drv %d(%d) '%s'('%s') reg %d-------------\n",
  407. aml.devidx, name, aml.drvidx, aml.altidx, drv, alt, aml.regidx);
  408. aml_dump(&aml.node[aml.devidx]);
  409. aml_dump(&aml.node[aml.drvidx]);
  410. if(aml.altidx != -1U) aml_dump(&aml.node[aml.altidx]);
  411. aml_dump(&aml.node[aml.regidx]);
  412. printf("--------------------------------------------------------------\r\n");
  413. #endif
  414. if(drv[0]) {
  415. ptr = aml.node[aml.regidx].data.p[0]; end = aml.node[aml.regidx].data.p[0] + aml.node[aml.regidx].data.d[2];
  416. if(aml.node[aml.regidx].type == 0x0011 && ptr >= aml.memmin && end < aml.memmax) {
  417. /* ResourceTemplate, lásd ACPI Specification, 6.4 Resource Data Types for ACPI fejezet */
  418. while(ptr < end) {
  419. if(*ptr & 0x80) { t = *ptr; s = (ptr[2] << 8) | ptr[1]; ptr += 3; }
  420. else { t = *ptr >> 3; s = *ptr & 7; ptr++; }
  421. #if AML_DEBUG+0 > 1
  422. printf("t %02x s %d ", t, s); for(i = 0; i < (int)s; i++) { printf(" %02x", ptr[i]); } printf("\n");
  423. #endif
  424. switch(t) {
  425. case 0x04: /* IRQ Format Descriptor */
  426. for(n = ptr[0] | (ptr[1] << 8), i = 0; i < 16; i++)
  427. if(n & (1 << i)) HWDET_RESOURCE(name, drv, alt, HWDET_IRQ, i, 0);
  428. break;
  429. case 0x05: /* DMA Format Descriptor */
  430. for(n = ptr[0], i = 0; i < 8; i++)
  431. if(n & (1 << i)) HWDET_RESOURCE(name, drv, alt, HWDET_DMA, i, 1);
  432. break;
  433. case 0x08: /* I/O Port Descriptor */
  434. for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8), re = (uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8);
  435. rs <= re; rs += ptr[5] ? ptr[5] : 1)
  436. if(rs) HWDET_RESOURCE(name, drv, alt, HWDET_IO, rs, ptr[6] ? ptr[6] : (ptr[5] ? ptr[5] : 1));
  437. break;
  438. case 0x09: /* Fixed Location I/O Port Descriptor */
  439. ra = ptr[0] | (ptr[1] << 8); if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, ra, ptr[2] ? ptr[2] : 1);
  440. break;
  441. case 0x0A: /* Fixed DMA Descriptor */
  442. HWDET_RESOURCE(name, drv, alt, HWDET_DMA, ptr[0] | (ptr[1] << 8), 1 << ptr[4]);
  443. break;
  444. case 0x81: /* 24-Bit Memory Range Descriptor */
  445. for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8), re = (uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8),
  446. ra = ((uint64_t)ptr[5] << 16) | ((uint64_t)ptr[6] << 24); rs <= re; rs += ra) {
  447. if(rs) {
  448. HWDET_RESVMEM(rs, ((uint64_t)ptr[7] << 8) | ((uint64_t)ptr[8] << 16));
  449. HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, ((uint64_t)ptr[7] << 8) | ((uint64_t)ptr[8] << 16));
  450. }
  451. if(!ra) ra = 65536;
  452. }
  453. break;
  454. case 0x82: /* Generic Register Descriptor */
  455. memcpy(&ra, ptr + 4, 8); rs = ptr[5] ? 1 << (ptr[5]-1) : 1;
  456. switch(ptr[0]) {
  457. case 0: if(ra) HWDET_RESVMEM(ra, rs); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, ra, rs); break;
  458. case 1: if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, ra, rs); break;
  459. default: HWDET_RESOURCE(name, drv, alt, ptr[0] - 2 + HWDET_PCI, ra, rs); break;
  460. }
  461. break;
  462. case 0x85: /* 32-Bit Memory Range Descriptor */
  463. for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8) | ((uint64_t)ptr[3] << 16) | ((uint64_t)ptr[4] << 24),
  464. re = (uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8) | ((uint64_t)ptr[7] << 16) | ((uint64_t)ptr[8] << 24),
  465. ra = (uint64_t)ptr[9] | ((uint64_t)ptr[10] << 8) | ((uint64_t)ptr[11] << 16) | ((uint64_t)ptr[12] << 24);
  466. rs <= re; rs += ra) {
  467. if(rs) {
  468. HWDET_RESVMEM(rs, ptr[13] | (ptr[14] << 8) | (ptr[15] << 16) | (ptr[16] << 24));
  469. HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, ptr[13] | (ptr[14] << 8) | (ptr[15] << 16) | (ptr[16] << 24));
  470. }
  471. if(!ra) ra = 65536;
  472. }
  473. break;
  474. case 0x86: /* 32-Bit Fixed Memory Range Descriptor */
  475. rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8) | ((uint64_t)ptr[3] << 16) | ((uint64_t)ptr[4] << 24);
  476. re = (uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8) | ((uint64_t)ptr[7] << 16) | ((uint64_t)ptr[8] << 24);
  477. if(rs) { HWDET_RESVMEM(rs, re); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, re); }
  478. break;
  479. case 0x87: /* Address Space Resource Descriptors */
  480. ra = ((uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8) | ((uint64_t)ptr[5] << 16) | ((uint64_t)ptr[6] << 24)) + 1;
  481. rs = ((uint64_t)ptr[7] | ((uint64_t)ptr[8] << 8) | ((uint64_t)ptr[9] << 16) | ((uint64_t)ptr[10] << 24));
  482. re = ((uint64_t)ptr[11] | ((uint64_t)ptr[12] << 8) | ((uint64_t)ptr[13] << 16) | ((uint64_t)ptr[14] << 24));
  483. rt = ((uint64_t)ptr[15] | ((uint64_t)ptr[16] << 8) | ((uint64_t)ptr[17] << 16) | ((uint64_t)ptr[18] << 24));
  484. rl = ((uint64_t)ptr[19] | ((uint64_t)ptr[20] << 8) | ((uint64_t)ptr[21] << 16) | ((uint64_t)ptr[22] << 24));
  485. asd: if(ptr[1] & 2) rt = -rt;
  486. if(ra < rl) ra = rl;
  487. if(!ra) ra = !ptr[0] ? 65536 : 1;
  488. for(; rs <= re; rs += ra) {
  489. if(rs)
  490. switch(ptr[0]) {
  491. case 0: HWDET_RESVMEM(rs + rt, rl); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs + rt, rl); break;
  492. case 1: if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, rs + rt, rl); break;
  493. }
  494. }
  495. break;
  496. case 0x88: /* Word Address Space Descriptor */
  497. ra = ((uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8)) + 1;
  498. rs = ((uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8)); re = ((uint64_t)ptr[7] | ((uint64_t)ptr[8] << 8));
  499. rt = ((uint64_t)ptr[9] | ((uint64_t)ptr[10] << 8)); rl = ((uint64_t)ptr[11] | ((uint64_t)ptr[12] << 8));
  500. goto asd;
  501. break;
  502. case 0x89: /* Extended Interrupt Descriptor */
  503. for(n = ptr[1], i = 0; i < n; i++)
  504. HWDET_RESOURCE(name, drv, alt, HWDET_IRQ, (uint64_t)ptr[2+i*4] | ((uint64_t)ptr[3+i*4] << 8) |
  505. ((uint64_t)ptr[4+i*4] << 16) | ((uint64_t)ptr[5+i*4] << 24), 0);
  506. break;
  507. case 0x8A: /* QWord Address Space Descriptor */
  508. memcpy(&ra, ptr + 3, 8); ra++;
  509. memcpy(&rs, ptr + 11, 8); memcpy(&re, ptr + 19, 8);
  510. memcpy(&rt, ptr + 27, 8); memcpy(&rl, ptr + 35, 8);
  511. goto asd;
  512. break;
  513. case 0x8B: /* Extended Address Space Descriptor */
  514. memcpy(&ra, ptr + 5, 8); ra++;
  515. memcpy(&rs, ptr + 13, 8); memcpy(&re, ptr + 21, 8);
  516. memcpy(&rt, ptr + 29, 8); memcpy(&rl, ptr + 37, 8);
  517. goto asd;
  518. break;
  519. case 0x8C: case 0x8E: /* Connectors */
  520. case 0x8D: case 0x8F: case 0x90: case 0x91: case 0x92: /* Pins */
  521. case 0x0F: /* End Tag */ break;
  522. #ifdef AML_DEBUG
  523. default: printf("unhandled ResourceTemplate %lx type %02x\n",(uintptr_t)ptr, t); exit(1); break;
  524. #endif
  525. }
  526. ptr += s;
  527. }
  528. } else
  529. if(aml.node[aml.regidx].type) HWDET_RESOURCE(name, drv, alt, HWDET_NONE, 0, 0);
  530. }
  531. }
  532. /**
  533. * AML név beolvasása
  534. */
  535. static uint8_t *aml_NameString(uint8_t *ptr)
  536. {
  537. int c;
  538. #ifdef AML_DEBUG
  539. if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
  540. #endif
  541. while(*ptr == '\\' || *ptr == '^') ptr++;
  542. switch(*ptr) {
  543. case 0x00: ptr++; c = 0; break;
  544. case 0x2E: ptr++; c = 8; break;
  545. case 0x2F: ptr++; c = *ptr++ << 2; break;
  546. default: c = 4; break;
  547. }
  548. return ptr + c;
  549. }
  550. /**
  551. * AML változónév beolvasása
  552. */
  553. static uint8_t *aml_SuperName(uint8_t *ptr, aml_t *node)
  554. {
  555. uint8_t *st = ptr;
  556. uint16_t op;
  557. #ifdef AML_DEBUG
  558. if(stkchk + 32 > stkmax) stkmax = stkchk + 32;
  559. #endif
  560. ptr = aml_opcode(ptr, &op);
  561. node->type = op;
  562. switch(op) {
  563. case 0x0000: /* NullStr */ node->data.q[0] = 0; node->type = 0x000D; break;
  564. case 0x0009: /* Simplename */ if((op = aml_lookup(st))) memcpy(node, &aml.node[op], sizeof(aml_t)); break;
  565. case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067: /* LocalX */
  566. case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F: /* ArgX */
  567. break;
  568. case 0x5B31: /* DebugObj */ break;
  569. default: ptr = st; break;
  570. }
  571. return ptr;
  572. }
  573. /**
  574. * AML mezőlista beolvasása
  575. */
  576. static uint8_t *aml_FieldList(uint8_t *ptr, uint8_t *end, aml_t *node)
  577. {
  578. uint32_t pos = 0;
  579. AML_STKENTER(24);
  580. while(ptr < end) {
  581. switch(*ptr) {
  582. case 0: /* reserved */ ptr++; ptr = aml_pkg(ptr); pos += aml.len; break;
  583. case 1: /* access */ ptr += 3; break;
  584. case 2: /* connect */ ptr = aml_NameString(ptr + 1); break;
  585. case 3: /* extended */ ptr += 3 + ptr[2]; break;
  586. default: /* named */
  587. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  588. NODE.name = ptr; ptr += 4; ptr = aml_pkg(ptr);
  589. NODE.type = 0x5B13; NODE.parent = aml.par;
  590. NODE.data.q[0] = node->data.q[0];
  591. NODE.data.d[2] = pos; NODE.data.d[3] = aml.len;
  592. pos += aml.len;
  593. aml.num++;
  594. break;
  595. }
  596. }
  597. AML_STKLEAVE(24);
  598. return ptr;
  599. }
  600. /**
  601. * AML bájtkód értelmezése
  602. */
  603. static uint8_t *aml_TermArg(uint8_t *ptr, uint8_t *end, aml_t *node)
  604. {
  605. aml_t arg1, arg2;
  606. uint8_t *st = ptr, *s;
  607. uint16_t op;
  608. uint32_t l, par, num;
  609. ptr = aml_opcode(ptr, &op);
  610. #ifdef AML_DEBUG
  611. AML_STKENTER(104);
  612. if(aml.num > numchk) numchk = aml.num;
  613. #if AML_DEBUG+0 > 1
  614. printf("%08lx op %x (ptr %lx num %d par %d)\n",(uintptr_t)st,op,(uintptr_t)ptr,aml.num,aml.par);
  615. #endif
  616. #endif
  617. memset(&arg1, 0, sizeof(arg1)); memset(&arg2, 0, sizeof(arg2));
  618. switch(op) {
  619. case 0x5B30: /* RevisionOp */
  620. case 0x0000: /* ZeroOp */ node->data.q[0] = 0; node->type = 0x000E; break;
  621. case 0x0001: /* OneOp */ node->data.q[0] = 1; node->type = 0x000E; break;
  622. case 0x00FF: /* OnesOp */ node->data.q[0] = ~0UL; node->type = 0x000E; break;
  623. case 0x0006: /* AliasOp */
  624. l = aml_lookup(ptr); ptr = aml_NameString(ptr);
  625. s = ptr; ptr = aml_NameString(ptr);
  626. if(l) {
  627. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  628. memcpy(&NODE, &aml.node[l], sizeof(aml_t));
  629. NODE.name = s; NODE.parent = aml.par; aml_fn(&NODE);
  630. aml.num++;
  631. }
  632. break;
  633. case 0x0008: /* NameOp */
  634. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  635. NODE.name = ptr; ptr = aml_NameString(ptr);
  636. NODE.type = op; NODE.parent = par = aml.par; aml.par = aml.num; aml_fn(&NODE);
  637. if(!memcmp(NODE.name, "_HID", 4)) aml.drvidx = aml.num; else
  638. if(!memcmp(NODE.name, "_CID", 4)) aml.altidx = aml.num; else
  639. if(!memcmp(NODE.name, "_CRS", 4)) aml.regidx = aml.num;
  640. num = aml.num++; ptr = aml_TermArg(ptr, end, &aml.node[num]);
  641. aml.num = num + 1; aml.par = par;
  642. break;
  643. case 0x0009: /* ObjReference/Call */
  644. if((l = aml_lookup(st))) {
  645. if(aml.node[l].type == 0x0014) {
  646. if(aml.sp >= 16 && aml.sp - 16 < AML_MAXLEVEL*16) {
  647. aml.sp -= 8;
  648. /* ACPI AML bug: 8 paramétert lehet címezni, de a 0x14 MethodFlags-ében csak 7 paramétert lehet megadni */
  649. for(par = 0; par <= (aml.node[l].data.d[3] & 7); par++) {
  650. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  651. aml.stack[aml.sp + par] = arg1.data.q[0];
  652. }
  653. aml.sp -= 8;
  654. aml_TermList(aml.node[l].data.p[0], aml.node[l].data.p[0] + aml.node[l].data.d[2], &arg1);
  655. node->data.q[0] = arg1.data.q[0]; node->data.q[1] = arg1.data.q[1]; node->type = arg1.type;
  656. }
  657. } else { memcpy(&node->data, &aml.node[l].data, sizeof(arg1.data)); node->type = aml.node[l].type; }
  658. }
  659. break;
  660. case 0x000A: /* BytePrefix */ node->data.q[0] = *ptr++; node->type = op; break;
  661. case 0x000B: /* WordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 2); ptr += 2; node->type = op; break;
  662. case 0x000C: /* DWordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 4); ptr += 4; node->type = op; break;
  663. case 0x000E: /* QWordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 8); ptr += 8; node->type = op; break;
  664. case 0x000D: /* StringPrefix */ node->data.p[0] = ptr; node->type = op; while(ptr[-1]) ptr++; break;
  665. case 0x0010: /* Scope */
  666. case 0x0014: /* Method */
  667. case 0x5B82: /* Device */
  668. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  669. ptr = aml_pkg(ptr); s = st + (op > 0xff ? 2 : 1) + aml.len;
  670. if(op == 0x5B82) aml.devidx = aml.num;
  671. NODE.name = ptr; ptr = aml_NameString(ptr);
  672. NODE.type = op; NODE.parent = par = aml.par; aml.par = aml.num;
  673. aml_fn(&NODE);
  674. /* ha metódus, akkor csak akkor futtatjuk le, ha eszközmeghajtótípus, vagy regiszterdefiníció
  675. * mivel direktben a metódus node-jával hívjuk, felül fognak ezek íródni a visszatérési értékkel,
  676. * és a továbbiakban mint normál változók fognak működni */
  677. if(op == 0x0014) {
  678. NODE.data.d[3] = (*ptr++ & 7);
  679. NODE.data.p[0] = ptr;
  680. NODE.data.d[2] = s - ptr;
  681. l = 0; aml.mtdidx = aml.num;
  682. if(!memcmp(NODE.name, "_HID", 4)) { l = 1; aml.drvidx = aml.num; } else
  683. if(!memcmp(NODE.name, "_CID", 4)) { l = 1; aml.altidx = aml.num; } else
  684. if(!memcmp(NODE.name, "_CRS", 4)) { l = 1; aml.regidx = aml.num; }
  685. if(l) { if(!aml.sp) l = 0; else { aml.sp -= 16; memset(&aml.stack[aml.sp], 0, 16 * sizeof(aml.stack[0])); } }
  686. } else l = 1;
  687. #if AML_DEBUG+0 > 1
  688. printf("SCOPE++ %04x '%c%c%c%c' num %d par %d aml.len %d s %lx l %d sp %d\n", op,
  689. NODE.name[0],NODE.name[1],NODE.name[2],NODE.name[3],aml.num,par,aml.len,(uintptr_t)s,l,aml.sp);
  690. #endif
  691. num = aml.num++;
  692. if(l) ptr = aml_TermList(ptr, s, &aml.node[num]);
  693. ptr = s;
  694. if(op == 0x0014) { aml.mtdidx = -1U; if(l) aml.sp += 16; }
  695. #if AML_DEBUG+0 > 1
  696. printf("SCOPE-- num %d (new %d) %lx sp %d\n",aml.num,num+1,(uintptr_t)ptr,aml.sp);
  697. #endif
  698. if(op == 0x5B82 && aml.devidx != -1U && aml.drvidx != -1U && aml.regidx != -1U) {
  699. aml_ResourceTemplate();
  700. aml.devidx = aml.drvidx = aml.altidx = aml.regidx = -1U;
  701. }
  702. aml.num = num + 1; aml.par = par;
  703. break;
  704. case 0x0015: /* ExternalOp */
  705. ptr = aml_NameString(ptr) + 2;
  706. break;
  707. case 0x0011: /* Buffer */
  708. ptr = aml_pkg(ptr); st += 1 + aml.len;
  709. ptr = aml_TermArg(ptr, end, &arg1);
  710. node->data.q[1] = arg1.data.q[0];
  711. node->data.p[0] = ptr;
  712. node->type = op;
  713. ptr = st;
  714. break;
  715. case 0x0012: /* Package */
  716. ptr = aml_pkg(ptr); st += 1 + aml.len;
  717. node->data.d[2] = aml.len;
  718. node->data.d[3] = *ptr++;
  719. node->data.p[0] = ptr;
  720. node->type = op;
  721. ptr = st;
  722. break;
  723. case 0x0013: /* VarPackage */
  724. ptr = aml_pkg(ptr); st += 1 + aml.len;
  725. ptr = aml_TermArg(ptr, end, node);
  726. node->data.d[2] = aml.len;
  727. node->data.d[3] = 0;
  728. node->data.p[0] = ptr;
  729. node->type = op;
  730. ptr = st;
  731. break;
  732. case 0x5B01: /* MutexOp */ ptr = aml_NameString(ptr) + 1; break;
  733. case 0x5B02: /* EventOp */ ptr = aml_NameString(ptr); break;
  734. case 0x5B12: /* CondRefOfOp */
  735. case 0x0071: /* RefOfOp */
  736. ptr = aml_SuperName(ptr, &arg1);
  737. ptr = aml_SuperName(ptr, &arg2);
  738. if(arg1.type != 0x0009) {
  739. aml_set(&arg2, &arg1);
  740. memcpy(node, &arg1, sizeof(arg1));
  741. } else
  742. if(op == 0x0071) return (uint8_t*)-1UL;
  743. break;
  744. case 0x5B1F: /* LoadTableOp */
  745. ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1);
  746. ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1);
  747. break;
  748. case 0x5B20: /* LoadOp */
  749. l = aml_lookup(ptr); ptr = aml_NameString(ptr);
  750. ptr = aml_SuperName(ptr, &arg1);
  751. if(l) { memcpy(&aml.node[l].data, &arg1.data, sizeof(arg1.data)); aml.node[l].type = arg1.type; }
  752. break;
  753. case 0x5B21: /* StallOp */
  754. case 0x5B22: /* SleepOp */
  755. ptr = aml_TermArg(ptr, end, &arg1);
  756. break;
  757. case 0x5B23: /* AcquireOp */
  758. ptr = aml_SuperName(ptr, &arg1) + 2;
  759. break;
  760. case 0x5B24: /* SignalOp */
  761. case 0x5B26: /* ResetOp */
  762. case 0x5B27: /* ReleaseOp */
  763. ptr = aml_SuperName(ptr, &arg1);
  764. break;
  765. case 0x5B25: /* WaitOp */
  766. ptr = aml_SuperName(ptr, &arg1);
  767. ptr = aml_TermArg(ptr, end, &arg1);
  768. break;
  769. case 0x5B28: /* FromBCDOp */
  770. case 0x5B29: /* ToBCDOp */
  771. ptr = aml_TermArg(ptr, end, &arg1);
  772. ptr = aml_SuperName(ptr, &arg1);
  773. break;
  774. case 0x5B32: /* FatalOp */ return (uint8_t*)-1UL;
  775. case 0x5B80: /* OpRegion */
  776. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  777. NODE.name = ptr; ptr = aml_NameString(ptr);
  778. NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
  779. NODE.data.b[12] = *ptr++; /* space */
  780. ptr = aml_TermArg(ptr, end, &arg1); /* address */
  781. NODE.data.q[0] = arg1.data.q[0];
  782. ptr = aml_TermArg(ptr, end, &arg1); /* length */
  783. NODE.data.d[2] = arg1.data.d[0];
  784. /* ha rendszermemóriára hivatkozik, ki kell venni a szabad memória listából */
  785. if(!NODE.data.b[12] && NODE.data.q[0]) HWDET_RESVMEM(NODE.data.q[0], NODE.data.d[2]);
  786. aml.num++;
  787. break;
  788. case 0x5B81: /* Field */
  789. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  790. ptr = aml_pkg(ptr); st += 2 + aml.len;
  791. NODE.name = ptr; ptr = aml_NameString(ptr);
  792. NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
  793. NODE.data.d[0] = 0;
  794. NODE.data.d[1] = *ptr++; /* flags */
  795. aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
  796. ptr = st;
  797. break;
  798. case 0x5B83: /* Processor (nem használt a v6.4 óta) */
  799. ptr = aml_pkg(ptr);
  800. arg1.data.q[0] = 0; memcpy(&arg1.data, ptr, 4);
  801. HWDET_RESOURCE((char*)&arg1.data, "CORE", "", HWDET_CPU, 0, ptr[4]);
  802. ptr = st + 2 + aml.len;
  803. break;
  804. case 0x5B86: /* IndexField */
  805. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  806. ptr = aml_pkg(ptr); st += 2 + aml.len;
  807. NODE.name = ptr; ptr = aml_NameString(ptr);
  808. NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
  809. NODE.data.d[0] = aml_lookup(ptr); ptr = aml_NameString(ptr);
  810. NODE.data.d[1] = *ptr++; /* flags */
  811. aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
  812. ptr = st;
  813. break;
  814. case 0x5B87: /* BankField */
  815. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  816. ptr = aml_pkg(ptr); st += 2 + aml.len;
  817. NODE.name = ptr; ptr = aml_NameString(ptr);
  818. NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
  819. NODE.data.d[0] = aml_lookup(ptr); ptr = aml_NameString(ptr);
  820. ptr = aml_TermArg(ptr, end, &arg1);
  821. NODE.data.d[1] = *ptr++; /* flags */
  822. NODE.data.q[1] = arg1.data.q[0];
  823. aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
  824. ptr = st;
  825. break;
  826. case 0x5B88: /* DataRegion */
  827. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  828. ptr = aml_pkg(ptr); st += 2 + aml.len;
  829. NODE.name = ptr; ptr = aml_NameString(ptr);
  830. NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
  831. ptr = aml_TermArg(ptr, end, &arg1); NODE.data.q[0] = arg1.data.q[0];
  832. ptr = aml_TermArg(ptr, end, &arg1); NODE.data.d[2] = arg1.data.d[0];
  833. ptr = aml_TermArg(ptr, end, &arg1); NODE.data.d[3] = arg1.data.d[0];
  834. aml.num++;
  835. ptr = st;
  836. break;
  837. case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067: /* LocalX */
  838. case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F: /* ArgX */
  839. node->type = op; op = aml.sp + op - 0x60; node->data.q[0] = op < AML_MAXLEVEL*16 ? aml.stack[op] : 0;
  840. break;
  841. case 0x0070: /* StoreOp */
  842. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  843. ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
  844. break;
  845. case 0x0075: /* IncrementOp */
  846. ptr = aml_SuperName(ptr, &arg1); aml_get(&arg2, &arg1);
  847. arg2.data.q[0]++; aml_set(&arg1, &arg2);
  848. node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
  849. break;
  850. case 0x0076: /* DecrementOp */
  851. ptr = aml_SuperName(ptr, &arg1); aml_get(&arg2, &arg1);
  852. arg2.data.q[0]--; aml_set(&arg1, &arg2);
  853. node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
  854. break;
  855. case 0x0083: /* DerefOfOp */
  856. ptr = aml_TermArg(ptr, end, &arg1);
  857. if(arg1.type == 0x000D) {
  858. l = aml_lookup(arg1.data.p[0]);
  859. if(l) memcpy(&arg1, &aml.node[l], sizeof(arg1));
  860. }
  861. memcpy(node, &arg1, sizeof(arg1));
  862. break;
  863. case 0x0072: /* AddOp */
  864. case 0x0073: /* ConcatOp */
  865. case 0x0074: /* SubtractOp */
  866. case 0x0077: /* MultiplyOp */
  867. case 0x0078: /* DivideOp */
  868. case 0x0079: /* ShiftLeftOp */
  869. case 0x007A: /* ShiftRightOp */
  870. case 0x007B: /* AndOp */
  871. case 0x007C: /* NandOp */
  872. case 0x007D: /* OrOp */
  873. case 0x007E: /* NorOp */
  874. case 0x007F: /* XorOp */
  875. case 0x0084: /* ConcatResOp */
  876. case 0x0085: /* ModOp */
  877. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  878. ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
  879. switch(op) {
  880. case 0x0072: arg1.data.q[0] += arg2.data.q[0]; break;
  881. case 0x0074: arg1.data.q[0] -= arg2.data.q[0]; break;
  882. case 0x0077: arg1.data.q[0] *= arg2.data.q[0]; break;
  883. case 0x0078: arg1.data.q[0] = arg2.data.q[0] ? arg1.data.q[0] / arg2.data.q[0] : 0; break;
  884. case 0x0079: arg1.data.q[0] <<= arg2.data.q[0]; break;
  885. case 0x007A: arg1.data.q[0] >>= arg2.data.q[0]; break;
  886. case 0x007B: arg1.data.q[0] &= arg2.data.q[0]; break;
  887. case 0x007C: arg1.data.q[0] = ~(arg1.data.q[0] & arg2.data.q[0]); break;
  888. case 0x007D: arg1.data.q[0] |= arg2.data.q[0]; break;
  889. case 0x007E: arg1.data.q[0] = ~(arg1.data.q[0] | arg2.data.q[0]); break;
  890. case 0x007F: arg1.data.q[0] ^= arg2.data.q[0]; break;
  891. case 0x0085: arg1.data.q[0] = arg2.data.q[0] ? arg1.data.q[0] % arg2.data.q[0] : 0; break;
  892. }
  893. ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
  894. node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
  895. break;
  896. case 0x0088: /* IndexOp */
  897. ptr = aml_TermArg(ptr, end, &arg1);
  898. ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
  899. arg1.data.q[0] += arg2.data.q[0];
  900. ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
  901. node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
  902. break;
  903. case 0x0090: /* LandOp */
  904. case 0x0091: /* LorOp */
  905. case 0x9293: /* LNotEqualOp */
  906. case 0x9294: /* LLessEqualOp */
  907. case 0x9295: /* LGreaterEqualOp */
  908. case 0x0093: /* LEqualOp */
  909. case 0x0094: /* LGreaterOp */
  910. case 0x0095: /* LLessOp */
  911. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  912. ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
  913. switch(op) {
  914. case 0x0090: arg1.data.q[0] = (arg1.data.q[0] && arg2.data.q[0]); break;
  915. case 0x0091: arg1.data.q[0] = (arg1.data.q[0] || arg2.data.q[0]); break;
  916. case 0x9293: arg1.data.q[0] = (arg1.data.q[0] != arg2.data.q[0]); break;
  917. case 0x9294: arg1.data.q[0] = (arg1.data.q[0] <= arg2.data.q[0]); break;
  918. case 0x9295: arg1.data.q[0] = (arg1.data.q[0] >= arg2.data.q[0]); break;
  919. case 0x0093: arg1.data.q[0] = (arg1.data.q[0] == arg2.data.q[0]); break;
  920. case 0x0094: arg1.data.q[0] = (arg1.data.q[0] > arg2.data.q[0]); break;
  921. case 0x0095: arg1.data.q[0] = (arg1.data.q[0] < arg2.data.q[0]); break;
  922. }
  923. node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
  924. break;
  925. case 0x0081: /* FindSetLeftBitOp */
  926. case 0x0082: /* FindSetRightBitOp */
  927. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  928. ptr = aml_SuperName(ptr, &arg2);
  929. if(arg1.data.q[0]) {
  930. if(op == 0x0081) for(l = 1; arg1.data.q[0] & 1; l++, arg1.data.q[0] >>= 1);
  931. else for(l = 1; !(arg1.data.q[0] & 1); l++, arg1.data.q[0] >>= 1);
  932. } else l = 0;
  933. arg2.data.q[0] = l; aml_set(&arg2, &arg2);
  934. node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
  935. break;
  936. case 0x0092: /* LnotOp */
  937. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
  938. arg1.data.q[0] = !arg1.data.q[0];
  939. ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
  940. node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
  941. break;
  942. case 0x0086: /* NotifyOp */
  943. ptr = aml_SuperName(ptr, &arg1);
  944. ptr = aml_TermArg(ptr, end, &arg2);
  945. #ifdef AML_DEBUG
  946. aml_get(&arg2, &arg2);
  947. printf("NotifyOp\n");
  948. aml_dump(&arg1);
  949. aml_dump(&arg2);
  950. #endif
  951. break;
  952. case 0x0087: /* SizeofOp */
  953. ptr = aml_SuperName(ptr, &arg1);
  954. node->data.q[0] = 0;
  955. switch(arg1.type) {
  956. case 0x000A: node->data.q[0] = 1; break;
  957. case 0x000B: node->data.q[0] = 2; break;
  958. case 0x000C: node->data.q[0] = 4; break;
  959. case 0x000D: if((s = node->data.p[0]) && s >= aml.memmin && s < aml.memmax) for(; *s; s++, node->data.q[0]++); break;
  960. case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067:
  961. case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F:
  962. case 0x000E: node->data.q[0] = 8; break;
  963. case 0x0011: case 0x0012: case 0x0013: case 0x5B80: node->data.q[0] = arg1.data.d[2]; break;
  964. case 0x5B13: node->data.q[0] = (arg1.data.d[3] + 7) >> 3; break;
  965. }
  966. node->type = 0x000E;
  967. break;
  968. case 0x0089: /* MatchOp */
  969. ptr = aml_TermArg(ptr, end, &arg1); /* package */
  970. ptr++; /* op1 */
  971. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* obj1 */
  972. ptr++; /* op2 */
  973. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* obj2 */
  974. ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* startindex */
  975. node->data.q[0] = ~0UL; node->type = 0x000E;
  976. break;
  977. case 0x008A: /* CreateDWordField */
  978. case 0x008B: /* CreateWordField */
  979. case 0x008C: /* CreateByteField */
  980. case 0x008D: /* CreateBitField */
  981. case 0x008F: /* CreateQWordField */
  982. case 0x5B13: /* CreateFieldOp */
  983. if(aml.num >= aml.max) return (uint8_t*)-1UL;
  984. ptr = aml_TermArg(ptr, end, &arg1); /* SourceBuff */
  985. ptr = aml_TermArg(ptr, end, &arg2); /* ByteIndex (0x8D/0x5B13=BitIndex) */
  986. NODE.name = ptr; ptr = aml_NameString(ptr);
  987. NODE.type = 0x5B13; NODE.parent = aml.par; aml_fn(&NODE);
  988. NODE.data.q[0] = arg1.data.q[0]; NODE.data.d[2] = arg2.data.d[0];
  989. switch(op) { /* size */
  990. case 0x008A: NODE.data.d[3] = 32; NODE.data.d[2] <<= 3; break;
  991. case 0x008B: NODE.data.d[3] = 16; NODE.data.d[2] <<= 3; break;
  992. case 0x008C: NODE.data.d[3] = 8; NODE.data.d[2] <<= 3; break;
  993. case 0x008D: NODE.data.d[3] = 1; break;
  994. case 0x008F: NODE.data.d[3] = 64; NODE.data.d[2] <<= 3; break;
  995. case 0x5B13: ptr = aml_TermArg(ptr, end, &arg2); NODE.data.d[3] = arg2.data.d[0]; break;
  996. }
  997. aml.num++;
  998. break;
  999. case 0x008E: /* ObjectType */
  1000. ptr = aml_SuperName(ptr, &arg1);
  1001. node->type = 0x000E;
  1002. switch(arg1.type) {
  1003. case 0x000A: case 0x000B: case 0x000C: case 0x000E: node->data.q[0] = 1; break; /* Integer */
  1004. case 0x000D: node->data.q[0] = 2; break; /* String */
  1005. case 0x0011: node->data.q[0] = 3; break; /* Buffer */
  1006. case 0x0012: case 0x0013: node->data.q[0] = 4; break; /* Package */
  1007. case 0x5B81: node->data.q[0] = 5; break; /* Field */
  1008. case 0x5B82: node->data.q[0] = 6; break; /* Device */
  1009. case 0x5B02: node->data.q[0] = 7; break; /* Event */
  1010. case 0x0014: node->data.q[0] = 8; break; /* Method */
  1011. case 0x5B01: node->data.q[0] = 9; break; /* Mutex */
  1012. case 0x5B80: node->data.q[0] =10; break; /* OpRegion */
  1013. case 0x5B84: node->data.q[0] =11; break; /* PowerRes */
  1014. case 0x5B83: node->data.q[0] =12; break; /* Processor */
  1015. case 0x5B85: node->data.q[0] =13; break; /* ThermalZone */
  1016. case 0x5B13: node->data.q[0] =14; break; /* BufferField */
  1017. case 0x5B1F: case 0x5B20: node->data.q[0] =15; break; /* DDBHandle */
  1018. case 0x5B30: node->data.q[0] =16; break; /* DebugObj */
  1019. default: node->data.q[0] = 0;
  1020. }
  1021. break;
  1022. case 0x00A0: /* If */
  1023. ptr = aml_pkg(ptr); st += 1 + aml.len;
  1024. ptr = aml_TermArg(ptr, end, &arg1);
  1025. if(arg1.data.q[0]) ptr = aml_TermList(ptr, st, node); else ptr = st;
  1026. if(*ptr == 0xA1) {
  1027. ptr = aml_pkg(ptr + 1); st += 1 + aml.len;
  1028. if(arg1.data.q[0]) ptr = st; else ptr = aml_TermList(ptr, st, node);
  1029. }
  1030. break;
  1031. case 0x00A1: /* Else blokk If nélkül? */
  1032. ptr = aml_pkg(ptr); ptr = st + 1 + aml.len;
  1033. break;
  1034. case 0x00A2: /* While */
  1035. /* ezt direkt kihagyjuk, mert nekünk csak arra kell az AML, hogy a regisztermezőket lekérjük */
  1036. ptr = aml_pkg(ptr); ptr = st + 1 + aml.len;
  1037. break;
  1038. case 0x00A4: /* Return */
  1039. ptr = aml_TermArg(ptr, end, &arg1);
  1040. memcpy(&node->data, &arg1.data, sizeof(arg1.data)); node->type = arg1.type;
  1041. break;
  1042. case 0x5B2A: /* fenntartott */
  1043. case 0x5B33: /* TimerOp */
  1044. case 0x009F: /* Continue */
  1045. case 0x00A3: /* Noop */
  1046. case 0x00CC: /* BreakPoint */ break;
  1047. default: ptr = st; break;
  1048. }
  1049. AML_STKLEAVE(104);
  1050. return ptr;
  1051. }
  1052. /**
  1053. * AML bájtkód értelmezése
  1054. */
  1055. static uint8_t *aml_TermList(uint8_t *ptr, uint8_t *end, aml_t *node)
  1056. {
  1057. uint8_t *st;
  1058. AML_STKENTER(24);
  1059. if(!node) { node = &aml.node[0]; memset(node, 0, sizeof(aml_t)); }
  1060. while(ptr < end) {
  1061. st = ptr; ptr = aml_TermArg(st, end, node);
  1062. if(ptr == st) {
  1063. #ifdef AML_DEBUG
  1064. printf("unknown opcode %08lx %02x %02x\n", (uintptr_t)ptr, ptr[0], ptr[1]); exit(1);
  1065. #endif
  1066. return (uint8_t*)-1UL;
  1067. }
  1068. }
  1069. AML_STKLEAVE(24);
  1070. return ptr;
  1071. }
  1072. typedef struct {
  1073. char *name, *drv, *alt;
  1074. uint32_t parent, intparent, addrcells, sizecells, intcells, dmacells, clkcells, gpiocells;
  1075. uint32_t type, phandle, phparent;
  1076. uint32_t mapsz[2], *map[2];
  1077. uint64_t cpurel;
  1078. } fdt_t;
  1079. static fdt_t *fdt_nodes;
  1080. static uint32_t fdt_numnodes;
  1081. /**
  1082. * Get value (from a property data)
  1083. */
  1084. static uint64_t fdt_value(uint32_t *ptr, uint32_t size)
  1085. {
  1086. uint64_t r = 0;
  1087. uint8_t *p = (uint8_t*)ptr;
  1088. if(size) {
  1089. r = ((uint64_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
  1090. if(size > 1) { p += 4; r <<= 32; r |= ((uint64_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; }
  1091. }
  1092. return r;
  1093. }
  1094. /**
  1095. * Get address (get value from property data and translate to parent address space)
  1096. */
  1097. static uint64_t fdt_addr(uint32_t *ptr, uint32_t size, int map, fdt_t *node)
  1098. {
  1099. uint32_t i, siz, as;
  1100. uint64_t a = fdt_value(ptr, size), c, b, s;
  1101. if(node->parent) {
  1102. node = &fdt_nodes[node->parent];
  1103. as = fdt_nodes[node->parent].addrcells;
  1104. while(1) {
  1105. if(node->map[map] && node->mapsz[map] && node->sizecells) {
  1106. siz = node->mapsz[map] >> 2;
  1107. for(i = 0; i < siz;) {
  1108. c = fdt_value(&node->map[map][i], node->addrcells); i += node->addrcells;
  1109. b = fdt_value(&node->map[map][i], as); i += as;
  1110. s = fdt_value(&node->map[map][i], node->sizecells); i += node->sizecells;
  1111. if(a >= c && a < c + s) { a = a - c + b; break; }
  1112. }
  1113. }
  1114. if(!node->parent || node->parent >= fdt_numnodes || node == &fdt_nodes[node->parent]) break;
  1115. node = &fdt_nodes[node->parent];
  1116. }
  1117. }
  1118. return a;
  1119. }
  1120. /**
  1121. * Get a phandle (return node index for phandle in property data)
  1122. */
  1123. static uint32_t fdt_phandle(uint32_t *ptr)
  1124. {
  1125. uint32_t i;
  1126. if(ptr && *ptr)
  1127. for(i = 0; i < fdt_numnodes; i++)
  1128. if(*ptr == fdt_nodes[i].phandle)
  1129. return i;
  1130. return 0;
  1131. }
  1132. /**
  1133. * The real deal, convert an FDT node properties into a GUDT node
  1134. */
  1135. static void fdt_prop(char *name, uint8_t *value, uint32_t size, fdt_t *node)
  1136. {
  1137. uint64_t a, s;
  1138. uint32_t as, ss, is, i, j, n = size >> 2, *p = (uint32_t*)value;
  1139. if(value && size) {
  1140. as = fdt_nodes[node->parent].addrcells; ss = fdt_nodes[node->parent].sizecells; is = fdt_nodes[node->intparent].intcells;
  1141. if(!memcmp(name, "reg", 4) && as) {
  1142. for(i = 0; i < n;) {
  1143. a = fdt_addr(&p[i], as, 0, node); i += as;
  1144. s = fdt_value(&p[i], ss); i += ss;
  1145. switch(node->type) {
  1146. case 1: HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_CPU, node->cpurel, a); break;
  1147. case 2: break;
  1148. case 3: HWDET_RESVMEM(a, s); break;
  1149. default: HWDET_RESVMEM(a, s); HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_MMIO, a, s); break;
  1150. }
  1151. }
  1152. } else
  1153. if(!memcmp(name, "dmas", 5) && as) {
  1154. for(i = 0; i < n;) {
  1155. a = fdt_addr(&p[i], as, 1, node); i += as;
  1156. s = fdt_value(&p[i], ss); i += ss;
  1157. HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_DMA, a, s);
  1158. }
  1159. } else
  1160. if(!memcmp(name, "interrupts-extended", 20)) {
  1161. for(i = 0; i < n;) {
  1162. j = fdt_phandle(&p[i]); i++;
  1163. if(!fdt_nodes[j].intcells) break;
  1164. if(fdt_nodes[j].intcells > 2) i += fdt_nodes[j].intcells - 2;
  1165. a = fdt_value(&p[i], 1); i++;
  1166. if(fdt_nodes[j].intcells > 1) { s = fdt_value(&p[i], 1); i++; } else s = 0;
  1167. HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_IRQ, a, s);
  1168. }
  1169. } else
  1170. if(!memcmp(name, "interrupts", 11) && is) {
  1171. for(i = 0; i < n;) {
  1172. if(is > 2) i += is - 2;
  1173. a = fdt_value(&p[i], 1); i++;
  1174. if(is > 1) { s = fdt_value(&p[i], 1); i++; } else s = 0;
  1175. HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_IRQ, a, s);
  1176. }
  1177. }
  1178. #if AML_DEBUG
  1179. else printf("unhandled property \"%s\" \"%s\" \"%s\"\r\n", node->drv, node->name, name);
  1180. #endif
  1181. }
  1182. }
  1183. /**
  1184. * FDT bájtkód értelmezése
  1185. */
  1186. static void fdt_dtb(uint8_t *ptr)
  1187. {
  1188. fdt_t *node;
  1189. uint32_t parent[AML_MAXLEVEL];
  1190. uint32_t totalsize = ptr[7] | (ptr[6] << 8) | (ptr[5] << 16);
  1191. uint32_t off_dt = ptr[11] | (ptr[10] << 8) | (ptr[9] << 16);
  1192. uint32_t off_str = ptr[15] | (ptr[14] << 8) | (ptr[13] << 16);
  1193. uint32_t off_rsvmap = ptr[19] | (ptr[18] << 8) | (ptr[17] << 16);
  1194. uint32_t version = ptr[23] | (ptr[22] << 8) | (ptr[21] << 16);
  1195. uint32_t siz_str = ptr[35] | (ptr[34] << 8) | (ptr[33] << 16);
  1196. uint32_t siz_dt = ptr[39] | (ptr[38] << 8) | (ptr[37] << 16);
  1197. uint32_t siz_rsvmap = (off_dt < off_str ? off_dt : off_str) - off_rsvmap;
  1198. uint8_t *p = ptr + off_dt, *t, *s, *end = ptr + off_dt + siz_dt;
  1199. uint32_t i, tag, sz, idx, d = 0;
  1200. #if AML_DEBUG+0 > 1
  1201. uint32_t j, k, l;
  1202. #endif
  1203. uint64_t addr, size;
  1204. if(version < 17) {
  1205. #ifdef AML_DEBUG
  1206. printf("FDT version %d not supported\n", version);
  1207. #endif
  1208. return;
  1209. }
  1210. for(i = 0; i < siz_rsvmap; i += 16) {
  1211. p = ptr + off_rsvmap + i;
  1212. addr = p[7] | (p[6] << 8) | (p[5] << 16) | (p[4] << 24) | ((uint64_t)p[3] << 32) | ((uint64_t)p[2] << 40);
  1213. p += 8;
  1214. size = p[7] | (p[6] << 8) | (p[5] << 16) | (p[4] << 24) | ((uint64_t)p[3] << 32) | ((uint64_t)p[2] << 40);
  1215. if(addr == 0 && size == 0) break;
  1216. HWDET_RESVMEM(addr, size);
  1217. }
  1218. if(end > ptr + totalsize) end = ptr + totalsize;
  1219. /* first, count nodes */
  1220. for(fdt_numnodes = 0, p = ptr + off_dt; p < end; ) {
  1221. tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
  1222. if(tag == 9) break;
  1223. switch(tag) {
  1224. case 1: fdt_numnodes++; for(; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3); break;
  1225. case 3: sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 8; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3); break;
  1226. }
  1227. }
  1228. if(!fdt_numnodes) return;
  1229. fdt_nodes = (fdt_t*)__builtin_alloca((fdt_numnodes + 1) * sizeof(fdt_t));
  1230. memset(fdt_nodes, 0, (fdt_numnodes + 1) * sizeof(fdt_t));
  1231. memset(parent, 0, sizeof(parent));
  1232. /* second run, collect phandle references in advance */
  1233. for(idx = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
  1234. tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
  1235. if(tag == 9) break;
  1236. switch(tag) {
  1237. case 1: for(node++, idx++; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3); break;
  1238. case 3:
  1239. sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1240. i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1241. t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
  1242. s = ptr + off_str + i;
  1243. if(i < siz_str - 1) {
  1244. if(!memcmp(s, "#interrupt-cells", 17)) { node->intcells = t[sz - 1]; } else
  1245. if(!memcmp(s, "interrupt-parent", 17)) { memcpy(&node->phparent, t, 4); } else
  1246. if(!memcmp(s, "phandle", 8) || !memcmp(s, "linux,phandle", 14)) { memcpy(&node->phandle, t, 4); }
  1247. }
  1248. break;
  1249. }
  1250. }
  1251. /* third run, actually flatten the so called "flattened" device tree, parse all properties */
  1252. for(idx = d = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
  1253. tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
  1254. if(tag == 9) break;
  1255. switch(tag) {
  1256. case 1:
  1257. node++;
  1258. if(d) parent[d] = parent[d - 1];
  1259. node->addrcells = 2; node->sizecells = 1;
  1260. node->parent = parent[d];
  1261. if(node->phparent) node->intparent = fdt_phandle(&node->phparent);
  1262. else node->intparent = fdt_nodes[node->parent].intparent;
  1263. if(!node->intparent) node->intparent = node->parent;
  1264. for(node->name = (char*)p; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3);
  1265. if(!memcmp(node->name, "cpu@", 4)) node->type = 1;
  1266. if(!memcmp(node->name, "memory@", 7)) node->type = 2;
  1267. if(!memcmp(node->name, "nvram@", 6)) node->type = 3;
  1268. parent[d++] = ++idx;
  1269. break;
  1270. case 2: d--; break;
  1271. case 3:
  1272. sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1273. i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1274. t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
  1275. s = ptr + off_str + i;
  1276. if(i < siz_str - 1) {
  1277. if(!memcmp(s, "#address-cells", 15)) { node->addrcells = t[sz - 1]; } else
  1278. if(!memcmp(s, "#size-cells", 12)) { node->sizecells = t[sz - 1]; } else
  1279. if(!memcmp(s, "#dma-cells", 11)) { node->dmacells = t[sz - 1]; } else
  1280. if(!memcmp(s, "#clock-cells", 13)) { node->clkcells = t[sz - 1]; } else
  1281. if(!memcmp(s, "#gpio-cells", 12)) { node->gpiocells = t[sz - 1]; } else
  1282. if((!memcmp(s, "model", 6) || !memcmp(s, "name", 5)) && !*node->name) { node->name = (char*)t; } else
  1283. if(!memcmp(s, "device_type", 12)) {
  1284. if(!memcmp(t, "cpu", 4)) node->type = 1;
  1285. if(!memcmp(t, "memory", 7)) node->type = 2;
  1286. if(!memcmp(t, "nvram", 6)) node->type = 3;
  1287. } else
  1288. if(!memcmp(s, "cpu-release", 11)) { node->type = 1; node->cpurel = fdt_value((uint32_t*)t, 2); } else
  1289. if(!memcmp(s, "ranges", 7)) {
  1290. if(sz) {
  1291. node->map[0] = (uint32_t*)t;
  1292. node->mapsz[0] = sz;
  1293. }
  1294. } else
  1295. if(!memcmp(s, "dma-ranges", 11)) {
  1296. if(sz) {
  1297. node->map[1] = (uint32_t*)t;
  1298. node->mapsz[1] = sz;
  1299. }
  1300. } else
  1301. if(!memcmp(s, "compatible", 11)) {
  1302. for(node->drv = (char*)t; *t && t < p; t++);
  1303. node->alt = !*t && t[1] && t + 2 < p ? (char*)t + 1 : NULL;
  1304. }
  1305. }
  1306. break;
  1307. }
  1308. }
  1309. /* fourth times the charm, do the actual parsing */
  1310. for(idx = d = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
  1311. tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
  1312. if(tag == 9) break;
  1313. switch(tag) {
  1314. case 1:
  1315. node++; idx++;
  1316. for(; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3);
  1317. #if AML_DEBUG+0 > 1
  1318. printf("\r\n");
  1319. for(l = 0; l < d; l++) printf(" ");
  1320. printf("node %u name '%s' drv '%s' alt '%s'\r\n", idx, node->name, node->drv, node->alt);
  1321. for(l = 0; l < d; l++) printf(" ");
  1322. printf(" parent %u intparent %u phandle %x phparent %x\r\n", node->parent, node->intparent,
  1323. node->phandle, node->phparent);
  1324. for(l = 0; l < d; l++) printf(" ");
  1325. printf(" acells %u scells %u icells %u dcells %u ccells %u gcells %u\r\n",
  1326. node->addrcells, node->sizecells, node->intcells, node->dmacells, node->clkcells, node->gpiocells);
  1327. for(j = 0; j < 2; j++)
  1328. if(node->map[j] && node->sizecells) {
  1329. for(l = 0; l < d; l++) printf(" ");
  1330. printf(" map[%u] offs %08x size %3d", j, (uint32_t)((uint8_t*)node->map[j] - ptr), node->mapsz[j]);
  1331. l = node->mapsz[j] >> 2;
  1332. for(k = 0; k < l;) {
  1333. printf(" <%lx", fdt_value(&node->map[j][k], node->addrcells)); k += node->addrcells;
  1334. printf(",%lx", fdt_value(&node->map[j][k], fdt_nodes[node->parent].addrcells)); k += fdt_nodes[node->parent].addrcells;
  1335. printf(",%lx>", fdt_value(&node->map[j][k], node->sizecells)); k += node->sizecells;
  1336. }
  1337. printf("\r\n");
  1338. }
  1339. #endif
  1340. d++;
  1341. break;
  1342. case 2: d--; break;
  1343. case 3:
  1344. sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1345. i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
  1346. t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
  1347. s = ptr + off_str + i;
  1348. if(i < siz_str - 1) {
  1349. #if AML_DEBUG+0 > 1
  1350. for(i = 0; i < d; i++) printf(" ");
  1351. printf(" prop offs %08x size %3d %s", (uint32_t)(t - ptr), sz, (char*)s);
  1352. if(sz) { printf(" <"); for(i = 0; i < sz; i++) { printf("%s%02x", i ? "," : "", t[i]); } printf(">"); }
  1353. printf("\r\n");
  1354. #endif
  1355. /* filter out all properties that we have already parsed */
  1356. if(memcmp(s, "#address-cells", 15) && memcmp(s, "#size-cells", 12) && memcmp(s, "#dma-cells", 11) &&
  1357. memcmp(s, "#clock-cells", 13) && memcmp(s, "#gpio-cells", 12) &&
  1358. memcmp(s, "model", 6) && memcmp(s, "name", 5) && memcmp(s, "device_type", 12) &&
  1359. memcmp(s, "cpu-release", 11) && memcmp(s + 1, "-cache-", 7) && memcmp(s, "chassis-type", 13) &&
  1360. memcmp(s, "ranges", 7) && memcmp(s, "dma-ranges", 11) && memcmp(s, "compatible", 11) &&
  1361. memcmp(s, "#interrupt-cells", 17) && memcmp(s, "interrupt-parent", 17) &&
  1362. memcmp(s, "phandle", 8) && memcmp(s, "linux,phandle", 14) &&
  1363. memcmp(s, "status", 7) && node->name && *node->name && node->drv && *node->drv &&
  1364. memcmp(node->name, "aliases", 8) && memcmp(node->name, "chosen", 7) &&
  1365. memcmp(node->name, "__symbols__", 12) && memcmp(node->name, "__overrides__", 14))
  1366. fdt_prop((char*)s, t, sz, node);
  1367. }
  1368. break;
  1369. }
  1370. }
  1371. #ifdef AML_DEBUG
  1372. stkmax = AML_MAXLEVEL * sizeof(fdt_ctx_t) + 16 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 5 * sizeof(void*) +
  1373. fdt_numnodes * sizeof(fdt_t) + /* functions calls */64;
  1374. #endif
  1375. }
  1376. /* type field */
  1377. enum { GUDT_T_DEVICE, GUDT_T_CPUCORE, GUDT_T_DMA, GUDT_T_IRQ, GUDT_T_INTC, GUDT_T_PINS, GUDT_T_LEDS, GUDT_T_CLOCKS, GUDT_T_SENSORS,
  1378. GUDT_BUTTONS, GUDT_T_AMPER, GUDT_T_VOLT, GUDT_T_THERMAL, GUDT_T_FREQ, GUDT_T_L0CACHE, GUDT_T_L1CACHE, GUDT_T_L2CACHE,
  1379. GUDT_T_L3CACHE, /* unassigned */
  1380. GUDT_T_EDID = 0xd7, GUDT_T_FBPTR, GUDT_T_FBDIM, GUDT_T_MODULE, GUDT_T_CMDLINE, GUDT_T_DEFAULT,
  1381. GUDT_T_NVSMEM, GUDT_T_RESVMEM, GUDT_T_RAM,
  1382. /* top 32 entries must match ACPI region space */
  1383. GUDT_T_MMIO = 0xe0, GUDT_T_IOPORT, GUDT_T_PCI, GUDT_T_EC, GUDT_T_SMB, GUDT_T_NVRAM, GUDT_T_PCIBAR, GUDT_T_IPMI,
  1384. GUDT_T_GPIO, GUDT_T_GSB, GUDT_T_PCC };
  1385. /* category field, must match pci.ids class */
  1386. enum { GUDT_C_UNKNOWN, GUDT_T_STORAGE, GUDT_C_NETWORK, GUDT_C_DISPLAY, GUDT_C_MULTIMEDIA, GUDT_C_MEMORY, GUDT_C_BRIDGE,
  1387. GUDT_C_COMM, GUDT_C_GENERIC, GUDT_C_INPUT, GUDT_C_DOCK, GUDT_C_PROCESSOR, GUDT_C_SERIAL, GUDT_C_WIRELESS, GUDT_C_INTELLIGENT,
  1388. GUDT_C_SATELLITE, GUDT_C_ENCRYPTION, GUDT_C_SIGNAL, GUDT_C_ACCEL, GUDT_C_NONESSENTIAL, GUDT_C_MACHINE = 0xff };
  1389. /* device field but only when category is GUDT_C_MACHINE, must match ACPI PM Profiles */
  1390. enum { GUDT_D_UNSPECIFIED, GUDT_D_DESKTOP, GUDT_D_MOBILE, GUDT_D_WORKSTATION, GUDT_D_ENTERPRISE, GUDT_D_SOHO, GUDT_D_APPLIANCE,
  1391. GUDT_D_PERFORMANCE, GUDT_D_TABLET };
  1392. /* stored in flags */
  1393. #define GUDT_F_UNIT(x) (1<<((x)&15))
  1394. #define GUDT_F_DATA(x) (((x)>>4)&15)
  1395. #define GUDT_F_INDIRECT 0x0f
  1396. /* device node */
  1397. typedef struct {
  1398. uint8_t type; /* must be 0, GUDT_T_DEVICE */
  1399. uint8_t category; /* PCI device class, GUDT_C_x */
  1400. uint16_t parent; /* parent node */
  1401. uint16_t driver; /* string table offset, device driver name */
  1402. uint16_t alternative; /* string table offset, alternative driver name */
  1403. uint16_t name; /* string table offset, device's unique name */
  1404. uint16_t device; /* PCI device sub-class (or GUDT_D_x) */
  1405. uint16_t vendor; /* PCI vendor code */
  1406. uint16_t model; /* PCI device code */
  1407. } __attribute__((packed)) gudt_device_t;
  1408. /* resource node */
  1409. typedef struct {
  1410. uint8_t type; /* must not be 0, any other GUDT_T_x */
  1411. uint8_t flags; /* bit 0..3: resource's unit size */
  1412. uint16_t parent; /* parent node */
  1413. union { /* resource descriptor */
  1414. /* flags bit 4..7: 0 */
  1415. struct { uint32_t size; uint64_t base; } __attribute__((packed)) p;
  1416. /* flags bit 4..7: num items */
  1417. struct { uint8_t data[12]; } __attribute__((packed)) b;
  1418. struct { uint16_t data[6]; } __attribute__((packed)) w;
  1419. struct { uint32_t data[3]; } __attribute__((packed)) d;
  1420. struct { uint32_t pad; uint64_t data[1]; } __attribute__((packed)) q;
  1421. } __attribute__((packed)) r;
  1422. } __attribute__((packed)) gudt_node_t;
  1423. typedef struct { uint32_t b, c, t; uint8_t *s, *d; uint16_t e[16], f[288], g[16], h[288]; } gudt_z_t;
  1424. static void gudt_bt(uint16_t *t, uint16_t *r, const uint8_t *l, uint32_t n) {
  1425. uint32_t i, s, o[16]; for(i = 0; i < 16; i++) { t[i] = 0; } for(i = 0; i < n; i++) t[(uint32_t)l[i]]++;
  1426. for(s = 0, i = 0, t[0] = 0; i < 16; i++) { o[i] = s; s += t[i]; } for(i = 0; i < n; i++) if(l[i]) r[o[(uint32_t)l[i]]++] = i; }
  1427. static int gudt_gb(gudt_z_t *d) { uint32_t b; if(!d->b--) { d->t = *d->s++; d->b = 7; } b = d->t & 1; d->t >>= 1; return b; }
  1428. static uint32_t gudt_rb(gudt_z_t *d, uint32_t n, uint32_t b) {
  1429. uint32_t v = 0, m, l; if(n) { l = 1 << n; for(m = 1; m < l; m <<= 1) if(gudt_gb(d)) v += m; } return v + b; }
  1430. static int gudt_ds(gudt_z_t *d, uint16_t *t, uint16_t *r) {
  1431. int s = 0, c = 0, l = 0; do { c = (c << 1) + gudt_gb(d); s += t[++l]; c -= t[l]; } while(c >= 0); return r[s + c]; }
  1432. int gudt_unpack(const gudt_hdr_t *src, gudt_hdr_t *dst)
  1433. {
  1434. uint32_t i, l, size, siz, x, y, z;
  1435. uint16_t m[30] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}, n[30] = {1,2,3,4,
  1436. 5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
  1437. uint8_t *strs = (uint8_t*)dst, k[288+32], p, c[] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
  1438. int r = 2, s, t = -1, f = 0, o = 0;
  1439. gudt_z_t d = { 0 };
  1440. if(!src || !dst || src->magic[0] != 'G' || src->magic[1] != 'U' || src->magic[2] != 'D') return 0;
  1441. size = (((((uint8_t*)src)[4] | (((uint8_t*)src)[5] << 8)) + 7) & ~7) + ((((uint8_t*)src)[6] | (((uint8_t*)src)[7] << 8)) << 4);
  1442. if(((uint8_t*)src)[8] == 0x78 && ((uint8_t*)src)[9] == 0xDA) {
  1443. for(i = r = 0; i < 8; i++) strs[i] = ((uint8_t*)src)[i];
  1444. d.s = (uint8_t*)src + 10; d.d = strs + 8; siz = size;
  1445. do {
  1446. do {
  1447. if(t == -1) {
  1448. again: f = gudt_gb(&d);
  1449. t = gudt_rb(&d, 2, 0);
  1450. switch(t) {
  1451. case 1:
  1452. for(i = 0; i < 7; i++) d.e[i] = 0;
  1453. d.e[7] = 24; d.e[8] = 152; d.e[9] = 112;
  1454. for(i = 0; i < 24; i++) d.f[i] = 256 + i;
  1455. for(i = 0; i < 144; i++) d.f[24 + i] = i;
  1456. for(i = 0; i < 8; i++) d.f[24 + 144 + i] = 280 + i;
  1457. for(i = 0; i < 112; i++) d.f[24 + 144 + 8 + i] = 144 + i;
  1458. for(i = 0; i < 5; i++) d.g[i] = 0;
  1459. for(i = 0, d.g[5] = 32; i < 32; i++) d.h[i] = i;
  1460. break;
  1461. case 2:
  1462. x = gudt_rb(&d, 5, 257); y = gudt_rb(&d, 5, 1); z = gudt_rb(&d, 4, 4);
  1463. for(i = 0; i < 19; i++) k[i] = 0;
  1464. for(i = 0; i < z; i++) k[c[i]] = gudt_rb(&d, 3, 0);
  1465. gudt_bt(d.e, d.f, k, 19);
  1466. for(i = 0; i < x + y;)
  1467. switch((s = gudt_ds(&d, d.e, d.f))) {
  1468. case 16: for(p = k[i - 1], l = gudt_rb(&d, 2, 3); l; l--) k[i++] = p; break;
  1469. case 17: for(l = gudt_rb(&d, 3, 3); l; l--) k[i++] = 0; break;
  1470. case 18: for(l = gudt_rb(&d, 7, 11); l; l--) k[i++] = 0; break;
  1471. default: k[i++] = s; break;
  1472. }
  1473. gudt_bt(d.e, d.f, k, x); gudt_bt(d.g, d.h, k + x, y);
  1474. break;
  1475. }
  1476. }
  1477. switch(t) {
  1478. case 0:
  1479. if(!d.c) { d.c = 1 + (d.s[0] | (d.s[1] << 8)); d.s += 4; d.b = 0; }
  1480. if(!--d.c) r = 1; else { *d.d++ = *d.s++; r = 0; }
  1481. break;
  1482. case 1: case 2:
  1483. if(!d.c) {
  1484. s = gudt_ds(&d, d.e, d.f);
  1485. if(s < 256) { *d.d++ = s; r = 0; break; } else if(s == 256) { r = 1; break; }
  1486. s -= 257; d.c = gudt_rb(&d, s < 4 ? 0 : ((s - 4) >> 2), m[s]);
  1487. r = gudt_ds(&d, d.g, d.h); o = -gudt_rb(&d, r < 2 ? 0 : ((r - 2) >> 1), n[r]);
  1488. }
  1489. d.d[0] = d.d[o]; d.d++; d.c--; r = 0;
  1490. break;
  1491. default: return 0;
  1492. }
  1493. if(r == 1 && !f) goto again;
  1494. if(r) break;
  1495. } while(--siz);
  1496. } while(!r);
  1497. }
  1498. return r;
  1499. }
  1500. /**
  1501. * GUDT bájtkód értelmezése
  1502. */
  1503. static void gudt(uint8_t *ptr)
  1504. {
  1505. gudt_hdr_t *hdr;
  1506. gudt_device_t *dev;
  1507. gudt_node_t *nodes;
  1508. uint32_t i, j, l, t;
  1509. switch(gudt_unpack((gudt_hdr_t*)ptr, (gudt_hdr_t *)aml.node)) {
  1510. case 0: return;
  1511. case 1: ptr = (uint8_t*)aml.node; break;
  1512. case 2: /* nincs dolgunk */ break;
  1513. }
  1514. hdr = (gudt_hdr_t*)ptr;
  1515. nodes = (gudt_node_t*)((uint8_t*)hdr + ((hdr->hdrsize + 7) & ~7));
  1516. for(i = 0; i < hdr->numnodes; i++)
  1517. if(nodes[i].parent < hdr->numnodes && nodes[nodes[i].parent].type == GUDT_T_DEVICE) {
  1518. if(nodes[i].type >= GUDT_T_NVSMEM && nodes[i].type < GUDT_T_MMIO) {
  1519. HWDET_RESVMEM(nodes[i].r.p.base, nodes[i].r.p.size);
  1520. } else if(nodes[i].type != GUDT_T_RAM && nodes[i].type != GUDT_T_DEVICE) {
  1521. dev = (gudt_device_t*)&nodes[nodes[i].parent];
  1522. switch(nodes[i].type) {
  1523. case GUDT_T_CPUCORE: t = HWDET_CPU; break;
  1524. case GUDT_T_IOPORT: t = HWDET_IO; break;
  1525. case GUDT_T_IRQ: t = HWDET_IRQ; break;
  1526. case GUDT_T_DMA: t = HWDET_DMA; break;
  1527. case GUDT_T_MMIO: t = HWDET_MMIO; HWDET_RESVMEM(nodes[i].r.p.base, nodes[i].r.p.size); break;
  1528. case GUDT_T_PCI: t = HWDET_PCI; break;
  1529. case GUDT_T_EC: t = HWDET_EC; break;
  1530. case GUDT_T_SMB: t = HWDET_SMB; break;
  1531. case GUDT_T_NVRAM: t = HWDET_CMOS; break;
  1532. default: t = HWDET_NONE; break;
  1533. }
  1534. l = GUDT_F_DATA(nodes[i].flags);
  1535. if(l) {
  1536. if(t == HWDET_IRQ && GUDT_F_UNIT(nodes[i].flags) == 1)
  1537. for(j = 0; j < l; j++)
  1538. HWDET_RESOURCE(dev->name ? (char*)ptr + dev->name : "", dev->driver ? (char*)ptr + dev->driver : "",
  1539. dev->alternative ? (char*)ptr + dev->alternative : "", t, nodes[i].r.b.data[j], 0);
  1540. } else
  1541. HWDET_RESOURCE(dev->name ? (char*)ptr + dev->name : "", dev->driver ? (char*)ptr + dev->driver : "",
  1542. dev->alternative ? (char*)ptr + dev->alternative : "", t, nodes[i].r.p.base, nodes[i].r.p.size);
  1543. }
  1544. }
  1545. }
  1546. /**
  1547. * A fő publikus API
  1548. */
  1549. void hwdet(int num, uint8_t **ds)
  1550. {
  1551. uint64_t lapic;
  1552. uint8_t *p, *e;
  1553. int i, n;
  1554. n = aml_numnodes(num, (acpi_t**)ds);
  1555. if(n > 0) {
  1556. aml.node = __builtin_alloca(n * sizeof(aml_t));
  1557. memset(aml.node, 0, n * sizeof(aml_t));
  1558. for(i = 0; i < num; i++)
  1559. if(ds[i]) {
  1560. if((ds[i][0] == 'D' || ds[i][0] == 'S') && !memcmp(ds[i] + 1, "SDT", 3) && ((acpi_t*)ds[i])->size) {
  1561. if(ds[i][36] == 0xD0 && ds[i][37] == 0x0D && ds[i][38] == 0xFE && ds[i][39] == 0xED) fdt_dtb(ds[i] + 36); else
  1562. if(!memcmp(ds[i] + 36, "GUDT", 4)) gudt(ds[i] + 36); else
  1563. aml_TermList((uint8_t*)ds[i] + sizeof(acpi_t), (uint8_t*)ds[i] + ((acpi_t*)ds[i])->size, NULL);
  1564. } else
  1565. if(ds[i][0] == 0xD0 && ds[i][1] == 0x0D && ds[i][2] == 0xFE && ds[i][3] == 0xED) fdt_dtb(ds[i]); else
  1566. if(!memcmp(ds[i] + 36, "APIC", 4)) {
  1567. p = (uint8_t*)ds[i] + sizeof(acpi_t);
  1568. lapic = *((uint32_t*)p);
  1569. for(p += 8, e = (uint8_t*)ds[i] + ((acpi_t*)ds[i])->size; p < e && p[1]; p += p[1])
  1570. switch(*p) {
  1571. case 0: if(p[4]) HWDET_RESOURCE("C000", "CORE", "", HWDET_CPU, 0, p[3]); break;
  1572. case 1:
  1573. HWDET_RESVMEM(*((uint32_t*)(p + 4)), 256);
  1574. HWDET_RESOURCE("IOAPIC", "PNP0C08", "", HWDET_MMIO, *((uint32_t*)(p + 4)), 256);
  1575. HWDET_RESOURCE("IOAPIC", "PNP0C08", "", HWDET_IRQ, *((uint32_t*)(p + 8)), 0);
  1576. break;
  1577. case 5: lapic = *((uint64_t*)(p + 4)); break;
  1578. case 9: if(p[8]) HWDET_RESOURCE("C000", "CORE", "", HWDET_CPU, 0, *((uint32_t*)(p + 12))); break;
  1579. break;
  1580. }
  1581. if(lapic) { HWDET_RESVMEM(lapic, 1024); HWDET_RESOURCE("C000", "PNP0003", "", HWDET_MMIO, lapic, 1024); }
  1582. } else
  1583. if(!memcmp(ds[i] + 36, "GUDT", 4)) gudt(ds[i]);
  1584. #ifdef AML_DEBUG
  1585. else printf("unknown table format, pointer #%d\n", i + 1);
  1586. #endif
  1587. }
  1588. }
  1589. #ifdef AML_DEBUG
  1590. printf("numchk %d/max %d, stackmax %d.\n", numchk, aml.max, stkmax);
  1591. #endif
  1592. }