big update from cinap interface: - default implementations of amlalloc, amlfree - new function amldelay, and default nil implementation - new functions ioalloc, iofree to allow for access to the generic address structures - new functions amltake/amldrop to inhibit/enable garbage collection. - recursive method evaluation internal: - evaluate osi method (default windows) - evaluate undefined names (fixnames) - remove Package def'n, which had been internal to the library. - new instructions Olbit, Orbit local changes: - man page updates - use (get|put)le. NB: these have a different argument order than cinap's version. Reference: /n/atom/patch/applied2013/amlupdate Date: Fri Sep 20 04:39:31 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/man/2/aml Fri Sep 20 04:33:38 2013 +++ /sys/man/2/aml Fri Sep 20 04:33:39 2013 @@ -11,6 +11,30 @@ #include #include .PB +enum { + MemSpace = 0, + IoSpace = 1, + PcicfgSpace = 2, + EbctlSpace = 3, + SmbusSpace = 4, + CmosSpace = 5, + PcibarSpace = 6, + IpmiSpace = 7, +}; +.PB +typedef struct Amlio Amlio; +struct Amlio { + int space; + uvlong off; + uvlong len; + void* name; + uchar* a; + + void *aux; + int (*read)(Amlio *io, void *data, int len, int off); + int (*write)(Amlio *io, void *data, int len, int off); +}; +.PB .PD 0 .ta +\w'\fL 'u +\w'\fL 'u +6n +4n int amltag(void *p) @@ -21,22 +45,34 @@ .PB int amllen(void *p) .PB +void amlnew(char type, int size) +.PB +void amltake(void *p) +.PB +void amldrop(void *p) +.PB void amlinit(void) .PB void amlexit(void) .PB -int amlload(uchar *data, int len); +int amlload(uchar *data, int len) .PB -void* amlwalk(void *dot, char *name); +void* amlwalk(void *dot, char *name) .PB -int amleval(void *dot, char *fmt, ...); +int amleval(void *dot, char *fmt, ...) .PB void amlenum(void *dot, char *seg, - int (*proc)(void *, void *), void *arg); + int (*proc)(void *, void *), void *arg) +.PB +void* amlalloc(usize) +.PB +void amlfree(void*) +.PB +void amldelay(int microsec) .PB -void* amlalloc(usize); +int amlmapio(Amlio *io) .PB -void amlfree(void*); +void amlunmapio(Amlio *io) .SH DESCRIPTION .I Aml implements an interpreter for the ACPI machine language, AML. @@ -58,6 +94,7 @@ tag type name b uchar* buffer s char* string +n char* undefined name i uvlong* integer p void** package r void* region @@ -69,8 +106,8 @@ .PP .TP .BI amlload(data ,\ len\f5) -Start the interperter with the given AML code. For userspace, kernel -provides +Start the interperter with the given AML code. For userspace, +the kernel provides .BR #P/acpitbls . .TP .B amlexit() @@ -110,6 +147,18 @@ Return the number of elements in .IR p . .TP +.BI amlnew( type ,\ size ) +Create a new aml object of the given +.I size +and +.IR type . +.TP +.IR amltake( p ) +Exclude object from garbage collection. +.TP +.IR amldrop ( p ) +Include previously excluded object in garbage collection. +.TP .BI amlwalk( dot ,\ name ) Walk the aml heirarchy to .I name @@ -127,7 +176,17 @@ .IR procfn ( arg ) for each matching object under .IR dot . +.TP +.BI amldelay( microsec ) +Delay for the given number of microseconds. +.TP +.BI amlmapio( io ) +Map the given region, and set function pointers for reading and +writing. +.TP +.BI amlunmapio( io ) +Discard the previously mapped region. .SH "SEE ALSO" -.CW http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf +.L http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf .SH BUGS A 32-bit little-endian machine is assumed. --- /sys/include/aml.h Fri Sep 20 04:33:41 2013 +++ /sys/include/aml.h Fri Sep 20 04:33:43 2013 @@ -4,6 +4,7 @@ /* * b uchar* buffer amllen() returns number of bytes * s char* string amllen() is strlen() + * n char* undefined name amllen() is strlen() * i u64int* integer * p void** package amllen() is # of elements * r void* region @@ -16,6 +17,7 @@ void* amlval(void*); uvlong amlint(void*); int amllen(void*); +void* amlnew(char, int); void amlinit(void); void amlexit(void); @@ -25,6 +27,12 @@ int amleval(void *dot, char *fmt, ...); void amlenum(void *dot, char *seg, int (*proc)(void *, void *), void *arg); +/* + * exclude from garbage collection + */ +void amltake(void *); +void amldrop(void *); + extern void* amlroot; extern int amldebug; @@ -34,3 +42,33 @@ /* to be provided by operating system */ extern void* amlalloc(usize); extern void amlfree(void*); + +extern void amldelay(int); /* microseconds */ + +enum { + MemSpace = 0x00, + IoSpace = 0x01, + PcicfgSpace = 0x02, + EbctlSpace = 0x03, + SmbusSpace = 0x04, + CmosSpace = 0x05, + PcibarSpace = 0x06, + IpmiSpace = 0x07, +}; + +typedef struct Amlio Amlio; +struct Amlio +{ + int space; + uvlong off; + uvlong len; + void *name; + uchar *va; + + void *aux; + int (*read)(Amlio *io, void *data, int len, int off); + int (*write)(Amlio *io, void *data, int len, int off); +}; + +extern int amlmapio(Amlio *io); +extern void amlunmapio(Amlio *io); --- /sys/src/libaml/aml.c Fri Sep 20 04:33:48 2013 +++ /sys/src/libaml/aml.c Fri Sep 20 04:33:50 2013 @@ -6,7 +6,6 @@ typedef struct Frame Frame; typedef struct Heap Heap; -typedef struct Package Package; typedef struct Method Method; typedef struct Region Region; typedef struct Field Field; @@ -28,17 +27,6 @@ #define TAG(d) D2H(d)->tag #define SIZE(d) D2H(d)->size -enum { - MemSpace = 0x00, - IoSpace = 0x01, - PcicfgSpace = 0x02, - EbctlSpace = 0x03, - SmbusSpace = 0x04, - CmosSpace = 0x05, - PcibarSpace = 0x06, - IpmiSpace = 0x07, -}; - static char *spacename[] = { "Mem", "Io", @@ -68,11 +56,6 @@ UpdateMask = 0x60, }; -struct Package { - int n; - void *a[]; -}; - struct Method { Name *name; int narg; @@ -82,11 +65,8 @@ }; struct Region { - Name *name; - int space; - uvlong off; - uvlong len; - uchar *va; /* non nil when mapped */ + Amlio; + char mapped; }; struct Field { @@ -164,7 +144,7 @@ Oreg, Ofld, Oxfld, Opkg, Ovpkg, Oenv, Obuf, Omet, Odev, Ocpu, Othz, Oprc, Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor, - Onor, Oxor, Onot, Oinc, Odec, + Onor, Oxor, Onot, Olbit, Orbit, Oinc, Odec, Oland, Olor, Olnot, Oleq, Olgt, Ollt, Oindex, Omutex, Oevent, Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8, @@ -193,14 +173,13 @@ Field *f; Heap *h; Name *n, *d; - Package *a; if(p == nil) return; h = D2H(p); - if(h->mark) + if(h->mark & 1) return; - h->mark = 1; + h->mark |= 1; switch(h->tag){ case 'E': e = p; @@ -223,9 +202,8 @@ gcmark(n->up); break; case 'p': - a = p; - for(i=0; in; i++) - gcmark(a->a[i]); + for(i=0; i<(SIZE(p)/sizeof(void*)); i++) + gcmark(((void**)p)[i]); break; case 'r': gcmark(((Region*)p)->name); @@ -251,7 +229,11 @@ Frame *f; for(h = hp; h; h = h->link) - h->mark = 0; + h->mark &= ~1; + + for(h = hp; h; h = h->link) + if(h->mark & 2) + gcmark(H2D(h)); for(f = FP; f >= FB; f--){ for(i=0; inarg; i++) @@ -273,8 +255,17 @@ *hh = h->link; if(h->tag == 'r'){ Region *r = (void*)H2D(h); - - /* TODO: unmap region */ + 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); @@ -441,47 +432,95 @@ 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 rwreg(void *reg, int off, int len, uvlong v, int write) { + uchar buf[8], *p; Region *r; - uchar *p; - int i; switch(TAG(reg)){ case 'b': p = reg; if((off+len) > SIZE(p)) break; - RWMem: - if(write){ - /* putle(p, v, 8); */ - for(i=0; i>= 8; - } - } else { - /* v |= getle(p, 8); */ - for(i=0; i r->len) break; - if(amldebug){ - print("\nrwreg: %s %-8s [%llux+%x]/%d %llux\n", - write ? "W" : "R", - spacename[r->space], - r->off, off, len, v); + if(r->mapped == 0){ + if(amldebug) + print("\namlmapio(%N): %-8s %llux - %llux\n", + (Name*)r->name, spacename[r->space], + r->off, r->off + r->len); + r->mapped = 1; + if(amlmapio(r) < 0) + r->mapped = -1; } - /* TODO: map region */ - if(r->va != nil){ + if(r->mapped <= 0) + break; + + if(r->va != nil) p = r->va + off; - goto RWMem; + else { + if(len > sizeof(buf)) + break; + p = buf; } - break; + + if(write){ + if(amldebug) + print("\nrwreg(%N): %-8s [%llux+%x]/%d <- %llux\n", + (Name*)r->name, spacename[r->space], + r->off, off, len, v); + putle(p, v, len); + if(r->write != nil){ + if((*r->write)(r, p, len, off) != len) + break; + } else if(p == buf) + break; + } else { + if(r->read != nil){ + if((*r->read)(r, p, len, off) != len) + break; + } else if(p == buf) + break; + v = getle(p, len); + if(amldebug) + print("\nrwreg(%N): %-8s [%llux+%x]/%d -> %llux\n", + (Name*)r->name, spacename[r->space], + r->off, off, len, v); + } + return v; } return ~0; @@ -553,10 +592,7 @@ } else { w = ival(v); b = mk('b', (blen+7)/8); - for(i=0; i>= 8; - } + putle(b, w, SIZE(b)); } } else b = mk('b', (blen+7)/8); @@ -572,10 +608,10 @@ w = 0; for(i = 0; i < wl; i++, boff++) if(b[boff/8] & (1<<(boff%8))) - w |= 1LL< 64) return b; - - w = 0; - for(i=0; i 0) n++; + /* zero length string is converted to zero length buffer */ + if(n > 0) n++; } d = mk(tag, n); memmove(d, s, n); @@ -759,7 +793,6 @@ Field *l; Name *nm; Method *m; - Package *a; Region *g; Ref *r; @@ -781,17 +814,19 @@ return fmtprint(f, "Arg%ld=%V", r->ptr - e->arg, *r->ptr); if(c == 'L') return fmtprint(f, "Local%ld=%V", r->ptr - e->loc, *r->ptr); + case 'n': + return fmtprint(f, "%s", (char*)p); case 's': return fmtprint(f, "\"%s\"", (char*)p); case 'i': return fmtprint(f, "%#llux", *((uvlong*)p)); case 'p': - a = p; - fmtprint(f, "Package(%d){", a->n); - for(i=0; in; i++){ + n = SIZE(p)/sizeof(void*); + fmtprint(f, "Package(%d){", n); + for(i=0; i 0) fmtprint(f, ", "); - fmtprint(f, "%V", a->a[i]); + fmtprint(f, "%V", ((void**)p)[i]); } fmtprint(f, "}"); return 0; @@ -1019,7 +1054,7 @@ } if(FP < FB){ if(pret){ - if(amldebug) print(" => %V\n", r); + if(amldebug) print(" -> %V\n", r); *pret = r; } return 0; @@ -1035,23 +1070,25 @@ static void* evalnamec(void) { - int s, c, new; - Name *x, *dot; + static char name[1024]; + char *d; + void *r; + int c; - dot = FP->dot; - new = FP->tag == 'N'; - s = !new; c = 1; + d = name; PC = FP->start; - if(*PC == '\\'){ - PC++; - dot = rootname(dot); - s = 0; - } + if(*PC == '\\') + *d++ = *PC++; while(*PC == '^'){ - PC++; - dot = dot->up; - s = 0; + if(d >= &name[sizeof(name)-1]){ + Toolong: + *d = 0; + print("aml: name too long: %s\n", name); + PC = FP->end; + return nil; + } + *d++ = *PC++; } if(*PC == '.'){ PC++; @@ -1062,23 +1099,25 @@ } else if(*PC == 0){ PC++; c = 0; - } else if(s){ - for(;;){ - if(x = getseg(dot, PC, 0)) - break; - if(dot == dot->up) - break; - dot = dot->up; - } - PC += 4; - return x; } while(c > 0){ - dot = getseg(dot, PC, new); - PC += 4; - c--; + if(d >= &name[sizeof(name)-5]) + goto Toolong; + *d++ = *PC++; + *d++ = *PC++; + *d++ = *PC++; + *d++ = *PC++; + while((d > &name[0]) && (d[-1] == '_' || d[-1] == 0)) + d--; + if(--c > 0) + *d++ = '.'; + } + *d = 0; + if((r = getname(FP->dot, name, FP->tag == 'N')) == nil){ + r = mks(name); + D2H(r)->tag = 'n'; /* unresolved name */ } - return dot; + return r; } static void* @@ -1118,22 +1157,20 @@ static void* evalpkg(void) { - Package *p; - void **x; + void **p, **x; int n; if((p = FP->ref) != nil){ x = FP->aux; - if(x >= &p->a[0] && x < &p->a[p->n]){ + if(x >= p && x < (p+(SIZE(p)/sizeof(void*)))){ *x++ = FP->arg[0]; FP->aux = x; } }else { n = ival(FP->arg[0]); if(n < 0) n = 0; - p = mk('p', sizeof(Package) + n*sizeof(void*)); - p->n = n; - FP->aux = p->a; + p = mk('p', n*sizeof(void*)); + FP->aux = p; FP->ref = p; } return p; @@ -1180,7 +1217,7 @@ Name *n; Method *m; - if(n = FP->arg[0]){ + if((n = FP->arg[0]) != nil){ m = mk('m', sizeof(Method)); m->narg = ival(FP->arg[1]) & 7; m->start = PC; @@ -1450,7 +1487,7 @@ FP->env = e; FP->narg = 0; FP->dot = m->name; - if(m->eval){ + if(m->eval != nil){ FP->op = nil; FP->end = PC; return (*m->eval)(); @@ -1575,14 +1612,14 @@ store(f, FP->arg[2]); return f; case 'p': - if(x < 0 || x >= ((Package*)p)->n) + if(x < 0 || x >= (SIZE(p)/sizeof(void*))) break; if(TAG(FP->arg[0]) == 'A' || TAG(FP->arg[0]) == 'L') r = mk(TAG(FP->arg[0]), sizeof(Ref)); else r = mk('R', sizeof(Ref)); r->ref = p; - r->ptr = &((Package*)p)->a[x]; + r->ptr = ((void**)p) + x; store(r, FP->arg[2]); return r; } @@ -1611,7 +1648,7 @@ void *p; if(p = FP->arg[0]){ - if(TAG(p) == 's') + if(TAG(p) == 's' || TAG(p) == 'n') p = getname(FP->dot, (char*)p, 0); p = deref(p); } @@ -1623,6 +1660,7 @@ { uvlong v, d; void *r; + int i; r = nil; switch(FP->op - optab){ @@ -1675,6 +1713,22 @@ r = mki(~ival(FP->arg[0])); store(r, FP->arg[1]); return r; + case Olbit: + v = ival(FP->arg[0]); + if(v == 0) + break; + for(i=0; (v & 1) == 0; i++) + v >>= 1; + r = mki(i+1); + break; + case Orbit: + v = ival(FP->arg[0]); + if(v == 0) + break; + for(i=0; v != 0; i++) + v >>= 1; + r = mki(i); + break; case Oland: return mki(ival(FP->arg[0]) && ival(FP->arg[1])); case Olor: @@ -1707,7 +1761,9 @@ tid = nil; if(FP->aux){ if(PC >= FP->end){ +print("PC>=FP->end\n"); PC = FP->aux; /* restore */ +// amlenum(amlroot, nil, fixnames, nil); FP->aux = nil; FP->end = PC; tid = mki(1); /* fake */ @@ -1717,7 +1773,7 @@ if(FP->arg[0] == nil) return nil; - l = rwreg(FP->arg[0], LenOffset, 32, 0, 0); + l = rwreg(FP->arg[0], LenOffset, 4, 0, 0); if(l <= HdrLen) return nil; @@ -1731,9 +1787,8 @@ break; case 'r': r = FP->ref; - if(r->len < l || r->va == nil) + if(r->len < l || r->va == nil || r->mapped <= 0) return nil; - /* assuming rwreg() has mapped the region */ PC = (uchar*)r->va + HdrLen; break; default: @@ -1749,6 +1804,20 @@ return tid; } +static void* +evalstall(void) +{ + amldelay(ival(FP->arg[0])); + return nil; +} + +static void* +evalsleep(void) +{ + amldelay(ival(FP->arg[0])*1000); + return nil; +} + static Op optab[] = { [Obad] "", "", evalbad, [Onop] "Noop", "", evalnop, @@ -1802,6 +1871,9 @@ [Oxor] "Xor", "ii@", evalarith, [Onot] "Not", "i@", evalarith, + [Olbit] "FindSetLeftBit", "i@", evalarith, + [Orbit] "FindSetRightBit", "i@", evalarith, + [Oinc] "Increment", "@", evalarith, [Odec] "Decrement", "@", evalarith, @@ -1833,8 +1905,8 @@ [Oacq] "Acquire", "@2", evalnop, [Orel] "Release", "@", evalnop, - [Ostall] "Stall", "i", evalnop, - [Osleep] "Sleep", "i", evalnop, + [Ostall] "Stall", "i", evalstall, + [Osleep] "Sleep", "i", evalsleep, [Oload] "Load", "*@}", evalload, [Ounload] "Unload", "@", evalnop, }; @@ -1856,7 +1928,7 @@ /* 68 */ Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Obad, /* 70 */ Ostore, Oref, Oadd, Ocat, Osub, Oinc, Odec, Omul, /* 78 */ Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor, -/* 80 */ Onot, Obad, Obad, Oderef, Obad, Omod, Obad, Osize, +/* 80 */ Onot, Olbit, Orbit, Oderef, Obad, Omod, Obad, Osize, /* 88 */ Oindex, Obad, Ocfld4, Ocfld2, Ocfld1, Ocfld0, Obad, Ocfld8, /* 90 */ Oland, Olor, Olnot, Oleq, Olgt, Ollt, Obad, Obad, /* 98 */ Obad, Obad, Obad, Obad, Obad, Obad, Obad, Obad, @@ -1918,10 +1990,7 @@ void* amlval(void *p) { - p = deref(p); - if(p && TAG(p) == 'p') - p = ((Package*)p)->a; - return p; + return deref(p); } uvlong @@ -1938,10 +2007,11 @@ case 'R': p = *((Ref*)p)->ptr; continue; + case 'n': case 's': return strlen((char*)p); case 'p': - return ((Package*)p)->n; + return SIZE(p)/sizeof(void*); default: return SIZE(p); } @@ -1949,6 +2019,43 @@ return 0; } +void* +amlnew(char tag, int len) +{ + switch(tag){ + case 'i': + return mki(0); + case 'n': + case 's': + return mk(tag, len + 1); + case 'p': + return mk(tag, len * sizeof(void*)); + default: + return mk(tag, len); + } +} + +static void* +evalosi(void) +{ + static char *w[] = { + "Windows 2001", + "Windows 2001 SP1", + "Windows 2001 SP2", + "Windows 2006", + }; + char *s; + int i; + + s = FP->env->arg[0]; + if(s == nil || TAG(s) != 's') + return nil; + for(i = 0; i < nelem(w); i++) + if(strcmp(s, w[i]) == 0) + return mki(0xFFFFFFFF); + return nil; +} + void amlinit(void) { @@ -1978,7 +2085,7 @@ m = mk('m', sizeof(Method)); m->narg = 1; - m->eval = evalnop; + m->eval = evalosi; m->name = n; n->v = m; } @@ -1995,7 +2102,11 @@ int amlload(uchar *data, int len) { - return xec(data, data+len, amlroot, nil, nil); + int ret; + + ret = xec(data, data+len, amlroot, nil, nil); + amlenum(amlroot, nil, fixnames, nil); + return ret; } void* @@ -2033,9 +2144,11 @@ int i; va_start(a, fmt); - e = *fmt != 0? mk('E', sizeof(Env)): nil; + e = mk('E', sizeof(Env)); for(i=0;*fmt;fmt++){ switch(*fmt){ + default: + return -1; case 's': e->arg[i++] = mks(va_arg(a, char*)); break; @@ -2045,6 +2158,12 @@ case 'I': e->arg[i++] = mki(va_arg(a, uvlong)); break; + case 'b': + case 'p': + case '*': + print("amleval %c\n", *fmt); + e->arg[i++] = va_arg(a, void*); + break; } } r = va_arg(a, void**); @@ -2054,9 +2173,31 @@ m = dot; if(i != m->narg) return -1; - return xec(m->start, m->end, forkname(m->name), e, r); + if(m->eval == nil) + return xec(m->start, m->end, forkname(m->name), e, r); + FP = FB; + FP->op = nil; + FP->env = e; + FP->narg = 0; + FP->dot = m->name; + FP->ref = FP->aux = nil; + dot = (*m->eval)(); } if(r != nil) *r = dot; return 0; +} + +void +amltake(void *p) +{ + if(p != nil) + D2H(p)->mark |= 2; +} + +void +amldrop(void *p) +{ + if(p != nil) + D2H(p)->mark &= ~2; } --- /sys/src/libaml/amlalloc.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libaml/amlalloc.c Fri Sep 20 04:33:51 2013 @@ -0,0 +1,15 @@ +#include +#include +#include + +void* +amlalloc(usize n) +{ + return mallocz(n, 1); +} + +void +amlfree(void *p) +{ + free(p); +} --- /sys/src/libaml/amldelay.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libaml/amldelay.c Fri Sep 20 04:33:52 2013 @@ -0,0 +1,8 @@ +#include +#include +#include + +void +amldelay(int) +{ +} --- /sys/src/libaml/amlmapio.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libaml/amlmapio.c Fri Sep 20 04:33:53 2013 @@ -0,0 +1,10 @@ +#include +#include +#include + +int +amlmapio(Amlio*) +{ + print("aml: mapio\n"); + return -1; +} --- /sys/src/libaml/amlunmapio.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libaml/amlunmapio.c Fri Sep 20 04:33:54 2013 @@ -0,0 +1,8 @@ +#include +#include +#include + +void +amlunmapio(Amlio*) +{ +} --- /sys/src/libaml/mkfile Fri Sep 20 04:33:57 2013 +++ /sys/src/libaml/mkfile Fri Sep 20 04:33:58 2013 @@ -3,6 +3,10 @@ LIB=/$objtype/lib/libaml.a OFILES=\ aml.$O\ + amlmapio.$O\ + amlunmapio.$O\ + amlalloc.$O\ + amldelay.$O\ HFILES=/sys/include/aml.h