#include <u.h>#include <libc.h>#include <aml.h> typedef struct Interp Interp;typedef struct Frame Frame;typedef struct Heap Heap; typedef struct Method Method;typedef struct Region Region;typedef struct Field Field; typedef struct Name Name;typedef struct Ref Ref;typedef struct Env Env;typedef struct Op Op; struct Heap { Heap *link; int size; uchar mark; char tag;}; #define H2D(h) (((Heap*)(h))+1)#define D2H(d) (((Heap*)(d))-1)#define TAG(d) D2H(d)->tag#define SIZE(d) D2H(d)->size static char *spacename[] = { "Mem", "Io", "Pcicfg", "Ebctl", "Smbus", "Cmos", "Pcibar", "Ipmi",}; /* field flags */enum { AnyAcc = 0x00, ByteAcc = 0x01, WordAcc = 0x02, DWordAcc = 0x03, QWordAcc = 0x04, BufferAcc = 0x05, AccMask = 0x07, NoLock = 0x10, Preserve = 0x00, WriteAsOnes = 0x20, WriteAsZeros = 0x40, UpdateMask = 0x60,}; struct Method { Name *name; int narg; void* (*eval)(void); uchar *start; uchar *end;}; struct Region { Amlio; char mapped;}; struct Field { void *reg; /* Buffer or Region or data Field */ void *bank; /* bank value */ Field *index; /* bank or index Field */ int flags; int bitoff; int bitlen;}; struct Name { void *v; Name *up; Name *next; Name *fork; Name *down; char seg[4];}; struct Ref { void *ref; void **ptr;}; struct Env { void *loc[8]; void *arg[8];}; struct Op { char *name; char *sequence; void* (*eval)(void);}; struct Frame { int tag; int cond; char *phase; uchar *start; uchar *end; Op *op; Env *env; Name *dot; void *ref; void *aux; int narg; void *arg[8];}; struct Interp { uchar *pc; Frame *fp; Frame *fb;}; static Interp interp;static Frame stack[32]; #define PC interp.pc#define FP interp.fp#define FB interp.fb #define F0 stack#define FT &stack[nelem(stack)] static Heap *hp; enum { Obad, Onop, Odebug, Ostr, Obyte, Oword, Odword, Oqword, Oconst, Onamec, Oname, Oscope, Oalias, Oreg, Ofld, Oxfld, Obfld, Opkg, Ovpkg, Oenv, Obuf, Omet, Odev, Ocpu, Othz, Oprc, Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor, Onot, Olbit, Orbit, Oinc, Odec, Oland, Olor, Olnot, Oleq, Olgt, Ollt, Oindex, Omatch, Omutex, Oevent, Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8, Oif, Oelse, Owhile, Obreak, Oret, Ocall, Ostore, Oderef, Ootype, Osize, Oref, Ocref, Ocat, Ocatr, Omid, Oacq, Osignal, Orel, Ostall, Osleep, Otimer, Oload, Ounload, Otobuf, Otodec, Otohex, Otoint, Otostr, Onotify,}; static Op optab[];static uchar octab1[];static uchar octab2[]; static Name*rootname(Name *dot){ while(dot != dot->up) dot = dot->up; return dot;} static voidgcmark(void *p){ int i; Env *e; Field *f; Heap *h; Name *n, *d; if(p == nil) return; h = D2H(p); if(h->mark & 1) return; h->mark |= 1; switch(h->tag){ case 'E': e = p; for(i=0; i<nelem(e->loc); i++) gcmark(e->loc[i]); for(i=0; i<nelem(e->arg); i++) gcmark(e->arg[i]); break; case 'R': case 'A': case 'L': gcmark(((Ref*)p)->ref); break; case 'N': n = p; gcmark(n->v); for(d = n->down; d; d = d->next) gcmark(d); gcmark(n->fork); gcmark(n->up); break; case 'p': for(i=0; i<(SIZE(p)/sizeof(void*)); i++) gcmark(((void**)p)[i]); break; case 'r': gcmark(((Region*)p)->name); break; case 'm': gcmark(((Method*)p)->name); break; case 'f': case 'u': f = p; gcmark(f->reg); gcmark(f->bank); gcmark(f->index); break; }} static intgc(void){ int i; Heap *h, *hn, **hh; Frame *f; for(h = hp; h; h = h->link) h->mark &= ~1; for(h = hp; h; h = h->link) if(h->mark & 2) gcmark(H2D(h)); for(f = FP; f >= F0; f--){ for(i=0; i<f->narg; i++) gcmark(f->arg[i]); gcmark(f->env); gcmark(f->dot); gcmark(f->ref); } gcmark(amlroot); i = 0; hn = nil; hh = &hp; while(h = *hh){ if(h->mark){ hh = &h->link; continue; } *hh = h->link; if(h->tag == 'N'){ ((Name*)H2D(h))->v = nil; /* defer deletion until everything unmapped */ h->link = hn; hn = h; continue; } if(h->tag == 'r'){ Region *r = (void*)H2D(h); if(r->mapped > 0){ if(amldebug) print("\namlunmapio(%N): %-8s %llux - %llux\n", (Name*)r->name, spacename[r->space], r->off, r->off + r->len); amlunmapio(r); } r->mapped = 0; r->write = nil; r->read = nil; r->aux = nil; r->va = nil; } memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } while(h = hn){ hn = h->link; memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } return i;} static void*mk(int tag, int size){ Heap *h; int a; a = sizeof(Heap) + size; assert(a >= sizeof(Heap)); h = amlalloc(a); h->size = size; h->tag = tag; h->link = hp; hp = h; return h+1;} static uvlong*mki(uvlong i){ uvlong *v; v = mk('i', sizeof(uvlong)); *v = i & amlintmask; return v;} static char*mks(char *s){ char *r = mk('s', strlen(s)+1); strcpy(r, s); return r;} static intpkglen(uchar *p, uchar *e, uchar **np){ ulong n; uchar b; if(p >= e) return -1; b = *p++; if(b <= 0x3F) n = b; else { n = b & 0xF; if(p >= e) return -1; n += *p++ << 4; if(b >= 0x80){ if(p >= e) return -1; n += *p++ << 12; } if(b >= 0xC0){ if(p >= e) return -1; n += *p++ << 20; } } if(np) *np = p; return n;} static Name*forkname(Name *dot){ Name *n; n = mk('N', sizeof(Name)); *n = *dot; n->fork = dot; n->next = n->down = nil; if(dot->v == dot) n->v = n; if(dot->up == dot) n->up = n; else { if(n->up = forkname(dot->up)) n->up->down = n; } return n;} static Name*getseg(Name *dot, void *seg, int new){ Name *n, *l; for(n = l = nil; dot; dot = dot->fork){ for(n = dot->down; n; n = n->next){ if(memcmp(seg, n->seg, 4) == 0) return n; l = n; } if(new){ n = mk('N', sizeof(Name)); memmove(n->seg, seg, sizeof(n->seg)); n->up = dot; if(l == nil) dot->down = n; else l->next = n; n->v = n; break; } } return n;} Name*getname(Name *dot, char *path, int new){ char seg[4]; int i, s; Name *x; if(dot == nil) return nil; s = !new; if(*path == '\\'){ path++; dot = rootname(dot); s = 0; } while(*path == '^'){ path++; dot = dot->up; s = 0; } do { for(i=0; i<4; i++){ if(*path == 0 || *path == '.') break; seg[i] = *path++; } if(i == 0) break; while(i < 4) seg[i++] = '_'; if(s && *path == 0){ for(;;){ if(x = getseg(dot, seg, 0)) break; if(dot == dot->up) break; dot = dot->up; } return x; } s = 0; dot = getseg(dot, seg, new); } while(*path++ == '.'); return dot;} static intfixnames(void *dot, void *arg){ void **r, *v; int i; if(arg == nil) r = &((Name*)dot)->v; else r = arg; v = *r; if(v == nil || v == dot) return 0; if(TAG(v) == 'p'){ r = (void**)v; for(i=0; i<(SIZE(r)/sizeof(void*)); i++) fixnames(dot, r+i); return 0; } if(TAG(v) == 'n' && (v = getname(dot, v, 0)) != nil) *r = v; return 0;} static uvlonggetle(uchar *p, int len){ uvlong v; int i; v = 0ULL; for(i=0; i<len; i++) v |= ((uvlong)p[i]) << i*8; return v;} static voidputle(uchar *p, int len, uvlong v){ int i; for(i=0; i<len; i++){ p[i] = v; v >>= 8;Lines 1–500 of 2600. Load more
#include <u.h> #include <libc.h> #include <aml.h> typedef struct Interp Interp; typedef struct Frame Frame; typedef struct Heap Heap; typedef struct Method Method; typedef struct Region Region; typedef struct Field Field; typedef struct Name Name; typedef struct Ref Ref; typedef struct Env Env; typedef struct Op Op; struct Heap { Heap *link; int size; uchar mark; char tag; }; #define H2D(h) (((Heap*)(h))+1) #define D2H(d) (((Heap*)(d))-1) #define TAG(d) D2H(d)->tag #define SIZE(d) D2H(d)->size static char *spacename[] = { "Mem", "Io", "Pcicfg", "Ebctl", "Smbus", "Cmos", "Pcibar", "Ipmi", }; /* field flags */ enum { AnyAcc = 0x00, ByteAcc = 0x01, WordAcc = 0x02, DWordAcc = 0x03, QWordAcc = 0x04, BufferAcc = 0x05, AccMask = 0x07, NoLock = 0x10, Preserve = 0x00, WriteAsOnes = 0x20, WriteAsZeros = 0x40, UpdateMask = 0x60, }; struct Method { Name *name; int narg; void* (*eval)(void); uchar *start; uchar *end; }; struct Region { Amlio; char mapped; }; struct Field { void *reg; /* Buffer or Region or data Field */ void *bank; /* bank value */ Field *index; /* bank or index Field */ int flags; int bitoff; int bitlen; }; struct Name { void *v; Name *up; Name *next; Name *fork; Name *down; char seg[4]; }; struct Ref { void *ref; void **ptr; }; struct Env { void *loc[8]; void *arg[8]; }; struct Op { char *name; char *sequence; void* (*eval)(void); }; struct Frame { int tag; int cond; char *phase; uchar *start; uchar *end; Op *op; Env *env; Name *dot; void *ref; void *aux; int narg; void *arg[8]; }; struct Interp { uchar *pc; Frame *fp; Frame *fb; }; static Interp interp; static Frame stack[32]; #define PC interp.pc #define FP interp.fp #define FB interp.fb #define F0 stack #define FT &stack[nelem(stack)] static Heap *hp; enum { Obad, Onop, Odebug, Ostr, Obyte, Oword, Odword, Oqword, Oconst, Onamec, Oname, Oscope, Oalias, Oreg, Ofld, Oxfld, Obfld, Opkg, Ovpkg, Oenv, Obuf, Omet, Odev, Ocpu, Othz, Oprc, Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor, Onot, Olbit, Orbit, Oinc, Odec, Oland, Olor, Olnot, Oleq, Olgt, Ollt, Oindex, Omatch, Omutex, Oevent, Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8, Oif, Oelse, Owhile, Obreak, Oret, Ocall, Ostore, Oderef, Ootype, Osize, Oref, Ocref, Ocat, Ocatr, Omid, Oacq, Osignal, Orel, Ostall, Osleep, Otimer, Oload, Ounload, Otobuf, Otodec, Otohex, Otoint, Otostr, Onotify, }; static Op optab[]; static uchar octab1[]; static uchar octab2[]; static Name* rootname(Name *dot) { while(dot != dot->up) dot = dot->up; return dot; } static void gcmark(void *p) { int i; Env *e; Field *f; Heap *h; Name *n, *d; if(p == nil) return; h = D2H(p); if(h->mark & 1) return; h->mark |= 1; switch(h->tag){ case 'E': e = p; for(i=0; i<nelem(e->loc); i++) gcmark(e->loc[i]); for(i=0; i<nelem(e->arg); i++) gcmark(e->arg[i]); break; case 'R': case 'A': case 'L': gcmark(((Ref*)p)->ref); break; case 'N': n = p; gcmark(n->v); for(d = n->down; d; d = d->next) gcmark(d); gcmark(n->fork); gcmark(n->up); break; case 'p': for(i=0; i<(SIZE(p)/sizeof(void*)); i++) gcmark(((void**)p)[i]); break; case 'r': gcmark(((Region*)p)->name); break; case 'm': gcmark(((Method*)p)->name); break; case 'f': case 'u': f = p; gcmark(f->reg); gcmark(f->bank); gcmark(f->index); break; } } static int gc(void) { int i; Heap *h, *hn, **hh; Frame *f; for(h = hp; h; h = h->link) h->mark &= ~1; for(h = hp; h; h = h->link) if(h->mark & 2) gcmark(H2D(h)); for(f = FP; f >= F0; f--){ for(i=0; i<f->narg; i++) gcmark(f->arg[i]); gcmark(f->env); gcmark(f->dot); gcmark(f->ref); } gcmark(amlroot); i = 0; hn = nil; hh = &hp; while(h = *hh){ if(h->mark){ hh = &h->link; continue; } *hh = h->link; if(h->tag == 'N'){ ((Name*)H2D(h))->v = nil; /* defer deletion until everything unmapped */ h->link = hn; hn = h; continue; } if(h->tag == 'r'){ Region *r = (void*)H2D(h); if(r->mapped > 0){ if(amldebug) print("\namlunmapio(%N): %-8s %llux - %llux\n", (Name*)r->name, spacename[r->space], r->off, r->off + r->len); amlunmapio(r); } r->mapped = 0; r->write = nil; r->read = nil; r->aux = nil; r->va = nil; } memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } while(h = hn){ hn = h->link; memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } return i; } static void* mk(int tag, int size) { Heap *h; int a; a = sizeof(Heap) + size; assert(a >= sizeof(Heap)); h = amlalloc(a); h->size = size; h->tag = tag; h->link = hp; hp = h; return h+1; } static uvlong* mki(uvlong i) { uvlong *v; v = mk('i', sizeof(uvlong)); *v = i & amlintmask; return v; } static char* mks(char *s) { char *r = mk('s', strlen(s)+1); strcpy(r, s); return r; } static int pkglen(uchar *p, uchar *e, uchar **np) { ulong n; uchar b; if(p >= e) return -1; b = *p++; if(b <= 0x3F) n = b; else { n = b & 0xF; if(p >= e) return -1; n += *p++ << 4; if(b >= 0x80){ if(p >= e) return -1; n += *p++ << 12; } if(b >= 0xC0){ if(p >= e) return -1; n += *p++ << 20; } } if(np) *np = p; return n; } static Name* forkname(Name *dot) { Name *n; n = mk('N', sizeof(Name)); *n = *dot; n->fork = dot; n->next = n->down = nil; if(dot->v == dot) n->v = n; if(dot->up == dot) n->up = n; else { if(n->up = forkname(dot->up)) n->up->down = n; } return n; } static Name* getseg(Name *dot, void *seg, int new) { Name *n, *l; for(n = l = nil; dot; dot = dot->fork){ for(n = dot->down; n; n = n->next){ if(memcmp(seg, n->seg, 4) == 0) return n; l = n; } if(new){ n = mk('N', sizeof(Name)); memmove(n->seg, seg, sizeof(n->seg)); n->up = dot; if(l == nil) dot->down = n; else l->next = n; n->v = n; break; } } return n; } Name* getname(Name *dot, char *path, int new) { char seg[4]; int i, s; Name *x; if(dot == nil) return nil; s = !new; if(*path == '\\'){ path++; dot = rootname(dot); s = 0; } while(*path == '^'){ path++; dot = dot->up; s = 0; } do { for(i=0; i<4; i++){ if(*path == 0 || *path == '.') break; seg[i] = *path++; } if(i == 0) break; while(i < 4) seg[i++] = '_'; if(s && *path == 0){ for(;;){ if(x = getseg(dot, seg, 0)) break; if(dot == dot->up) break; dot = dot->up; } return x; } s = 0; dot = getseg(dot, seg, new); } while(*path++ == '.'); return dot; } static int fixnames(void *dot, void *arg) { void **r, *v; int i; if(arg == nil) r = &((Name*)dot)->v; else r = arg; v = *r; if(v == nil || v == dot) return 0; if(TAG(v) == 'p'){ r = (void**)v; for(i=0; i<(SIZE(r)/sizeof(void*)); i++) fixnames(dot, r+i); return 0; } if(TAG(v) == 'n' && (v = getname(dot, v, 0)) != nil) *r = v; return 0; } static uvlong getle(uchar *p, int len) { uvlong v; int i; v = 0ULL; for(i=0; i<len; i++) v |= ((uvlong)p[i]) << i*8; return v; } static void putle(uchar *p, int len, uvlong v) { int i; for(i=0; i<len; i++){ p[i] = v; v >>= 8;