12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658 |
- /*
- * hwdet.h
- *
- * Copyright (C) 2023 bzt, GPLv3+
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * @brief Hardware Resource Detection single header library
- */
- enum { HWDET_NONE, HWDET_CPU, HWDET_IO, HWDET_IRQ, HWDET_DMA, HWDET_MMIO, HWDET_PCI, HWDET_EC, HWDET_SMB, HWDET_CMOS };
- /**
- * Public API, single function: pass a list of ACPI DSDT/SSDT tables, FDT (dtb) or GUDT blobs and it will call the two hooks
- */
- void HWDET_RESVMEM(uint64_t base, uint64_t size);
- void HWDET_RESOURCE(char *name, char *driver, char *altdriver, int type, uint64_t arg1, uint64_t arg2);
- void hwdet(int num, uint8_t **ds);
- /* Implementation */
- #ifndef AML_MAXLEVEL
- #define AML_MAXLEVEL 32
- #endif
- #ifndef AML_MAXSTR
- #define AML_MAXSTR 32
- #endif
- /*#define AML_MINNODES 768*/
- typedef struct {
- uint8_t magic[4];
- uint32_t size;
- uint8_t rev;
- uint8_t chksum;
- char OEM[6];
- char OEMtableid[8];
- uint32_t OEMrev;
- uint32_t creatid;
- uint32_t creatrev;
- } __attribute__((packed)) acpi_t;
- typedef struct {
- uint32_t type;
- uint32_t parent;
- uint8_t *name;
- union {
- uint8_t b[16];
- uint16_t w[8];
- uint32_t d[4];
- uint64_t q[2];
- uint8_t *p[2];
- } data;
- } aml_t;
- static struct {
- aml_t *node;
- uint64_t stack[AML_MAXLEVEL*16];
- uint32_t len, num, max, par, sp;
- uint32_t mtdidx, devidx, drvidx, altidx, regidx;
- uint8_t *memmin, *memmax;
- } aml;
- #define NODE aml.node[aml.num]
- typedef struct {
- uint8_t magic[4]; /* magic GUDT */
- uint16_t hdrsize; /* 8 + string table's size */
- uint16_t numnodes; /* number of nodes */
- } __attribute__((packed)) gudt_hdr_t;
- static uint8_t *aml_NameString(uint8_t *ptr);
- static uint8_t *aml_TermList(uint8_t *ptr, uint8_t *end, aml_t *node);
- #ifdef AML_DEBUG
- static uint32_t numchk, stkchk, stkmax;
- #define AML_STKENTER(s) do{ stkchk += s; if(stkchk > stkmax) stkmax = stkchk; }while(0)
- #define AML_STKLEAVE(s) stkchk -= s
- /**
- * AML node-ok listázása
- */
- void aml_dump(aml_t *node)
- {
- uint32_t i, j, n;
- if(node) n = 1; else { node = &aml.node[0]; n = aml.num; }
- for(i = 0; i < n; i++, node++) {
- printf("%4d parent %4d type %04x name '%c%c%c%c' data.q ", i, node->parent,node->type,
- node->name && node->name[0] > 32 && node->name[0] < 127 ? node->name[0] : '.',
- node->name && node->name[1] > 32 && node->name[1] < 127 ? node->name[1] : '.',
- node->name && node->name[2] > 32 && node->name[2] < 127 ? node->name[2] : '.',
- node->name && node->name[3] > 32 && node->name[3] < 127 ? node->name[3] : '.');
- for(j = 0; j < 2; j++) printf(" %lx", node->data.q[j]);
- printf(" data.d ");
- for(j = 0; j < 4; j++) printf(" %x", node->data.d[j]);
- printf("\n");
- }
- }
- #else
- #define AML_STKENTER(s)
- #define AML_STKLEAVE(s)
- #endif
- /**
- * AML node kikeresése
- */
- static uint32_t aml_lookup(uint8_t *name)
- {
- uint32_t parent = aml.par, i, n, c, a = 2;
- uint8_t *s;
- #ifdef AML_DEBUG
- if(stkchk + 32 > stkmax) stkmax = stkchk + 32;
- #endif
- if(name < aml.memmin || name >= aml.memmax) return 0;
- if(*name == '\\') { name++; parent = 0; }
- while(*name == '^' && parent) { name++; parent = aml.node[parent].parent; }
- switch(*name) {
- case 0x00: return 0;
- case 0x2E: name++; c = 2; break;
- case 0x2F: name++; c = *name++; break;
- default: c = 1; break;
- }
- /* gyors ellenőrzés, hogy a szülőre hivatkozik-e */
- i = aml.num - 1;
- if(c == 1 && (aml.node[i].parent == parent || aml.node[i].parent == aml.node[parent].parent) &&
- !memcmp(aml.node[i].name, name, 4)) return i;
- do {
- s = name; n = c;
- again: /* végigjárjuk a teljes path-ot */
- for(i = 1; i < aml.num; i++) {
- if(aml.node[i].parent == parent && !memcmp(aml.node[i].name, s, 4)) {
- n--; s += 4; parent = i;
- if(!n) return i; else goto again;
- }
- }
- /* bugos firmverek miatt csinálunk több ellenőrzést is, a szülőtől és a gyökértől is kiindulva */
- parent = a == 2 ? aml.node[aml.par].parent : 0;
- } while(a--);
- if(c == 1)
- for(i = aml.num - 1; i > 0; i--)
- if(!memcmp(aml.node[i].name, name, 4)) return i;
- #ifdef AML_DEBUG
- printf("node not found, parent %d '", aml.par);
- for(n = 0; n < c; n++)
- for(i = 0; i < 4; i++) {
- if(n) printf(".");
- if(name[i] > 32 && name[i] < 127) printf("%c", name[i]); else printf("\\x%02X", name[i]);
- }
- printf("'\n");
- #endif
- return 0;
- }
- /**
- * AML opkód beolvasása
- */
- static uint8_t *aml_opcode(uint8_t *ptr, uint16_t *op)
- {
- #ifdef AML_DEBUG
- if(stkchk + 16 > stkmax) stkmax = stkchk + 16;
- #endif
- if(ptr < aml.memmin || ptr >= aml.memmax) { *op = 0xffff; return ptr; }
- if(*ptr == '\\' || *ptr == '^' || *ptr == '/' || *ptr == '_' || *ptr == '.' || (*ptr >= 'A' && *ptr <= 'Z')) {
- *op = 9; ptr = aml_NameString(ptr);
- } else
- if(*ptr == 0x5B || (*ptr == 0x92 && ptr[1] >= 0x93 && ptr[1] <= 0x95)) { *op = *ptr++ << 8; *op |= *ptr++; }
- else *op = *ptr++;
- return ptr;
- }
- /**
- * AML packet értelmezése
- */
- static uint8_t *aml_pkg(uint8_t *ptr)
- {
- uint8_t imm = (*ptr & 0xC0) >> 6, i;
- aml.len = imm ? (*ptr++ & 0x0F) : (*ptr++ & 0x3F);
- for(i = 0; i < imm; i++) aml.len |= *ptr++ << (4 + (i << 3));
- return ptr;
- }
- /**
- * Meghatározza, maximum mennyi node-ra van szükség
- */
- static int aml_numnodes(int siz, acpi_t **tbl)
- {
- gudt_hdr_t *hdr;
- int i, n = 0, cur, l = 0, nodes[AML_MAXLEVEL] = { 0 }, skip = 0, skipbytes = 0, skip2 = 0, skip2bytes = 0;
- uint8_t *st, *ptr, *end, *scope[AML_MAXLEVEL] = { 0 };
- uint16_t op;
- /* egy a root node-nak, meg a biztonság kedvéért kis rátartással számolunk a dinamikus metódushívásoknak */
- cur = 1;
- memset(&aml, 0, sizeof(aml)); aml.memmin = (uint8_t*)-1UL;
- for(i = 0; i < siz && tbl; i++) {
- if(!tbl[i] || !tbl[i]->size) continue;
- if(tbl[i]->magic[0] == 0xD0 && tbl[i]->magic[1] == 0x0D) { n++; continue; }
- if(tbl[i]->magic[0] == 'G' && tbl[i]->magic[1] == 'U') {
- hdr = (gudt_hdr_t*)tbl[i];
- n += (((hdr->hdrsize + 7) & ~7) + hdr->numnodes * 16 + sizeof(aml_t) - 1) / sizeof(aml_t);
- continue;
- }
- ptr = (uint8_t*)tbl[i] + sizeof(acpi_t); end = ptr + tbl[i]->size;
- if(ptr[0] == 0xD0 && ptr[1] == 0x0D) { n++; continue; }
- if(aml.memmin > ptr) aml.memmin = ptr;
- if(aml.memmax < end) aml.memmax = end;
- while(ptr < end) {
- if(cur > n) n = cur;
- while(l > 0 && ptr >= scope[l - 1]) cur = nodes[--l];
- if(skip) { skip--; if(!skip) { ptr += skipbytes; skipbytes = 0; } }
- if(skip2) { skip2--; if(!skip2) { ptr += skip2bytes; skip2bytes = 0; } }
- st = ptr; ptr = aml_opcode(ptr, &op);
- switch(op) {
- case 0x0006: case 0x0008: ptr = aml_NameString(ptr); cur++; break;
- case 0x0009: break;
- case 0x000A: ptr++; break;
- case 0x000B: ptr += 2; break;
- case 0x000C: ptr += 4; break;
- case 0x000E: ptr += 8; break;
- case 0x000D: for(; ptr < end && ptr[-1]; ptr++); break;
- case 0x0011: case 0x0012: case 0x0013: case 0x5B83:
- ptr = aml_pkg(ptr); ptr = st + (op > 0xff ? 2 : 1) + aml.len; break;
- case 0x5B87: case 0x5B88:
- ptr = aml_pkg(ptr); ptr = st + (op > 0xff ? 2 : 1) + aml.len; cur++; break;
- case 0x0010: case 0x5B82:
- ptr = aml_pkg(ptr); cur++; if(l < AML_MAXLEVEL) { scope[l] = st + 1 + aml.len; nodes[l++] = cur; }
- break;
- case 0x0014:
- ptr = aml_pkg(ptr); cur++; st += 1 + aml.len;
- if(l < AML_MAXLEVEL && (!memcmp(ptr, "_HID", 4) || !memcmp(ptr, "_CID", 4) || !memcmp(ptr, "_CRS", 4))) {
- scope[l] = st; nodes[l++] = cur;
- } else ptr = st;
- break;
- case 0x0015: ptr = aml_NameString(ptr) + 2; break;
- case 0x00A0: case 0x00A1: case 0x00A2: ptr = aml_pkg(ptr); break;
- case 0x5B01: ptr = aml_NameString(ptr) + 1; break;
- case 0x5B02: ptr = aml_NameString(ptr); break;
- case 0x5B23: skip = 1; skipbytes = 2; break;
- case 0x5B80: ptr = aml_NameString(ptr) + 1; cur++; break;
- case 0x5B81: case 0x5B86: ptr = aml_pkg(ptr); st += 2 + aml.len;
- ptr = aml_NameString(ptr);
- if(op == 0x5B86) ptr = aml_NameString(ptr);
- ptr++;
- /* ptr - st FieldList */
- while(ptr < st) {
- switch(*ptr) {
- case 0: ptr++; ptr = aml_pkg(ptr); break;
- case 1: ptr += 3; break;
- case 2: ptr = aml_NameString(ptr + 1); break;
- case 3: ptr += 3 + ptr[2]; break;
- default: ptr += 4; ptr = aml_pkg(ptr); cur++; break;
- }
- }
- ptr = st; cur++;
- break;
- case 0x0089: skip = 1; skipbytes = 1; skip2 = 2; skip2bytes = 1; break;
- case 0x008A: case 0x008B: case 0x008C: case 0x008D: case 0x008F: case 0x5B13: cur++; break;
- default: break;
- }
- }
- }
- n += AML_MAXLEVEL*4;
- #ifdef AML_MINNODES
- if(n < AML_MINNODES) n = AML_MINNODES;
- #endif
- /* globális változók alaphelyzetbe állítása (érdemes globálist használni, mivel az aml_TermList rekurzív) */
- aml.num = 1; aml.max = n; aml.sp = AML_MAXLEVEL*16;
- aml.mtdidx = aml.devidx = aml.drvidx = aml.regidx = -1U;
- #ifdef AML_DEBUG
- numchk = 0; stkchk = stkmax = n * sizeof(aml_t) + 16;
- #endif
- return n;
- }
- /**
- * Path "fájlnév" részét adja vissza
- */
- static void aml_fn(aml_t *node)
- {
- int c;
- #ifdef AML_DEBUG
- if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
- #endif
- if(node->name[0] == '\\') { node->name++; node->parent = 0; }
- while(node->name[0] == '^' && node->parent) { node->name++; node->parent = aml.node[node->parent].parent; }
- if(node->name[0] == 0x2E) node->name += 4; else
- if(node->name[0] == 0x2F) { node->name++; c = (node->name[0] - 1) << 2; node->name += 1 + c; }
- }
- /**
- * AML node értékének betöltése
- */
- static void aml_get(aml_t *val, aml_t *in)
- {
- uint32_t idx;
- #ifdef AML_DEBUG
- if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
- #endif
- /* ha a forrás LocalX vagy ArgX */
- if(in->type >= 0x0060 && in->type <= 0x006F) {
- idx = aml.sp + in->type - 0x60;
- val->data.q[0] = idx < AML_MAXLEVEL*16 ? aml.stack[idx] : 0;
- val->type = 0x000E;
- } else
- /* ha a forrás egy FieldOp */
- if(in->type == 0x5B13) {
- val->data.q[0] = 0;
- val->type = 0x000E;
- if(in->data.p[0] >= aml.memmin && in->data.p[0] < aml.memmax) {
- if(!(in->data.d[2] & 7) && !(in->data.d[3] & 7))
- /* bájthatárra esik, és a mérete is bájttöbbszörös */
- memcpy(&val->data, (void*)(in->data.q[0] + (in->data.d[2] >> 3)),
- (in->data.d[3] >= 64 ? 64 : in->data.d[3]) >> 3);
- else {
- /* nem, tehát shiftelünk és maszkolunk */
- val->data.q[0] = *((uint64_t*)(in->data.q[0] + (in->data.d[2] >> 3))) >> (in->data.d[2] & 7);
- }
- }
- } else
- /* a forrás egy buffer vagy packet */
- if(in->type == 0x0011 || in->type == 0x0012 || in->type == 0x0013) {
- val->data.q[0] = 0;
- val->type = 0x000E;
- if(in->data.p[0] >= aml.memmin && in->data.p[0] < aml.memmax)
- memcpy(&val->data, in->data.p[0], in->data.d[2] >= 8 ? 8 : in->data.d[2]);
- } else
- if(val != in) memcpy(val, in, sizeof(aml_t));
- }
- /**
- * AML node értékének beállítása
- */
- static void aml_set(aml_t *out, aml_t *val)
- {
- uint64_t num;
- #ifdef AML_DEBUG
- if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
- #endif
- /* ha a cél a NULL */
- if(out->type == 0x000D && !out->data.p[0]) return;
- /* ha a cél LocalX vagy ArgX */
- if(out->type >= 0x0060 && out->type <= 0x006F) {
- num = aml.sp + out->type - 0x60;
- if(num < AML_MAXLEVEL*16) aml.stack[num] = val->data.q[0];
- out->data.q[0] = val->data.q[0];
- } else
- /* ha a cél egy FieldOp */
- if(out->type == 0x5B13) {
- if(out->data.p[0] >= aml.memmin && out->data.p[0] < aml.memmax) {
- if(!(out->data.d[2] & 7) && !(out->data.d[3] & 7))
- /* bájthatárra esik, és a mérete is bájttöbbszörös */
- memcpy((void*)(out->data.q[0] + (out->data.d[2] >> 3)), &val->data, out->data.d[3] >> 3);
- else {
- /* nem, tehát shiftelünk és maszkolunk */
- num = *((uint64_t*)(out->data.q[0] + (out->data.d[2] >> 3)));
- num &= ~(~(-1UL << (out->data.d[3])) << (out->data.d[2] & 7));
- num |= (val->data.q[0] & ~(-1UL << (out->data.d[3]))) << (out->data.d[2] & 7);
- *((uint64_t*)(out->data.q[0] + (out->data.d[2] >> 3))) = num;
- }
- }
- } else
- /* ha a cél egy buffer vagy packet */
- if(out->type == 0x0011 || out->type == 0x0012 || out->type == 0x0013) {
- if(out->data.p[0] >= aml.memmin && out->data.p[0] < aml.memmax)
- memcpy(out->data.p[0], &val->data, out->data.d[2] >= 8 ? 8 : out->data.d[2]);
- } else
- /* ha cél és forrás típusa megegyezik, vagy mindkettő integer */
- if(out->type == val->type || (out->type ==0x000E && val->type >= 0x60 && val->type <= 0x006F))
- memcpy(&out->data, &val->data, sizeof(out->data));
- #ifdef AML_DEBUG
- /* a feloldatlan referenciákat csendben kihagyjuk. Nem szabadna megtörténnie, de például a saját gépem DSDT-je is
- * bugos, olyan field-re hivatkozik, ami nem mindig van definiálva... */
- else if(out->type != 0x0009) { printf("Bad lvalue\n"); aml_dump(out); exit(1); }
- #endif
- }
- /**
- * Átkonvertálja az AML kódot olvasható sztringgé
- */
- static void aml_drvname(uint32_t idx, char *str)
- {
- int i;
- if(idx < 1 || idx >= aml.num) return;
- if(aml.node[idx].type == 0x000C) {
- /* Eisa Id */
- str[0] = '@' + ((aml.node[idx].data.d[0] >> 2) & 0x1F);
- str[1] = '@' + ((aml.node[idx].data.d[0] << 3) & 0x18) + ((aml.node[idx].data.d[0] >> 13) & 0x7);
- str[2] = '@' + ((aml.node[idx].data.d[0] >> 8) & 0x1F);
- i = (aml.node[idx].data.d[0] >> 20) & 0xF; str[3] = i < 10 ? '0' + i : 'A' + i - 10;
- i = (aml.node[idx].data.d[0] >> 16) & 0xF; str[4] = i < 10 ? '0' + i : 'A' + i - 10;
- i = (aml.node[idx].data.d[0] >> 28) & 0xF; str[5] = i < 10 ? '0' + i : 'A' + i - 10;
- i = (aml.node[idx].data.d[0] >> 24) & 0xF; str[6] = i < 10 ? '0' + i : 'A' + i - 10;
- } else
- if(aml.node[idx].type == 0x000D && aml.node[idx].data.p[0] >= aml.memmin &&
- aml.node[idx].data.p[0] < aml.memmax) {
- for(i = 0; i < 30 && aml.node[idx].data.p[0][i]; i++)
- str[i] = (char)aml.node[idx].data.p[0][i];
- }
- }
- /**
- * Akkor hívódik, ha egy erőforrást talált
- */
- static void aml_ResourceTemplate(void)
- {
- uint8_t *ptr, *end, t;
- uint16_t s, n;
- uint64_t rs, re, ra, rt, rl;
- char name[8], drv[AML_MAXSTR], alt[AML_MAXSTR];
- int i;
- memset(name, 0, sizeof(name)); memset(drv, 0, sizeof(drv)); memset(alt, 0, sizeof(alt));
- if(aml.node[aml.devidx].name >= aml.memmin && aml.node[aml.devidx].name < aml.memmax)
- memcpy(name, aml.node[aml.devidx].name, 4);
- aml_drvname(aml.drvidx, drv); aml_drvname(aml.altidx, alt);
- if(!memcmp(drv, alt, sizeof(alt))) memset(alt, 0, sizeof(alt));
- #ifdef AML_DEBUG
- printf("-----------------add resource dev %d '%s' drv %d(%d) '%s'('%s') reg %d-------------\n",
- aml.devidx, name, aml.drvidx, aml.altidx, drv, alt, aml.regidx);
- aml_dump(&aml.node[aml.devidx]);
- aml_dump(&aml.node[aml.drvidx]);
- if(aml.altidx != -1U) aml_dump(&aml.node[aml.altidx]);
- aml_dump(&aml.node[aml.regidx]);
- printf("--------------------------------------------------------------\r\n");
- #endif
- if(drv[0]) {
- ptr = aml.node[aml.regidx].data.p[0]; end = aml.node[aml.regidx].data.p[0] + aml.node[aml.regidx].data.d[2];
- if(aml.node[aml.regidx].type == 0x0011 && ptr >= aml.memmin && end < aml.memmax) {
- /* ResourceTemplate, lásd ACPI Specification, 6.4 Resource Data Types for ACPI fejezet */
- while(ptr < end) {
- if(*ptr & 0x80) { t = *ptr; s = (ptr[2] << 8) | ptr[1]; ptr += 3; }
- else { t = *ptr >> 3; s = *ptr & 7; ptr++; }
- #if AML_DEBUG+0 > 1
- printf("t %02x s %d ", t, s); for(i = 0; i < (int)s; i++) { printf(" %02x", ptr[i]); } printf("\n");
- #endif
- switch(t) {
- case 0x04: /* IRQ Format Descriptor */
- for(n = ptr[0] | (ptr[1] << 8), i = 0; i < 16; i++)
- if(n & (1 << i)) HWDET_RESOURCE(name, drv, alt, HWDET_IRQ, i, 0);
- break;
- case 0x05: /* DMA Format Descriptor */
- for(n = ptr[0], i = 0; i < 8; i++)
- if(n & (1 << i)) HWDET_RESOURCE(name, drv, alt, HWDET_DMA, i, 1);
- break;
- case 0x08: /* I/O Port Descriptor */
- for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8), re = (uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8);
- rs <= re; rs += ptr[5] ? ptr[5] : 1)
- if(rs) HWDET_RESOURCE(name, drv, alt, HWDET_IO, rs, ptr[6] ? ptr[6] : (ptr[5] ? ptr[5] : 1));
- break;
- case 0x09: /* Fixed Location I/O Port Descriptor */
- ra = ptr[0] | (ptr[1] << 8); if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, ra, ptr[2] ? ptr[2] : 1);
- break;
- case 0x0A: /* Fixed DMA Descriptor */
- HWDET_RESOURCE(name, drv, alt, HWDET_DMA, ptr[0] | (ptr[1] << 8), 1 << ptr[4]);
- break;
- case 0x81: /* 24-Bit Memory Range Descriptor */
- for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8), re = (uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8),
- ra = ((uint64_t)ptr[5] << 16) | ((uint64_t)ptr[6] << 24); rs <= re; rs += ra) {
- if(rs) {
- HWDET_RESVMEM(rs, ((uint64_t)ptr[7] << 8) | ((uint64_t)ptr[8] << 16));
- HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, ((uint64_t)ptr[7] << 8) | ((uint64_t)ptr[8] << 16));
- }
- if(!ra) ra = 65536;
- }
- break;
- case 0x82: /* Generic Register Descriptor */
- memcpy(&ra, ptr + 4, 8); rs = ptr[5] ? 1 << (ptr[5]-1) : 1;
- switch(ptr[0]) {
- case 0: if(ra) HWDET_RESVMEM(ra, rs); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, ra, rs); break;
- case 1: if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, ra, rs); break;
- default: HWDET_RESOURCE(name, drv, alt, ptr[0] - 2 + HWDET_PCI, ra, rs); break;
- }
- break;
- case 0x85: /* 32-Bit Memory Range Descriptor */
- for(rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8) | ((uint64_t)ptr[3] << 16) | ((uint64_t)ptr[4] << 24),
- re = (uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8) | ((uint64_t)ptr[7] << 16) | ((uint64_t)ptr[8] << 24),
- ra = (uint64_t)ptr[9] | ((uint64_t)ptr[10] << 8) | ((uint64_t)ptr[11] << 16) | ((uint64_t)ptr[12] << 24);
- rs <= re; rs += ra) {
- if(rs) {
- HWDET_RESVMEM(rs, ptr[13] | (ptr[14] << 8) | (ptr[15] << 16) | (ptr[16] << 24));
- HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, ptr[13] | (ptr[14] << 8) | (ptr[15] << 16) | (ptr[16] << 24));
- }
- if(!ra) ra = 65536;
- }
- break;
- case 0x86: /* 32-Bit Fixed Memory Range Descriptor */
- rs = (uint64_t)ptr[1] | ((uint64_t)ptr[2] << 8) | ((uint64_t)ptr[3] << 16) | ((uint64_t)ptr[4] << 24);
- re = (uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8) | ((uint64_t)ptr[7] << 16) | ((uint64_t)ptr[8] << 24);
- if(rs) { HWDET_RESVMEM(rs, re); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs, re); }
- break;
- case 0x87: /* Address Space Resource Descriptors */
- ra = ((uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8) | ((uint64_t)ptr[5] << 16) | ((uint64_t)ptr[6] << 24)) + 1;
- rs = ((uint64_t)ptr[7] | ((uint64_t)ptr[8] << 8) | ((uint64_t)ptr[9] << 16) | ((uint64_t)ptr[10] << 24));
- re = ((uint64_t)ptr[11] | ((uint64_t)ptr[12] << 8) | ((uint64_t)ptr[13] << 16) | ((uint64_t)ptr[14] << 24));
- rt = ((uint64_t)ptr[15] | ((uint64_t)ptr[16] << 8) | ((uint64_t)ptr[17] << 16) | ((uint64_t)ptr[18] << 24));
- rl = ((uint64_t)ptr[19] | ((uint64_t)ptr[20] << 8) | ((uint64_t)ptr[21] << 16) | ((uint64_t)ptr[22] << 24));
- asd: if(ptr[1] & 2) rt = -rt;
- if(ra < rl) ra = rl;
- if(!ra) ra = !ptr[0] ? 65536 : 1;
- for(; rs <= re; rs += ra) {
- if(rs)
- switch(ptr[0]) {
- case 0: HWDET_RESVMEM(rs + rt, rl); HWDET_RESOURCE(name, drv, alt, HWDET_MMIO, rs + rt, rl); break;
- case 1: if(ra) HWDET_RESOURCE(name, drv, alt, HWDET_IO, rs + rt, rl); break;
- }
- }
- break;
- case 0x88: /* Word Address Space Descriptor */
- ra = ((uint64_t)ptr[3] | ((uint64_t)ptr[4] << 8)) + 1;
- rs = ((uint64_t)ptr[5] | ((uint64_t)ptr[6] << 8)); re = ((uint64_t)ptr[7] | ((uint64_t)ptr[8] << 8));
- rt = ((uint64_t)ptr[9] | ((uint64_t)ptr[10] << 8)); rl = ((uint64_t)ptr[11] | ((uint64_t)ptr[12] << 8));
- goto asd;
- break;
- case 0x89: /* Extended Interrupt Descriptor */
- for(n = ptr[1], i = 0; i < n; i++)
- HWDET_RESOURCE(name, drv, alt, HWDET_IRQ, (uint64_t)ptr[2+i*4] | ((uint64_t)ptr[3+i*4] << 8) |
- ((uint64_t)ptr[4+i*4] << 16) | ((uint64_t)ptr[5+i*4] << 24), 0);
- break;
- case 0x8A: /* QWord Address Space Descriptor */
- memcpy(&ra, ptr + 3, 8); ra++;
- memcpy(&rs, ptr + 11, 8); memcpy(&re, ptr + 19, 8);
- memcpy(&rt, ptr + 27, 8); memcpy(&rl, ptr + 35, 8);
- goto asd;
- break;
- case 0x8B: /* Extended Address Space Descriptor */
- memcpy(&ra, ptr + 5, 8); ra++;
- memcpy(&rs, ptr + 13, 8); memcpy(&re, ptr + 21, 8);
- memcpy(&rt, ptr + 29, 8); memcpy(&rl, ptr + 37, 8);
- goto asd;
- break;
- case 0x8C: case 0x8E: /* Connectors */
- case 0x8D: case 0x8F: case 0x90: case 0x91: case 0x92: /* Pins */
- case 0x0F: /* End Tag */ break;
- #ifdef AML_DEBUG
- default: printf("unhandled ResourceTemplate %lx type %02x\n",(uintptr_t)ptr, t); exit(1); break;
- #endif
- }
- ptr += s;
- }
- } else
- if(aml.node[aml.regidx].type) HWDET_RESOURCE(name, drv, alt, HWDET_NONE, 0, 0);
- }
- }
- /**
- * AML név beolvasása
- */
- static uint8_t *aml_NameString(uint8_t *ptr)
- {
- int c;
- #ifdef AML_DEBUG
- if(stkchk + 24 > stkmax) stkmax = stkchk + 24;
- #endif
- while(*ptr == '\\' || *ptr == '^') ptr++;
- switch(*ptr) {
- case 0x00: ptr++; c = 0; break;
- case 0x2E: ptr++; c = 8; break;
- case 0x2F: ptr++; c = *ptr++ << 2; break;
- default: c = 4; break;
- }
- return ptr + c;
- }
- /**
- * AML változónév beolvasása
- */
- static uint8_t *aml_SuperName(uint8_t *ptr, aml_t *node)
- {
- uint8_t *st = ptr;
- uint16_t op;
- #ifdef AML_DEBUG
- if(stkchk + 32 > stkmax) stkmax = stkchk + 32;
- #endif
- ptr = aml_opcode(ptr, &op);
- node->type = op;
- switch(op) {
- case 0x0000: /* NullStr */ node->data.q[0] = 0; node->type = 0x000D; break;
- case 0x0009: /* Simplename */ if((op = aml_lookup(st))) memcpy(node, &aml.node[op], sizeof(aml_t)); break;
- case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067: /* LocalX */
- case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F: /* ArgX */
- break;
- case 0x5B31: /* DebugObj */ break;
- default: ptr = st; break;
- }
- return ptr;
- }
- /**
- * AML mezőlista beolvasása
- */
- static uint8_t *aml_FieldList(uint8_t *ptr, uint8_t *end, aml_t *node)
- {
- uint32_t pos = 0;
- AML_STKENTER(24);
- while(ptr < end) {
- switch(*ptr) {
- case 0: /* reserved */ ptr++; ptr = aml_pkg(ptr); pos += aml.len; break;
- case 1: /* access */ ptr += 3; break;
- case 2: /* connect */ ptr = aml_NameString(ptr + 1); break;
- case 3: /* extended */ ptr += 3 + ptr[2]; break;
- default: /* named */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- NODE.name = ptr; ptr += 4; ptr = aml_pkg(ptr);
- NODE.type = 0x5B13; NODE.parent = aml.par;
- NODE.data.q[0] = node->data.q[0];
- NODE.data.d[2] = pos; NODE.data.d[3] = aml.len;
- pos += aml.len;
- aml.num++;
- break;
- }
- }
- AML_STKLEAVE(24);
- return ptr;
- }
- /**
- * AML bájtkód értelmezése
- */
- static uint8_t *aml_TermArg(uint8_t *ptr, uint8_t *end, aml_t *node)
- {
- aml_t arg1, arg2;
- uint8_t *st = ptr, *s;
- uint16_t op;
- uint32_t l, par, num;
- ptr = aml_opcode(ptr, &op);
- #ifdef AML_DEBUG
- AML_STKENTER(104);
- if(aml.num > numchk) numchk = aml.num;
- #if AML_DEBUG+0 > 1
- printf("%08lx op %x (ptr %lx num %d par %d)\n",(uintptr_t)st,op,(uintptr_t)ptr,aml.num,aml.par);
- #endif
- #endif
- memset(&arg1, 0, sizeof(arg1)); memset(&arg2, 0, sizeof(arg2));
- switch(op) {
- case 0x5B30: /* RevisionOp */
- case 0x0000: /* ZeroOp */ node->data.q[0] = 0; node->type = 0x000E; break;
- case 0x0001: /* OneOp */ node->data.q[0] = 1; node->type = 0x000E; break;
- case 0x00FF: /* OnesOp */ node->data.q[0] = ~0UL; node->type = 0x000E; break;
- case 0x0006: /* AliasOp */
- l = aml_lookup(ptr); ptr = aml_NameString(ptr);
- s = ptr; ptr = aml_NameString(ptr);
- if(l) {
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- memcpy(&NODE, &aml.node[l], sizeof(aml_t));
- NODE.name = s; NODE.parent = aml.par; aml_fn(&NODE);
- aml.num++;
- }
- break;
- case 0x0008: /* NameOp */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = par = aml.par; aml.par = aml.num; aml_fn(&NODE);
- if(!memcmp(NODE.name, "_HID", 4)) aml.drvidx = aml.num; else
- if(!memcmp(NODE.name, "_CID", 4)) aml.altidx = aml.num; else
- if(!memcmp(NODE.name, "_CRS", 4)) aml.regidx = aml.num;
- num = aml.num++; ptr = aml_TermArg(ptr, end, &aml.node[num]);
- aml.num = num + 1; aml.par = par;
- break;
- case 0x0009: /* ObjReference/Call */
- if((l = aml_lookup(st))) {
- if(aml.node[l].type == 0x0014) {
- if(aml.sp >= 16 && aml.sp - 16 < AML_MAXLEVEL*16) {
- aml.sp -= 8;
- /* ACPI AML bug: 8 paramétert lehet címezni, de a 0x14 MethodFlags-ében csak 7 paramétert lehet megadni */
- for(par = 0; par <= (aml.node[l].data.d[3] & 7); par++) {
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- aml.stack[aml.sp + par] = arg1.data.q[0];
- }
- aml.sp -= 8;
- aml_TermList(aml.node[l].data.p[0], aml.node[l].data.p[0] + aml.node[l].data.d[2], &arg1);
- node->data.q[0] = arg1.data.q[0]; node->data.q[1] = arg1.data.q[1]; node->type = arg1.type;
- }
- } else { memcpy(&node->data, &aml.node[l].data, sizeof(arg1.data)); node->type = aml.node[l].type; }
- }
- break;
- case 0x000A: /* BytePrefix */ node->data.q[0] = *ptr++; node->type = op; break;
- case 0x000B: /* WordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 2); ptr += 2; node->type = op; break;
- case 0x000C: /* DWordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 4); ptr += 4; node->type = op; break;
- case 0x000E: /* QWordPrefix */ node->data.q[0] = 0; memcpy(node->data.q, ptr, 8); ptr += 8; node->type = op; break;
- case 0x000D: /* StringPrefix */ node->data.p[0] = ptr; node->type = op; while(ptr[-1]) ptr++; break;
- case 0x0010: /* Scope */
- case 0x0014: /* Method */
- case 0x5B82: /* Device */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_pkg(ptr); s = st + (op > 0xff ? 2 : 1) + aml.len;
- if(op == 0x5B82) aml.devidx = aml.num;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = par = aml.par; aml.par = aml.num;
- aml_fn(&NODE);
- /* ha metódus, akkor csak akkor futtatjuk le, ha eszközmeghajtótípus, vagy regiszterdefiníció
- * mivel direktben a metódus node-jával hívjuk, felül fognak ezek íródni a visszatérési értékkel,
- * és a továbbiakban mint normál változók fognak működni */
- if(op == 0x0014) {
- NODE.data.d[3] = (*ptr++ & 7);
- NODE.data.p[0] = ptr;
- NODE.data.d[2] = s - ptr;
- l = 0; aml.mtdidx = aml.num;
- if(!memcmp(NODE.name, "_HID", 4)) { l = 1; aml.drvidx = aml.num; } else
- if(!memcmp(NODE.name, "_CID", 4)) { l = 1; aml.altidx = aml.num; } else
- if(!memcmp(NODE.name, "_CRS", 4)) { l = 1; aml.regidx = aml.num; }
- if(l) { if(!aml.sp) l = 0; else { aml.sp -= 16; memset(&aml.stack[aml.sp], 0, 16 * sizeof(aml.stack[0])); } }
- } else l = 1;
- #if AML_DEBUG+0 > 1
- printf("SCOPE++ %04x '%c%c%c%c' num %d par %d aml.len %d s %lx l %d sp %d\n", op,
- NODE.name[0],NODE.name[1],NODE.name[2],NODE.name[3],aml.num,par,aml.len,(uintptr_t)s,l,aml.sp);
- #endif
- num = aml.num++;
- if(l) ptr = aml_TermList(ptr, s, &aml.node[num]);
- ptr = s;
- if(op == 0x0014) { aml.mtdidx = -1U; if(l) aml.sp += 16; }
- #if AML_DEBUG+0 > 1
- printf("SCOPE-- num %d (new %d) %lx sp %d\n",aml.num,num+1,(uintptr_t)ptr,aml.sp);
- #endif
- if(op == 0x5B82 && aml.devidx != -1U && aml.drvidx != -1U && aml.regidx != -1U) {
- aml_ResourceTemplate();
- aml.devidx = aml.drvidx = aml.altidx = aml.regidx = -1U;
- }
- aml.num = num + 1; aml.par = par;
- break;
- case 0x0015: /* ExternalOp */
- ptr = aml_NameString(ptr) + 2;
- break;
- case 0x0011: /* Buffer */
- ptr = aml_pkg(ptr); st += 1 + aml.len;
- ptr = aml_TermArg(ptr, end, &arg1);
- node->data.q[1] = arg1.data.q[0];
- node->data.p[0] = ptr;
- node->type = op;
- ptr = st;
- break;
- case 0x0012: /* Package */
- ptr = aml_pkg(ptr); st += 1 + aml.len;
- node->data.d[2] = aml.len;
- node->data.d[3] = *ptr++;
- node->data.p[0] = ptr;
- node->type = op;
- ptr = st;
- break;
- case 0x0013: /* VarPackage */
- ptr = aml_pkg(ptr); st += 1 + aml.len;
- ptr = aml_TermArg(ptr, end, node);
- node->data.d[2] = aml.len;
- node->data.d[3] = 0;
- node->data.p[0] = ptr;
- node->type = op;
- ptr = st;
- break;
- case 0x5B01: /* MutexOp */ ptr = aml_NameString(ptr) + 1; break;
- case 0x5B02: /* EventOp */ ptr = aml_NameString(ptr); break;
- case 0x5B12: /* CondRefOfOp */
- case 0x0071: /* RefOfOp */
- ptr = aml_SuperName(ptr, &arg1);
- ptr = aml_SuperName(ptr, &arg2);
- if(arg1.type != 0x0009) {
- aml_set(&arg2, &arg1);
- memcpy(node, &arg1, sizeof(arg1));
- } else
- if(op == 0x0071) return (uint8_t*)-1UL;
- break;
- case 0x5B1F: /* LoadTableOp */
- ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1);
- ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1); ptr = aml_TermArg(ptr, end, &arg1);
- break;
- case 0x5B20: /* LoadOp */
- l = aml_lookup(ptr); ptr = aml_NameString(ptr);
- ptr = aml_SuperName(ptr, &arg1);
- if(l) { memcpy(&aml.node[l].data, &arg1.data, sizeof(arg1.data)); aml.node[l].type = arg1.type; }
- break;
- case 0x5B21: /* StallOp */
- case 0x5B22: /* SleepOp */
- ptr = aml_TermArg(ptr, end, &arg1);
- break;
- case 0x5B23: /* AcquireOp */
- ptr = aml_SuperName(ptr, &arg1) + 2;
- break;
- case 0x5B24: /* SignalOp */
- case 0x5B26: /* ResetOp */
- case 0x5B27: /* ReleaseOp */
- ptr = aml_SuperName(ptr, &arg1);
- break;
- case 0x5B25: /* WaitOp */
- ptr = aml_SuperName(ptr, &arg1);
- ptr = aml_TermArg(ptr, end, &arg1);
- break;
- case 0x5B28: /* FromBCDOp */
- case 0x5B29: /* ToBCDOp */
- ptr = aml_TermArg(ptr, end, &arg1);
- ptr = aml_SuperName(ptr, &arg1);
- break;
- case 0x5B32: /* FatalOp */ return (uint8_t*)-1UL;
- case 0x5B80: /* OpRegion */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
- NODE.data.b[12] = *ptr++; /* space */
- ptr = aml_TermArg(ptr, end, &arg1); /* address */
- NODE.data.q[0] = arg1.data.q[0];
- ptr = aml_TermArg(ptr, end, &arg1); /* length */
- NODE.data.d[2] = arg1.data.d[0];
- /* ha rendszermemóriára hivatkozik, ki kell venni a szabad memória listából */
- if(!NODE.data.b[12] && NODE.data.q[0]) HWDET_RESVMEM(NODE.data.q[0], NODE.data.d[2]);
- aml.num++;
- break;
- case 0x5B81: /* Field */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_pkg(ptr); st += 2 + aml.len;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
- NODE.data.d[0] = 0;
- NODE.data.d[1] = *ptr++; /* flags */
- aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
- ptr = st;
- break;
- case 0x5B83: /* Processor (nem használt a v6.4 óta) */
- ptr = aml_pkg(ptr);
- arg1.data.q[0] = 0; memcpy(&arg1.data, ptr, 4);
- HWDET_RESOURCE((char*)&arg1.data, "CORE", "", HWDET_CPU, 0, ptr[4]);
- ptr = st + 2 + aml.len;
- break;
- case 0x5B86: /* IndexField */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_pkg(ptr); st += 2 + aml.len;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
- NODE.data.d[0] = aml_lookup(ptr); ptr = aml_NameString(ptr);
- NODE.data.d[1] = *ptr++; /* flags */
- aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
- ptr = st;
- break;
- case 0x5B87: /* BankField */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_pkg(ptr); st += 2 + aml.len;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
- NODE.data.d[0] = aml_lookup(ptr); ptr = aml_NameString(ptr);
- ptr = aml_TermArg(ptr, end, &arg1);
- NODE.data.d[1] = *ptr++; /* flags */
- NODE.data.q[1] = arg1.data.q[0];
- aml.num++; ptr = aml_FieldList(ptr, st, &aml.node[aml.num - 1]);
- ptr = st;
- break;
- case 0x5B88: /* DataRegion */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_pkg(ptr); st += 2 + aml.len;
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = op; NODE.parent = aml.par; aml_fn(&NODE);
- ptr = aml_TermArg(ptr, end, &arg1); NODE.data.q[0] = arg1.data.q[0];
- ptr = aml_TermArg(ptr, end, &arg1); NODE.data.d[2] = arg1.data.d[0];
- ptr = aml_TermArg(ptr, end, &arg1); NODE.data.d[3] = arg1.data.d[0];
- aml.num++;
- ptr = st;
- break;
- case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067: /* LocalX */
- case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F: /* ArgX */
- node->type = op; op = aml.sp + op - 0x60; node->data.q[0] = op < AML_MAXLEVEL*16 ? aml.stack[op] : 0;
- break;
- case 0x0070: /* StoreOp */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
- break;
- case 0x0075: /* IncrementOp */
- ptr = aml_SuperName(ptr, &arg1); aml_get(&arg2, &arg1);
- arg2.data.q[0]++; aml_set(&arg1, &arg2);
- node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
- break;
- case 0x0076: /* DecrementOp */
- ptr = aml_SuperName(ptr, &arg1); aml_get(&arg2, &arg1);
- arg2.data.q[0]--; aml_set(&arg1, &arg2);
- node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
- break;
- case 0x0083: /* DerefOfOp */
- ptr = aml_TermArg(ptr, end, &arg1);
- if(arg1.type == 0x000D) {
- l = aml_lookup(arg1.data.p[0]);
- if(l) memcpy(&arg1, &aml.node[l], sizeof(arg1));
- }
- memcpy(node, &arg1, sizeof(arg1));
- break;
- case 0x0072: /* AddOp */
- case 0x0073: /* ConcatOp */
- case 0x0074: /* SubtractOp */
- case 0x0077: /* MultiplyOp */
- case 0x0078: /* DivideOp */
- case 0x0079: /* ShiftLeftOp */
- case 0x007A: /* ShiftRightOp */
- case 0x007B: /* AndOp */
- case 0x007C: /* NandOp */
- case 0x007D: /* OrOp */
- case 0x007E: /* NorOp */
- case 0x007F: /* XorOp */
- case 0x0084: /* ConcatResOp */
- case 0x0085: /* ModOp */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
- switch(op) {
- case 0x0072: arg1.data.q[0] += arg2.data.q[0]; break;
- case 0x0074: arg1.data.q[0] -= arg2.data.q[0]; break;
- case 0x0077: arg1.data.q[0] *= arg2.data.q[0]; break;
- case 0x0078: arg1.data.q[0] = arg2.data.q[0] ? arg1.data.q[0] / arg2.data.q[0] : 0; break;
- case 0x0079: arg1.data.q[0] <<= arg2.data.q[0]; break;
- case 0x007A: arg1.data.q[0] >>= arg2.data.q[0]; break;
- case 0x007B: arg1.data.q[0] &= arg2.data.q[0]; break;
- case 0x007C: arg1.data.q[0] = ~(arg1.data.q[0] & arg2.data.q[0]); break;
- case 0x007D: arg1.data.q[0] |= arg2.data.q[0]; break;
- case 0x007E: arg1.data.q[0] = ~(arg1.data.q[0] | arg2.data.q[0]); break;
- case 0x007F: arg1.data.q[0] ^= arg2.data.q[0]; break;
- case 0x0085: arg1.data.q[0] = arg2.data.q[0] ? arg1.data.q[0] % arg2.data.q[0] : 0; break;
- }
- ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
- node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
- break;
- case 0x0088: /* IndexOp */
- ptr = aml_TermArg(ptr, end, &arg1);
- ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
- arg1.data.q[0] += arg2.data.q[0];
- ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
- node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
- break;
- case 0x0090: /* LandOp */
- case 0x0091: /* LorOp */
- case 0x9293: /* LNotEqualOp */
- case 0x9294: /* LLessEqualOp */
- case 0x9295: /* LGreaterEqualOp */
- case 0x0093: /* LEqualOp */
- case 0x0094: /* LGreaterOp */
- case 0x0095: /* LLessOp */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- ptr = aml_TermArg(ptr, end, &arg2); aml_get(&arg2, &arg2);
- switch(op) {
- case 0x0090: arg1.data.q[0] = (arg1.data.q[0] && arg2.data.q[0]); break;
- case 0x0091: arg1.data.q[0] = (arg1.data.q[0] || arg2.data.q[0]); break;
- case 0x9293: arg1.data.q[0] = (arg1.data.q[0] != arg2.data.q[0]); break;
- case 0x9294: arg1.data.q[0] = (arg1.data.q[0] <= arg2.data.q[0]); break;
- case 0x9295: arg1.data.q[0] = (arg1.data.q[0] >= arg2.data.q[0]); break;
- case 0x0093: arg1.data.q[0] = (arg1.data.q[0] == arg2.data.q[0]); break;
- case 0x0094: arg1.data.q[0] = (arg1.data.q[0] > arg2.data.q[0]); break;
- case 0x0095: arg1.data.q[0] = (arg1.data.q[0] < arg2.data.q[0]); break;
- }
- node->data.q[0] = arg1.data.q[0]; node->type = arg1.type;
- break;
- case 0x0081: /* FindSetLeftBitOp */
- case 0x0082: /* FindSetRightBitOp */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- ptr = aml_SuperName(ptr, &arg2);
- if(arg1.data.q[0]) {
- if(op == 0x0081) for(l = 1; arg1.data.q[0] & 1; l++, arg1.data.q[0] >>= 1);
- else for(l = 1; !(arg1.data.q[0] & 1); l++, arg1.data.q[0] >>= 1);
- } else l = 0;
- arg2.data.q[0] = l; aml_set(&arg2, &arg2);
- node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
- break;
- case 0x0092: /* LnotOp */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1);
- arg1.data.q[0] = !arg1.data.q[0];
- ptr = aml_SuperName(ptr, &arg2); aml_set(&arg2, &arg1);
- node->data.q[0] = arg2.data.q[0]; node->type = arg2.type;
- break;
- case 0x0086: /* NotifyOp */
- ptr = aml_SuperName(ptr, &arg1);
- ptr = aml_TermArg(ptr, end, &arg2);
- #ifdef AML_DEBUG
- aml_get(&arg2, &arg2);
- printf("NotifyOp\n");
- aml_dump(&arg1);
- aml_dump(&arg2);
- #endif
- break;
- case 0x0087: /* SizeofOp */
- ptr = aml_SuperName(ptr, &arg1);
- node->data.q[0] = 0;
- switch(arg1.type) {
- case 0x000A: node->data.q[0] = 1; break;
- case 0x000B: node->data.q[0] = 2; break;
- case 0x000C: node->data.q[0] = 4; break;
- case 0x000D: if((s = node->data.p[0]) && s >= aml.memmin && s < aml.memmax) for(; *s; s++, node->data.q[0]++); break;
- case 0x0060: case 0x0061: case 0x0062: case 0x0063: case 0x0064: case 0x0065: case 0x0066: case 0x0067:
- case 0x0068: case 0x0069: case 0x006A: case 0x006B: case 0x006C: case 0x006D: case 0x006E: case 0x006F:
- case 0x000E: node->data.q[0] = 8; break;
- case 0x0011: case 0x0012: case 0x0013: case 0x5B80: node->data.q[0] = arg1.data.d[2]; break;
- case 0x5B13: node->data.q[0] = (arg1.data.d[3] + 7) >> 3; break;
- }
- node->type = 0x000E;
- break;
- case 0x0089: /* MatchOp */
- ptr = aml_TermArg(ptr, end, &arg1); /* package */
- ptr++; /* op1 */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* obj1 */
- ptr++; /* op2 */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* obj2 */
- ptr = aml_TermArg(ptr, end, &arg1); aml_get(&arg1, &arg1); /* startindex */
- node->data.q[0] = ~0UL; node->type = 0x000E;
- break;
- case 0x008A: /* CreateDWordField */
- case 0x008B: /* CreateWordField */
- case 0x008C: /* CreateByteField */
- case 0x008D: /* CreateBitField */
- case 0x008F: /* CreateQWordField */
- case 0x5B13: /* CreateFieldOp */
- if(aml.num >= aml.max) return (uint8_t*)-1UL;
- ptr = aml_TermArg(ptr, end, &arg1); /* SourceBuff */
- ptr = aml_TermArg(ptr, end, &arg2); /* ByteIndex (0x8D/0x5B13=BitIndex) */
- NODE.name = ptr; ptr = aml_NameString(ptr);
- NODE.type = 0x5B13; NODE.parent = aml.par; aml_fn(&NODE);
- NODE.data.q[0] = arg1.data.q[0]; NODE.data.d[2] = arg2.data.d[0];
- switch(op) { /* size */
- case 0x008A: NODE.data.d[3] = 32; NODE.data.d[2] <<= 3; break;
- case 0x008B: NODE.data.d[3] = 16; NODE.data.d[2] <<= 3; break;
- case 0x008C: NODE.data.d[3] = 8; NODE.data.d[2] <<= 3; break;
- case 0x008D: NODE.data.d[3] = 1; break;
- case 0x008F: NODE.data.d[3] = 64; NODE.data.d[2] <<= 3; break;
- case 0x5B13: ptr = aml_TermArg(ptr, end, &arg2); NODE.data.d[3] = arg2.data.d[0]; break;
- }
- aml.num++;
- break;
- case 0x008E: /* ObjectType */
- ptr = aml_SuperName(ptr, &arg1);
- node->type = 0x000E;
- switch(arg1.type) {
- case 0x000A: case 0x000B: case 0x000C: case 0x000E: node->data.q[0] = 1; break; /* Integer */
- case 0x000D: node->data.q[0] = 2; break; /* String */
- case 0x0011: node->data.q[0] = 3; break; /* Buffer */
- case 0x0012: case 0x0013: node->data.q[0] = 4; break; /* Package */
- case 0x5B81: node->data.q[0] = 5; break; /* Field */
- case 0x5B82: node->data.q[0] = 6; break; /* Device */
- case 0x5B02: node->data.q[0] = 7; break; /* Event */
- case 0x0014: node->data.q[0] = 8; break; /* Method */
- case 0x5B01: node->data.q[0] = 9; break; /* Mutex */
- case 0x5B80: node->data.q[0] =10; break; /* OpRegion */
- case 0x5B84: node->data.q[0] =11; break; /* PowerRes */
- case 0x5B83: node->data.q[0] =12; break; /* Processor */
- case 0x5B85: node->data.q[0] =13; break; /* ThermalZone */
- case 0x5B13: node->data.q[0] =14; break; /* BufferField */
- case 0x5B1F: case 0x5B20: node->data.q[0] =15; break; /* DDBHandle */
- case 0x5B30: node->data.q[0] =16; break; /* DebugObj */
- default: node->data.q[0] = 0;
- }
- break;
- case 0x00A0: /* If */
- ptr = aml_pkg(ptr); st += 1 + aml.len;
- ptr = aml_TermArg(ptr, end, &arg1);
- if(arg1.data.q[0]) ptr = aml_TermList(ptr, st, node); else ptr = st;
- if(*ptr == 0xA1) {
- ptr = aml_pkg(ptr + 1); st += 1 + aml.len;
- if(arg1.data.q[0]) ptr = st; else ptr = aml_TermList(ptr, st, node);
- }
- break;
- case 0x00A1: /* Else blokk If nélkül? */
- ptr = aml_pkg(ptr); ptr = st + 1 + aml.len;
- break;
- case 0x00A2: /* While */
- /* ezt direkt kihagyjuk, mert nekünk csak arra kell az AML, hogy a regisztermezőket lekérjük */
- ptr = aml_pkg(ptr); ptr = st + 1 + aml.len;
- break;
- case 0x00A4: /* Return */
- ptr = aml_TermArg(ptr, end, &arg1);
- memcpy(&node->data, &arg1.data, sizeof(arg1.data)); node->type = arg1.type;
- break;
- case 0x5B2A: /* fenntartott */
- case 0x5B33: /* TimerOp */
- case 0x009F: /* Continue */
- case 0x00A3: /* Noop */
- case 0x00CC: /* BreakPoint */ break;
- default: ptr = st; break;
- }
- AML_STKLEAVE(104);
- return ptr;
- }
- /**
- * AML bájtkód értelmezése
- */
- static uint8_t *aml_TermList(uint8_t *ptr, uint8_t *end, aml_t *node)
- {
- uint8_t *st;
- AML_STKENTER(24);
- if(!node) { node = &aml.node[0]; memset(node, 0, sizeof(aml_t)); }
- while(ptr < end) {
- st = ptr; ptr = aml_TermArg(st, end, node);
- if(ptr == st) {
- #ifdef AML_DEBUG
- printf("unknown opcode %08lx %02x %02x\n", (uintptr_t)ptr, ptr[0], ptr[1]); exit(1);
- #endif
- return (uint8_t*)-1UL;
- }
- }
- AML_STKLEAVE(24);
- return ptr;
- }
- typedef struct {
- char *name, *drv, *alt;
- uint32_t parent, intparent, addrcells, sizecells, intcells, dmacells, clkcells, gpiocells;
- uint32_t type, phandle, phparent;
- uint32_t mapsz[2], *map[2];
- uint64_t cpurel;
- } fdt_t;
- static fdt_t *fdt_nodes;
- static uint32_t fdt_numnodes;
- /**
- * Get value (from a property data)
- */
- static uint64_t fdt_value(uint32_t *ptr, uint32_t size)
- {
- uint64_t r = 0;
- uint8_t *p = (uint8_t*)ptr;
- if(size) {
- r = ((uint64_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
- if(size > 1) { p += 4; r <<= 32; r |= ((uint64_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; }
- }
- return r;
- }
- /**
- * Get address (get value from property data and translate to parent address space)
- */
- static uint64_t fdt_addr(uint32_t *ptr, uint32_t size, int map, fdt_t *node)
- {
- uint32_t i, siz, as;
- uint64_t a = fdt_value(ptr, size), c, b, s;
- if(node->parent) {
- node = &fdt_nodes[node->parent];
- as = fdt_nodes[node->parent].addrcells;
- while(1) {
- if(node->map[map] && node->mapsz[map] && node->sizecells) {
- siz = node->mapsz[map] >> 2;
- for(i = 0; i < siz;) {
- c = fdt_value(&node->map[map][i], node->addrcells); i += node->addrcells;
- b = fdt_value(&node->map[map][i], as); i += as;
- s = fdt_value(&node->map[map][i], node->sizecells); i += node->sizecells;
- if(a >= c && a < c + s) { a = a - c + b; break; }
- }
- }
- if(!node->parent || node->parent >= fdt_numnodes || node == &fdt_nodes[node->parent]) break;
- node = &fdt_nodes[node->parent];
- }
- }
- return a;
- }
- /**
- * Get a phandle (return node index for phandle in property data)
- */
- static uint32_t fdt_phandle(uint32_t *ptr)
- {
- uint32_t i;
- if(ptr && *ptr)
- for(i = 0; i < fdt_numnodes; i++)
- if(*ptr == fdt_nodes[i].phandle)
- return i;
- return 0;
- }
- /**
- * The real deal, convert an FDT node properties into a GUDT node
- */
- static void fdt_prop(char *name, uint8_t *value, uint32_t size, fdt_t *node)
- {
- uint64_t a, s;
- uint32_t as, ss, is, i, j, n = size >> 2, *p = (uint32_t*)value;
- if(value && size) {
- as = fdt_nodes[node->parent].addrcells; ss = fdt_nodes[node->parent].sizecells; is = fdt_nodes[node->intparent].intcells;
- if(!memcmp(name, "reg", 4) && as) {
- for(i = 0; i < n;) {
- a = fdt_addr(&p[i], as, 0, node); i += as;
- s = fdt_value(&p[i], ss); i += ss;
- switch(node->type) {
- case 1: HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_CPU, node->cpurel, a); break;
- case 2: break;
- case 3: HWDET_RESVMEM(a, s); break;
- default: HWDET_RESVMEM(a, s); HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_MMIO, a, s); break;
- }
- }
- } else
- if(!memcmp(name, "dmas", 5) && as) {
- for(i = 0; i < n;) {
- a = fdt_addr(&p[i], as, 1, node); i += as;
- s = fdt_value(&p[i], ss); i += ss;
- HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_DMA, a, s);
- }
- } else
- if(!memcmp(name, "interrupts-extended", 20)) {
- for(i = 0; i < n;) {
- j = fdt_phandle(&p[i]); i++;
- if(!fdt_nodes[j].intcells) break;
- if(fdt_nodes[j].intcells > 2) i += fdt_nodes[j].intcells - 2;
- a = fdt_value(&p[i], 1); i++;
- if(fdt_nodes[j].intcells > 1) { s = fdt_value(&p[i], 1); i++; } else s = 0;
- HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_IRQ, a, s);
- }
- } else
- if(!memcmp(name, "interrupts", 11) && is) {
- for(i = 0; i < n;) {
- if(is > 2) i += is - 2;
- a = fdt_value(&p[i], 1); i++;
- if(is > 1) { s = fdt_value(&p[i], 1); i++; } else s = 0;
- HWDET_RESOURCE(node->name, node->drv, node->alt, HWDET_IRQ, a, s);
- }
- }
- #if AML_DEBUG
- else printf("unhandled property \"%s\" \"%s\" \"%s\"\r\n", node->drv, node->name, name);
- #endif
- }
- }
- /**
- * FDT bájtkód értelmezése
- */
- static void fdt_dtb(uint8_t *ptr)
- {
- fdt_t *node;
- uint32_t parent[AML_MAXLEVEL];
- uint32_t totalsize = ptr[7] | (ptr[6] << 8) | (ptr[5] << 16);
- uint32_t off_dt = ptr[11] | (ptr[10] << 8) | (ptr[9] << 16);
- uint32_t off_str = ptr[15] | (ptr[14] << 8) | (ptr[13] << 16);
- uint32_t off_rsvmap = ptr[19] | (ptr[18] << 8) | (ptr[17] << 16);
- uint32_t version = ptr[23] | (ptr[22] << 8) | (ptr[21] << 16);
- uint32_t siz_str = ptr[35] | (ptr[34] << 8) | (ptr[33] << 16);
- uint32_t siz_dt = ptr[39] | (ptr[38] << 8) | (ptr[37] << 16);
- uint32_t siz_rsvmap = (off_dt < off_str ? off_dt : off_str) - off_rsvmap;
- uint8_t *p = ptr + off_dt, *t, *s, *end = ptr + off_dt + siz_dt;
- uint32_t i, tag, sz, idx, d = 0;
- #if AML_DEBUG+0 > 1
- uint32_t j, k, l;
- #endif
- uint64_t addr, size;
- if(version < 17) {
- #ifdef AML_DEBUG
- printf("FDT version %d not supported\n", version);
- #endif
- return;
- }
- for(i = 0; i < siz_rsvmap; i += 16) {
- p = ptr + off_rsvmap + i;
- addr = p[7] | (p[6] << 8) | (p[5] << 16) | (p[4] << 24) | ((uint64_t)p[3] << 32) | ((uint64_t)p[2] << 40);
- p += 8;
- size = p[7] | (p[6] << 8) | (p[5] << 16) | (p[4] << 24) | ((uint64_t)p[3] << 32) | ((uint64_t)p[2] << 40);
- if(addr == 0 && size == 0) break;
- HWDET_RESVMEM(addr, size);
- }
- if(end > ptr + totalsize) end = ptr + totalsize;
- /* first, count nodes */
- for(fdt_numnodes = 0, p = ptr + off_dt; p < end; ) {
- tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
- if(tag == 9) break;
- switch(tag) {
- case 1: fdt_numnodes++; for(; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3); break;
- case 3: sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 8; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3); break;
- }
- }
- if(!fdt_numnodes) return;
- fdt_nodes = (fdt_t*)__builtin_alloca((fdt_numnodes + 1) * sizeof(fdt_t));
- memset(fdt_nodes, 0, (fdt_numnodes + 1) * sizeof(fdt_t));
- memset(parent, 0, sizeof(parent));
- /* second run, collect phandle references in advance */
- for(idx = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
- tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
- if(tag == 9) break;
- switch(tag) {
- case 1: for(node++, idx++; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3); break;
- case 3:
- sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
- s = ptr + off_str + i;
- if(i < siz_str - 1) {
- if(!memcmp(s, "#interrupt-cells", 17)) { node->intcells = t[sz - 1]; } else
- if(!memcmp(s, "interrupt-parent", 17)) { memcpy(&node->phparent, t, 4); } else
- if(!memcmp(s, "phandle", 8) || !memcmp(s, "linux,phandle", 14)) { memcpy(&node->phandle, t, 4); }
- }
- break;
- }
- }
- /* third run, actually flatten the so called "flattened" device tree, parse all properties */
- for(idx = d = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
- tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
- if(tag == 9) break;
- switch(tag) {
- case 1:
- node++;
- if(d) parent[d] = parent[d - 1];
- node->addrcells = 2; node->sizecells = 1;
- node->parent = parent[d];
- if(node->phparent) node->intparent = fdt_phandle(&node->phparent);
- else node->intparent = fdt_nodes[node->parent].intparent;
- if(!node->intparent) node->intparent = node->parent;
- for(node->name = (char*)p; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3);
- if(!memcmp(node->name, "cpu@", 4)) node->type = 1;
- if(!memcmp(node->name, "memory@", 7)) node->type = 2;
- if(!memcmp(node->name, "nvram@", 6)) node->type = 3;
- parent[d++] = ++idx;
- break;
- case 2: d--; break;
- case 3:
- sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
- s = ptr + off_str + i;
- if(i < siz_str - 1) {
- if(!memcmp(s, "#address-cells", 15)) { node->addrcells = t[sz - 1]; } else
- if(!memcmp(s, "#size-cells", 12)) { node->sizecells = t[sz - 1]; } else
- if(!memcmp(s, "#dma-cells", 11)) { node->dmacells = t[sz - 1]; } else
- if(!memcmp(s, "#clock-cells", 13)) { node->clkcells = t[sz - 1]; } else
- if(!memcmp(s, "#gpio-cells", 12)) { node->gpiocells = t[sz - 1]; } else
- if((!memcmp(s, "model", 6) || !memcmp(s, "name", 5)) && !*node->name) { node->name = (char*)t; } else
- if(!memcmp(s, "device_type", 12)) {
- if(!memcmp(t, "cpu", 4)) node->type = 1;
- if(!memcmp(t, "memory", 7)) node->type = 2;
- if(!memcmp(t, "nvram", 6)) node->type = 3;
- } else
- if(!memcmp(s, "cpu-release", 11)) { node->type = 1; node->cpurel = fdt_value((uint32_t*)t, 2); } else
- if(!memcmp(s, "ranges", 7)) {
- if(sz) {
- node->map[0] = (uint32_t*)t;
- node->mapsz[0] = sz;
- }
- } else
- if(!memcmp(s, "dma-ranges", 11)) {
- if(sz) {
- node->map[1] = (uint32_t*)t;
- node->mapsz[1] = sz;
- }
- } else
- if(!memcmp(s, "compatible", 11)) {
- for(node->drv = (char*)t; *t && t < p; t++);
- node->alt = !*t && t[1] && t + 2 < p ? (char*)t + 1 : NULL;
- }
- }
- break;
- }
- }
- /* fourth times the charm, do the actual parsing */
- for(idx = d = 0, p = ptr + off_dt, node = fdt_nodes; p < end && idx < fdt_numnodes; ) {
- tag = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); p += 4;
- if(tag == 9) break;
- switch(tag) {
- case 1:
- node++; idx++;
- for(; p < end && *p; p++){} p = (uint8_t*)(((uintptr_t)p + 3) & ~3);
- #if AML_DEBUG+0 > 1
- printf("\r\n");
- for(l = 0; l < d; l++) printf(" ");
- printf("node %u name '%s' drv '%s' alt '%s'\r\n", idx, node->name, node->drv, node->alt);
- for(l = 0; l < d; l++) printf(" ");
- printf(" parent %u intparent %u phandle %x phparent %x\r\n", node->parent, node->intparent,
- node->phandle, node->phparent);
- for(l = 0; l < d; l++) printf(" ");
- printf(" acells %u scells %u icells %u dcells %u ccells %u gcells %u\r\n",
- node->addrcells, node->sizecells, node->intcells, node->dmacells, node->clkcells, node->gpiocells);
- for(j = 0; j < 2; j++)
- if(node->map[j] && node->sizecells) {
- for(l = 0; l < d; l++) printf(" ");
- printf(" map[%u] offs %08x size %3d", j, (uint32_t)((uint8_t*)node->map[j] - ptr), node->mapsz[j]);
- l = node->mapsz[j] >> 2;
- for(k = 0; k < l;) {
- printf(" <%lx", fdt_value(&node->map[j][k], node->addrcells)); k += node->addrcells;
- printf(",%lx", fdt_value(&node->map[j][k], fdt_nodes[node->parent].addrcells)); k += fdt_nodes[node->parent].addrcells;
- printf(",%lx>", fdt_value(&node->map[j][k], node->sizecells)); k += node->sizecells;
- }
- printf("\r\n");
- }
- #endif
- d++;
- break;
- case 2: d--; break;
- case 3:
- sz = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- i = p[3] | (p[2] << 8) | (p[1] << 16); p += 4;
- t = p; p = (uint8_t*)(((uintptr_t)p + sz + 3) & ~3);
- s = ptr + off_str + i;
- if(i < siz_str - 1) {
- #if AML_DEBUG+0 > 1
- for(i = 0; i < d; i++) printf(" ");
- printf(" prop offs %08x size %3d %s", (uint32_t)(t - ptr), sz, (char*)s);
- if(sz) { printf(" <"); for(i = 0; i < sz; i++) { printf("%s%02x", i ? "," : "", t[i]); } printf(">"); }
- printf("\r\n");
- #endif
- /* filter out all properties that we have already parsed */
- if(memcmp(s, "#address-cells", 15) && memcmp(s, "#size-cells", 12) && memcmp(s, "#dma-cells", 11) &&
- memcmp(s, "#clock-cells", 13) && memcmp(s, "#gpio-cells", 12) &&
- memcmp(s, "model", 6) && memcmp(s, "name", 5) && memcmp(s, "device_type", 12) &&
- memcmp(s, "cpu-release", 11) && memcmp(s + 1, "-cache-", 7) && memcmp(s, "chassis-type", 13) &&
- memcmp(s, "ranges", 7) && memcmp(s, "dma-ranges", 11) && memcmp(s, "compatible", 11) &&
- memcmp(s, "#interrupt-cells", 17) && memcmp(s, "interrupt-parent", 17) &&
- memcmp(s, "phandle", 8) && memcmp(s, "linux,phandle", 14) &&
- memcmp(s, "status", 7) && node->name && *node->name && node->drv && *node->drv &&
- memcmp(node->name, "aliases", 8) && memcmp(node->name, "chosen", 7) &&
- memcmp(node->name, "__symbols__", 12) && memcmp(node->name, "__overrides__", 14))
- fdt_prop((char*)s, t, sz, node);
- }
- break;
- }
- }
- #ifdef AML_DEBUG
- stkmax = AML_MAXLEVEL * sizeof(fdt_ctx_t) + 16 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 5 * sizeof(void*) +
- fdt_numnodes * sizeof(fdt_t) + /* functions calls */64;
- #endif
- }
- /* type field */
- 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,
- GUDT_BUTTONS, GUDT_T_AMPER, GUDT_T_VOLT, GUDT_T_THERMAL, GUDT_T_FREQ, GUDT_T_L0CACHE, GUDT_T_L1CACHE, GUDT_T_L2CACHE,
- GUDT_T_L3CACHE, /* unassigned */
- GUDT_T_EDID = 0xd7, GUDT_T_FBPTR, GUDT_T_FBDIM, GUDT_T_MODULE, GUDT_T_CMDLINE, GUDT_T_DEFAULT,
- GUDT_T_NVSMEM, GUDT_T_RESVMEM, GUDT_T_RAM,
- /* top 32 entries must match ACPI region space */
- 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,
- GUDT_T_GPIO, GUDT_T_GSB, GUDT_T_PCC };
- /* category field, must match pci.ids class */
- enum { GUDT_C_UNKNOWN, GUDT_T_STORAGE, GUDT_C_NETWORK, GUDT_C_DISPLAY, GUDT_C_MULTIMEDIA, GUDT_C_MEMORY, GUDT_C_BRIDGE,
- GUDT_C_COMM, GUDT_C_GENERIC, GUDT_C_INPUT, GUDT_C_DOCK, GUDT_C_PROCESSOR, GUDT_C_SERIAL, GUDT_C_WIRELESS, GUDT_C_INTELLIGENT,
- GUDT_C_SATELLITE, GUDT_C_ENCRYPTION, GUDT_C_SIGNAL, GUDT_C_ACCEL, GUDT_C_NONESSENTIAL, GUDT_C_MACHINE = 0xff };
- /* device field but only when category is GUDT_C_MACHINE, must match ACPI PM Profiles */
- enum { GUDT_D_UNSPECIFIED, GUDT_D_DESKTOP, GUDT_D_MOBILE, GUDT_D_WORKSTATION, GUDT_D_ENTERPRISE, GUDT_D_SOHO, GUDT_D_APPLIANCE,
- GUDT_D_PERFORMANCE, GUDT_D_TABLET };
- /* stored in flags */
- #define GUDT_F_UNIT(x) (1<<((x)&15))
- #define GUDT_F_DATA(x) (((x)>>4)&15)
- #define GUDT_F_INDIRECT 0x0f
- /* device node */
- typedef struct {
- uint8_t type; /* must be 0, GUDT_T_DEVICE */
- uint8_t category; /* PCI device class, GUDT_C_x */
- uint16_t parent; /* parent node */
- uint16_t driver; /* string table offset, device driver name */
- uint16_t alternative; /* string table offset, alternative driver name */
- uint16_t name; /* string table offset, device's unique name */
- uint16_t device; /* PCI device sub-class (or GUDT_D_x) */
- uint16_t vendor; /* PCI vendor code */
- uint16_t model; /* PCI device code */
- } __attribute__((packed)) gudt_device_t;
- /* resource node */
- typedef struct {
- uint8_t type; /* must not be 0, any other GUDT_T_x */
- uint8_t flags; /* bit 0..3: resource's unit size */
- uint16_t parent; /* parent node */
- union { /* resource descriptor */
- /* flags bit 4..7: 0 */
- struct { uint32_t size; uint64_t base; } __attribute__((packed)) p;
- /* flags bit 4..7: num items */
- struct { uint8_t data[12]; } __attribute__((packed)) b;
- struct { uint16_t data[6]; } __attribute__((packed)) w;
- struct { uint32_t data[3]; } __attribute__((packed)) d;
- struct { uint32_t pad; uint64_t data[1]; } __attribute__((packed)) q;
- } __attribute__((packed)) r;
- } __attribute__((packed)) gudt_node_t;
- typedef struct { uint32_t b, c, t; uint8_t *s, *d; uint16_t e[16], f[288], g[16], h[288]; } gudt_z_t;
- static void gudt_bt(uint16_t *t, uint16_t *r, const uint8_t *l, uint32_t n) {
- 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]]++;
- 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; }
- 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; }
- static uint32_t gudt_rb(gudt_z_t *d, uint32_t n, uint32_t b) {
- 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; }
- static int gudt_ds(gudt_z_t *d, uint16_t *t, uint16_t *r) {
- 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]; }
- int gudt_unpack(const gudt_hdr_t *src, gudt_hdr_t *dst)
- {
- uint32_t i, l, size, siz, x, y, z;
- 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,
- 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};
- 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};
- int r = 2, s, t = -1, f = 0, o = 0;
- gudt_z_t d = { 0 };
- if(!src || !dst || src->magic[0] != 'G' || src->magic[1] != 'U' || src->magic[2] != 'D') return 0;
- size = (((((uint8_t*)src)[4] | (((uint8_t*)src)[5] << 8)) + 7) & ~7) + ((((uint8_t*)src)[6] | (((uint8_t*)src)[7] << 8)) << 4);
- if(((uint8_t*)src)[8] == 0x78 && ((uint8_t*)src)[9] == 0xDA) {
- for(i = r = 0; i < 8; i++) strs[i] = ((uint8_t*)src)[i];
- d.s = (uint8_t*)src + 10; d.d = strs + 8; siz = size;
- do {
- do {
- if(t == -1) {
- again: f = gudt_gb(&d);
- t = gudt_rb(&d, 2, 0);
- switch(t) {
- case 1:
- for(i = 0; i < 7; i++) d.e[i] = 0;
- d.e[7] = 24; d.e[8] = 152; d.e[9] = 112;
- for(i = 0; i < 24; i++) d.f[i] = 256 + i;
- for(i = 0; i < 144; i++) d.f[24 + i] = i;
- for(i = 0; i < 8; i++) d.f[24 + 144 + i] = 280 + i;
- for(i = 0; i < 112; i++) d.f[24 + 144 + 8 + i] = 144 + i;
- for(i = 0; i < 5; i++) d.g[i] = 0;
- for(i = 0, d.g[5] = 32; i < 32; i++) d.h[i] = i;
- break;
- case 2:
- x = gudt_rb(&d, 5, 257); y = gudt_rb(&d, 5, 1); z = gudt_rb(&d, 4, 4);
- for(i = 0; i < 19; i++) k[i] = 0;
- for(i = 0; i < z; i++) k[c[i]] = gudt_rb(&d, 3, 0);
- gudt_bt(d.e, d.f, k, 19);
- for(i = 0; i < x + y;)
- switch((s = gudt_ds(&d, d.e, d.f))) {
- case 16: for(p = k[i - 1], l = gudt_rb(&d, 2, 3); l; l--) k[i++] = p; break;
- case 17: for(l = gudt_rb(&d, 3, 3); l; l--) k[i++] = 0; break;
- case 18: for(l = gudt_rb(&d, 7, 11); l; l--) k[i++] = 0; break;
- default: k[i++] = s; break;
- }
- gudt_bt(d.e, d.f, k, x); gudt_bt(d.g, d.h, k + x, y);
- break;
- }
- }
- switch(t) {
- case 0:
- if(!d.c) { d.c = 1 + (d.s[0] | (d.s[1] << 8)); d.s += 4; d.b = 0; }
- if(!--d.c) r = 1; else { *d.d++ = *d.s++; r = 0; }
- break;
- case 1: case 2:
- if(!d.c) {
- s = gudt_ds(&d, d.e, d.f);
- if(s < 256) { *d.d++ = s; r = 0; break; } else if(s == 256) { r = 1; break; }
- s -= 257; d.c = gudt_rb(&d, s < 4 ? 0 : ((s - 4) >> 2), m[s]);
- r = gudt_ds(&d, d.g, d.h); o = -gudt_rb(&d, r < 2 ? 0 : ((r - 2) >> 1), n[r]);
- }
- d.d[0] = d.d[o]; d.d++; d.c--; r = 0;
- break;
- default: return 0;
- }
- if(r == 1 && !f) goto again;
- if(r) break;
- } while(--siz);
- } while(!r);
- }
- return r;
- }
- /**
- * GUDT bájtkód értelmezése
- */
- static void gudt(uint8_t *ptr)
- {
- gudt_hdr_t *hdr;
- gudt_device_t *dev;
- gudt_node_t *nodes;
- uint32_t i, j, l, t;
- switch(gudt_unpack((gudt_hdr_t*)ptr, (gudt_hdr_t *)aml.node)) {
- case 0: return;
- case 1: ptr = (uint8_t*)aml.node; break;
- case 2: /* nincs dolgunk */ break;
- }
- hdr = (gudt_hdr_t*)ptr;
- nodes = (gudt_node_t*)((uint8_t*)hdr + ((hdr->hdrsize + 7) & ~7));
- for(i = 0; i < hdr->numnodes; i++)
- if(nodes[i].parent < hdr->numnodes && nodes[nodes[i].parent].type == GUDT_T_DEVICE) {
- if(nodes[i].type >= GUDT_T_NVSMEM && nodes[i].type < GUDT_T_MMIO) {
- HWDET_RESVMEM(nodes[i].r.p.base, nodes[i].r.p.size);
- } else if(nodes[i].type != GUDT_T_RAM && nodes[i].type != GUDT_T_DEVICE) {
- dev = (gudt_device_t*)&nodes[nodes[i].parent];
- switch(nodes[i].type) {
- case GUDT_T_CPUCORE: t = HWDET_CPU; break;
- case GUDT_T_IOPORT: t = HWDET_IO; break;
- case GUDT_T_IRQ: t = HWDET_IRQ; break;
- case GUDT_T_DMA: t = HWDET_DMA; break;
- case GUDT_T_MMIO: t = HWDET_MMIO; HWDET_RESVMEM(nodes[i].r.p.base, nodes[i].r.p.size); break;
- case GUDT_T_PCI: t = HWDET_PCI; break;
- case GUDT_T_EC: t = HWDET_EC; break;
- case GUDT_T_SMB: t = HWDET_SMB; break;
- case GUDT_T_NVRAM: t = HWDET_CMOS; break;
- default: t = HWDET_NONE; break;
- }
- l = GUDT_F_DATA(nodes[i].flags);
- if(l) {
- if(t == HWDET_IRQ && GUDT_F_UNIT(nodes[i].flags) == 1)
- for(j = 0; j < l; j++)
- HWDET_RESOURCE(dev->name ? (char*)ptr + dev->name : "", dev->driver ? (char*)ptr + dev->driver : "",
- dev->alternative ? (char*)ptr + dev->alternative : "", t, nodes[i].r.b.data[j], 0);
- } else
- HWDET_RESOURCE(dev->name ? (char*)ptr + dev->name : "", dev->driver ? (char*)ptr + dev->driver : "",
- dev->alternative ? (char*)ptr + dev->alternative : "", t, nodes[i].r.p.base, nodes[i].r.p.size);
- }
- }
- }
- /**
- * A fő publikus API
- */
- void hwdet(int num, uint8_t **ds)
- {
- uint64_t lapic;
- uint8_t *p, *e;
- int i, n;
- n = aml_numnodes(num, (acpi_t**)ds);
- if(n > 0) {
- aml.node = __builtin_alloca(n * sizeof(aml_t));
- memset(aml.node, 0, n * sizeof(aml_t));
- for(i = 0; i < num; i++)
- if(ds[i]) {
- if((ds[i][0] == 'D' || ds[i][0] == 'S') && !memcmp(ds[i] + 1, "SDT", 3) && ((acpi_t*)ds[i])->size) {
- if(ds[i][36] == 0xD0 && ds[i][37] == 0x0D && ds[i][38] == 0xFE && ds[i][39] == 0xED) fdt_dtb(ds[i] + 36); else
- if(!memcmp(ds[i] + 36, "GUDT", 4)) gudt(ds[i] + 36); else
- aml_TermList((uint8_t*)ds[i] + sizeof(acpi_t), (uint8_t*)ds[i] + ((acpi_t*)ds[i])->size, NULL);
- } else
- if(ds[i][0] == 0xD0 && ds[i][1] == 0x0D && ds[i][2] == 0xFE && ds[i][3] == 0xED) fdt_dtb(ds[i]); else
- if(!memcmp(ds[i] + 36, "APIC", 4)) {
- p = (uint8_t*)ds[i] + sizeof(acpi_t);
- lapic = *((uint32_t*)p);
- for(p += 8, e = (uint8_t*)ds[i] + ((acpi_t*)ds[i])->size; p < e && p[1]; p += p[1])
- switch(*p) {
- case 0: if(p[4]) HWDET_RESOURCE("C000", "CORE", "", HWDET_CPU, 0, p[3]); break;
- case 1:
- HWDET_RESVMEM(*((uint32_t*)(p + 4)), 256);
- HWDET_RESOURCE("IOAPIC", "PNP0C08", "", HWDET_MMIO, *((uint32_t*)(p + 4)), 256);
- HWDET_RESOURCE("IOAPIC", "PNP0C08", "", HWDET_IRQ, *((uint32_t*)(p + 8)), 0);
- break;
- case 5: lapic = *((uint64_t*)(p + 4)); break;
- case 9: if(p[8]) HWDET_RESOURCE("C000", "CORE", "", HWDET_CPU, 0, *((uint32_t*)(p + 12))); break;
- break;
- }
- if(lapic) { HWDET_RESVMEM(lapic, 1024); HWDET_RESOURCE("C000", "PNP0003", "", HWDET_MMIO, lapic, 1024); }
- } else
- if(!memcmp(ds[i] + 36, "GUDT", 4)) gudt(ds[i]);
- #ifdef AML_DEBUG
- else printf("unknown table format, pointer #%d\n", i + 1);
- #endif
- }
- }
- #ifdef AML_DEBUG
- printf("numchk %d/max %d, stackmax %d.\n", numchk, aml.max, stkmax);
- #endif
- }
|