amlopex.c 245 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. amlopex.c
  9. Abstract:
  10. This module implements ACPI AML low level opcode support for executing
  11. AML statements.
  12. Author:
  13. Evan Green 13-Nov-2012
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/driver.h>
  21. #include "acpip.h"
  22. #include "amlos.h"
  23. #include "amlops.h"
  24. #include "namespce.h"
  25. #include "oprgn.h"
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. #define ACPI_RESOURCE_END_TAG 0x79
  30. //
  31. // Define the longest string that can be created from converting a decimal
  32. // integer to a string.
  33. //
  34. #define MAX_DECIMAL_STRING_LENGTH 22
  35. //
  36. // Define the portion of the mutex sync flags that represent the sync level.
  37. //
  38. #define MUTEX_FLAG_SYNC_LEVEL_MASK 0xF
  39. //
  40. // Define the bitfields of the method flags byte.
  41. //
  42. #define METHOD_ARGUMENT_COUNT_MASK 0x7
  43. #define METHOD_SERIALIZED_FLAG 0x08
  44. #define METHOD_SYNC_LEVEL_SHIFT 4
  45. #define METHOD_SYNC_LEVEL_MASK (0xF << METHOD_SYNC_LEVEL_SHIFT)
  46. //
  47. // ------------------------------------------------------ Data Type Definitions
  48. //
  49. typedef enum _ACPI_MATCH_OPERATOR {
  50. MatchOperatorTrue = 0,
  51. MatchOperatorEqual = 1,
  52. MatchOperatorLessThanOrEqualTo = 2,
  53. MatchOperatorLessThan = 3,
  54. MatchOperatorGreaterThanOrEqualTo = 4,
  55. MatchOperatorGreaterThan = 5,
  56. MatchOperatorCount
  57. } ACPI_MATCH_OPERATOR, *PACPI_MATCH_OPERATOR;
  58. //
  59. // ----------------------------------------------- Internal Function Prototypes
  60. //
  61. PACPI_OBJECT
  62. AcpipConvertObjectTypeToInteger (
  63. PAML_EXECUTION_CONTEXT Context,
  64. PACPI_OBJECT Object
  65. );
  66. PACPI_OBJECT
  67. AcpipConvertObjectTypeToString (
  68. PAML_EXECUTION_CONTEXT Context,
  69. PACPI_OBJECT Object
  70. );
  71. PACPI_OBJECT
  72. AcpipConvertObjectTypeToBuffer (
  73. PAML_EXECUTION_CONTEXT Context,
  74. PACPI_OBJECT Object
  75. );
  76. BOOL
  77. AcpipEvaluateMatchComparison (
  78. PAML_EXECUTION_CONTEXT Context,
  79. PACPI_OBJECT PackageElement,
  80. PACPI_OBJECT Operand1,
  81. ACPI_MATCH_OPERATOR Operator1,
  82. PACPI_OBJECT Operand2,
  83. ACPI_MATCH_OPERATOR Operator2
  84. );
  85. //
  86. // -------------------------------------------------------------------- Globals
  87. //
  88. PSTR AcpiMatchOpcodeString[MatchOperatorCount] = {
  89. "MTR", // Always TRUE.
  90. "MEQ", // Equal to.
  91. "MLE", // Less than or Equal to.
  92. "MLT", // Less than.
  93. "MGE", // Greater than or equal to.
  94. "MGT" // Greater than.
  95. };
  96. //
  97. // ------------------------------------------------------------------ Functions
  98. //
  99. KSTATUS
  100. AcpipEvaluateAcquireStatement (
  101. PAML_EXECUTION_CONTEXT Context,
  102. PAML_STATEMENT Statement
  103. )
  104. /*++
  105. Routine Description:
  106. This routine evaluates an Acquire (mutex) statement.
  107. Arguments:
  108. Context - Supplies a pointer to the current AML execution context.
  109. Statement - Supplies a pointer to the statement to evaluate.
  110. Return Value:
  111. Status code.
  112. --*/
  113. {
  114. PUCHAR InstructionPointer;
  115. PACPI_OBJECT NewArgument;
  116. ULONGLONG ResultValue;
  117. USHORT TimeoutValue;
  118. //
  119. // Gather arguments if needed.
  120. //
  121. TimeoutValue = 0;
  122. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  123. if (Context->PrintStatements != FALSE) {
  124. if (Context->PreviousStatement == NULL) {
  125. RtlDebugPrint("Acquire (");
  126. }
  127. }
  128. //
  129. // An argument is required.
  130. //
  131. if (Context->PreviousStatement == NULL) {
  132. return STATUS_MORE_PROCESSING_REQUIRED;
  133. }
  134. if (Context->ExecuteStatements == FALSE) {
  135. Statement->Argument[0] = NULL;
  136. } else {
  137. NewArgument = Context->PreviousStatement->Reduction;
  138. if (NewArgument == NULL) {
  139. return STATUS_ARGUMENT_EXPECTED;
  140. }
  141. Statement->Argument[0] = NewArgument;
  142. AcpipObjectAddReference(NewArgument);
  143. }
  144. Statement->ArgumentsAcquired += 1;
  145. //
  146. // The first argument should be acquired now, and the second argument
  147. // is a constant word representing the timeout value.
  148. //
  149. InstructionPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
  150. if (Context->CurrentOffset + sizeof(USHORT) >= Context->AmlCodeSize) {
  151. return STATUS_MALFORMED_DATA_STREAM;
  152. }
  153. TimeoutValue = *((PUSHORT)InstructionPointer);
  154. Context->CurrentOffset += sizeof(USHORT);
  155. if (Context->PrintStatements != FALSE) {
  156. RtlDebugPrint(", %d)", TimeoutValue);
  157. }
  158. }
  159. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  160. Statement->Reduction = NULL;
  161. if (Context->ExecuteStatements != FALSE) {
  162. ASSERT(Statement->Argument[0]->Type == AcpiObjectMutex);
  163. ResultValue = AcpipAcquireMutex(Context,
  164. Statement->Argument[0]->U.Mutex.OsMutex,
  165. TimeoutValue);
  166. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  167. AcpiObjectInteger,
  168. NULL,
  169. &ResultValue,
  170. sizeof(ULONGLONG));
  171. if (Statement->Reduction == NULL) {
  172. return STATUS_UNSUCCESSFUL;
  173. }
  174. }
  175. return STATUS_SUCCESS;
  176. }
  177. KSTATUS
  178. AcpipEvaluateAliasStatement (
  179. PAML_EXECUTION_CONTEXT Context,
  180. PAML_STATEMENT Statement
  181. )
  182. /*++
  183. Routine Description:
  184. This routine evaluates the alias statement.
  185. Arguments:
  186. Context - Supplies a pointer to the current AML execution context.
  187. Statement - Supplies a pointer to the statement to evaluate.
  188. Return Value:
  189. Status code.
  190. --*/
  191. {
  192. PACPI_OBJECT Destination;
  193. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  194. ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
  195. if (Context->PrintStatements != FALSE) {
  196. RtlDebugPrint("Alias (%s, %s)\n",
  197. Statement->Argument[0]->U.String.String,
  198. Statement->Argument[1]->U.String.String);
  199. }
  200. if (Context->ExecuteStatements != FALSE) {
  201. //
  202. // Get the destination object that the alias points to.
  203. //
  204. Destination = AcpipGetNamespaceObject(
  205. Statement->Argument[0]->U.String.String,
  206. Context->CurrentScope);
  207. if (Destination == NULL) {
  208. return STATUS_NOT_FOUND;
  209. }
  210. //
  211. // Create the alias.
  212. //
  213. Statement->Reduction = AcpipCreateNamespaceObject(
  214. Context,
  215. AcpiObjectAlias,
  216. Statement->Argument[1]->U.String.String,
  217. &Destination,
  218. sizeof(PVOID));
  219. if (Statement->Reduction == NULL) {
  220. return STATUS_UNSUCCESSFUL;
  221. }
  222. }
  223. return STATUS_SUCCESS;
  224. }
  225. KSTATUS
  226. AcpipEvaluateArgumentStatement (
  227. PAML_EXECUTION_CONTEXT Context,
  228. PAML_STATEMENT Statement
  229. )
  230. /*++
  231. Routine Description:
  232. This routine evaluates the ArgX opcodes.
  233. Arguments:
  234. Context - Supplies a pointer to the current AML execution context.
  235. Statement - Supplies a pointer to the statement to evaluate.
  236. Return Value:
  237. STATUS_SUCCESS always.
  238. --*/
  239. {
  240. ULONG ArgumentNumber;
  241. PACPI_OBJECT ArgumentObject;
  242. ArgumentNumber = (ULONG)Statement->AdditionalData;
  243. if (Context->PrintStatements != FALSE) {
  244. RtlDebugPrint("Arg%d", ArgumentNumber);
  245. }
  246. Statement->Reduction = NULL;
  247. if (Context->ExecuteStatements != FALSE) {
  248. ArgumentObject = Context->CurrentMethod->Argument[ArgumentNumber];
  249. if (ArgumentObject != NULL) {
  250. Statement->Reduction = ArgumentObject;
  251. AcpipObjectAddReference(ArgumentObject);
  252. }
  253. }
  254. return STATUS_SUCCESS;
  255. }
  256. KSTATUS
  257. AcpipEvaluateBankFieldStatement (
  258. PAML_EXECUTION_CONTEXT Context,
  259. PAML_STATEMENT Statement
  260. )
  261. /*++
  262. Routine Description:
  263. This routine evaluates a BankField (in an Operation Region) statement.
  264. Arguments:
  265. Context - Supplies a pointer to the current AML execution context.
  266. Statement - Supplies a pointer to the statement to evaluate.
  267. Return Value:
  268. STATUS_SUCCESS always.
  269. --*/
  270. {
  271. UCHAR AccessFlags;
  272. PUCHAR InstructionPointer;
  273. PACPI_OBJECT NewArgument;
  274. PACPI_OBJECT OperationRegion;
  275. KSTATUS Status;
  276. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  277. ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
  278. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  279. if (Context->PrintStatements != FALSE) {
  280. if (Context->PreviousStatement == NULL) {
  281. RtlDebugPrint("BankField (%s, ",
  282. Statement->Argument[0]->U.String.String);
  283. } else {
  284. RtlDebugPrint(")");
  285. }
  286. }
  287. if (Context->PreviousStatement == NULL) {
  288. return STATUS_MORE_PROCESSING_REQUIRED;
  289. }
  290. ASSERT(Statement->ArgumentsAcquired == 2);
  291. //
  292. // Perform a conversion if needed.
  293. //
  294. NewArgument = Context->PreviousStatement->Reduction;
  295. if (NewArgument == NULL) {
  296. return STATUS_ARGUMENT_EXPECTED;
  297. }
  298. if (NewArgument->Type != AcpiObjectInteger) {
  299. NewArgument = AcpipConvertObjectType(Context,
  300. NewArgument,
  301. AcpiObjectInteger);
  302. if (NewArgument == NULL) {
  303. return STATUS_UNSUCCESSFUL;
  304. }
  305. } else {
  306. AcpipObjectAddReference(NewArgument);
  307. }
  308. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  309. Statement->ArgumentsAcquired += 1;
  310. }
  311. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  312. ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
  313. //
  314. // Parse the starting flags and store them in additional data 2.
  315. //
  316. InstructionPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
  317. AccessFlags = *InstructionPointer;
  318. Context->CurrentOffset += 1;
  319. //
  320. // Get the operation region this Field refers to.
  321. //
  322. OperationRegion =
  323. AcpipGetNamespaceObject(Statement->Argument[0]->U.String.String,
  324. Context->CurrentScope);
  325. if (OperationRegion == NULL) {
  326. return STATUS_NOT_FOUND;
  327. }
  328. //
  329. // Parse the field list.
  330. //
  331. Status = AcpipParseFieldList(Context,
  332. Statement->Type,
  333. OperationRegion,
  334. Statement->Argument[1],
  335. Statement->Argument[2],
  336. NULL,
  337. NULL,
  338. Statement->AdditionalData,
  339. AccessFlags);
  340. return Status;
  341. }
  342. KSTATUS
  343. AcpipEvaluateBreakPointStatement (
  344. PAML_EXECUTION_CONTEXT Context,
  345. PAML_STATEMENT Statement
  346. )
  347. /*++
  348. Routine Description:
  349. This routine evaluates the BreakPoint statement.
  350. Arguments:
  351. Context - Supplies a pointer to the current AML execution context.
  352. Statement - Supplies a pointer to the statement to evaluate.
  353. Return Value:
  354. STATUS_SUCCESS always.
  355. --*/
  356. {
  357. if (Context->PrintStatements != FALSE) {
  358. RtlDebugPrint("BreakPoint");
  359. }
  360. if (Context->ExecuteStatements != FALSE) {
  361. RtlDebugBreak();
  362. }
  363. return STATUS_SUCCESS;
  364. }
  365. KSTATUS
  366. AcpipEvaluateBufferStatement (
  367. PAML_EXECUTION_CONTEXT Context,
  368. PAML_STATEMENT Statement
  369. )
  370. /*++
  371. Routine Description:
  372. This routine evaluates a buffer declaration statement.
  373. Arguments:
  374. Context - Supplies a pointer to the current AML execution context.
  375. Statement - Supplies a pointer to the statement to evaluate.
  376. Return Value:
  377. Status code.
  378. --*/
  379. {
  380. PACPI_OBJECT Argument;
  381. PACPI_OBJECT BufferObject;
  382. ULONG BufferSize;
  383. ULONG ByteIndex;
  384. ULONG ByteListLength;
  385. PUCHAR ByteListPointer;
  386. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  387. if (Context->PreviousStatement == NULL) {
  388. if (Context->PrintStatements != FALSE) {
  389. RtlDebugPrint("Buffer (");
  390. }
  391. return STATUS_MORE_PROCESSING_REQUIRED;
  392. }
  393. if (Context->ExecuteStatements != FALSE) {
  394. //
  395. // Convert the buffer size object to an integer if needed.
  396. //
  397. Argument = Context->PreviousStatement->Reduction;
  398. if (Argument == NULL) {
  399. return STATUS_ARGUMENT_EXPECTED;
  400. }
  401. if (Argument->Type != AcpiObjectInteger) {
  402. Argument = AcpipConvertObjectType(Context,
  403. Argument,
  404. AcpiObjectInteger);
  405. } else {
  406. AcpipObjectAddReference(Argument);
  407. }
  408. Statement->Argument[0] = Argument;
  409. //
  410. // Just pretend the argument would have been there.
  411. //
  412. } else {
  413. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  414. }
  415. Statement->ArgumentsAcquired += 1;
  416. }
  417. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  418. //
  419. // Collect the byte list following the buffer size argument just acquired.
  420. //
  421. ByteListLength = Statement->AdditionalData - Context->CurrentOffset;
  422. ByteListPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
  423. if (Context->PrintStatements != FALSE) {
  424. RtlDebugPrint(") {");
  425. for (ByteIndex = 0; ByteIndex < ByteListLength; ByteIndex += 1) {
  426. RtlDebugPrint("%02x ", ByteListPointer[ByteIndex]);
  427. }
  428. RtlDebugPrint("}");
  429. }
  430. if (Context->ExecuteStatements != FALSE) {
  431. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  432. //
  433. // The buffer size comes from evaluating the argument. If the
  434. // initializer is bigger than the buffer size, then expand it to fit
  435. // the initializer.
  436. //
  437. BufferSize = Statement->Argument[0]->U.Integer.Value;
  438. if (BufferSize < ByteListLength) {
  439. BufferSize = ByteListLength;
  440. }
  441. //
  442. // If the buffer size is greater than the initializer, allocate and
  443. // initialize in two steps. Otherwise, pass the data directly.
  444. //
  445. if (BufferSize > ByteListLength) {
  446. BufferObject = AcpipCreateNamespaceObject(Context,
  447. AcpiObjectBuffer,
  448. NULL,
  449. NULL,
  450. BufferSize);
  451. if (BufferObject == NULL) {
  452. return STATUS_UNSUCCESSFUL;
  453. }
  454. RtlCopyMemory(BufferObject->U.Buffer.Buffer,
  455. ByteListPointer,
  456. ByteListLength);
  457. } else {
  458. BufferObject = AcpipCreateNamespaceObject(Context,
  459. AcpiObjectBuffer,
  460. NULL,
  461. ByteListPointer,
  462. ByteListLength);
  463. if (BufferObject == NULL) {
  464. return STATUS_UNSUCCESSFUL;
  465. }
  466. }
  467. Statement->Reduction = BufferObject;
  468. }
  469. //
  470. // Move the instruction pointer over the byte list.
  471. //
  472. Context->CurrentOffset = (ULONG)Statement->AdditionalData;
  473. return STATUS_SUCCESS;
  474. }
  475. KSTATUS
  476. AcpipEvaluateConcatenateResourceTemplatesStatement (
  477. PAML_EXECUTION_CONTEXT Context,
  478. PAML_STATEMENT Statement
  479. )
  480. /*++
  481. Routine Description:
  482. This routine evaluates a "Concatenate Resource Templates" statement, which
  483. concatenates two buffers that are resources templates. It automatically
  484. strips the end tags off the two, adds it to the concatenation, and calcuates
  485. the checksum.
  486. Arguments:
  487. Context - Supplies a pointer to the current AML execution context.
  488. Statement - Supplies a pointer to the statement to evaluate.
  489. Return Value:
  490. Status code.
  491. --*/
  492. {
  493. PACPI_OBJECT Argument0;
  494. ULONG Argument0Length;
  495. PACPI_OBJECT Argument1;
  496. ULONG Argument1Length;
  497. PUCHAR BytePointer;
  498. PACPI_OBJECT NewArgument;
  499. PACPI_OBJECT Result;
  500. UCHAR SumOfTemplate;
  501. //
  502. // If not all arguments are acquired, evaluate the previous statement to get
  503. // the next argument.
  504. //
  505. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  506. //
  507. // Print out the piece of the statement depending on the number of
  508. // arguments acquired.
  509. //
  510. if (Context->PrintStatements != FALSE) {
  511. if (Context->PreviousStatement == NULL) {
  512. RtlDebugPrint("ConcatResTemplate (");
  513. } else if ((Statement->ArgumentsAcquired == 0) ||
  514. (Statement->ArgumentsAcquired == 1)) {
  515. RtlDebugPrint(", ");
  516. } else {
  517. RtlDebugPrint(")");
  518. }
  519. }
  520. if (Context->PreviousStatement == NULL) {
  521. return STATUS_MORE_PROCESSING_REQUIRED;
  522. }
  523. //
  524. // If not executing, then assume the argument would be there but don't
  525. // try to dink with it.
  526. //
  527. if (Context->ExecuteStatements == FALSE) {
  528. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  529. Statement->ArgumentsAcquired += 1;
  530. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  531. return STATUS_MORE_PROCESSING_REQUIRED;
  532. }
  533. } else {
  534. NewArgument = Context->PreviousStatement->Reduction;
  535. if ((Statement->ArgumentsAcquired == 0) ||
  536. (Statement->ArgumentsAcquired == 1)) {
  537. //
  538. // Fail if there is no argument there.
  539. //
  540. if (Context->PreviousStatement->Reduction == NULL) {
  541. return STATUS_ARGUMENT_EXPECTED;
  542. }
  543. //
  544. // Only buffers are supported.
  545. //
  546. if (NewArgument->Type != AcpiObjectBuffer) {
  547. return STATUS_INVALID_PARAMETER;
  548. }
  549. }
  550. AcpipObjectAddReference(NewArgument);
  551. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  552. Statement->ArgumentsAcquired += 1;
  553. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  554. return STATUS_MORE_PROCESSING_REQUIRED;
  555. }
  556. }
  557. }
  558. //
  559. // Evaluate the result.
  560. //
  561. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  562. Argument0 = Statement->Argument[0];
  563. Argument1 = Statement->Argument[1];
  564. ASSERT(Argument0->Type == AcpiObjectBuffer);
  565. ASSERT(Argument1->Type == AcpiObjectBuffer);
  566. //
  567. // Strip off the end tag of argument 0, if there is one.
  568. //
  569. Argument0Length = Argument0->U.Buffer.Length;
  570. if (Argument0Length < 2) {
  571. Argument0Length = 0;
  572. } else {
  573. BytePointer = (PUCHAR)Argument0->U.Buffer.Buffer +
  574. Argument0->U.Buffer.Length - 2;
  575. if (*BytePointer == ACPI_RESOURCE_END_TAG) {
  576. Argument0Length -= 2;
  577. }
  578. }
  579. //
  580. // Strip off argument 1's end tag.
  581. //
  582. Argument1Length = Argument1->U.Buffer.Length;
  583. if (Argument1Length < 2) {
  584. Argument1Length = 0;
  585. } else {
  586. BytePointer = (PUCHAR)Argument1->U.Buffer.Buffer +
  587. Argument1->U.Buffer.Length - 2;
  588. if (*BytePointer == ACPI_RESOURCE_END_TAG) {
  589. Argument1Length -= 2;
  590. }
  591. }
  592. //
  593. // Create the new buffer object with space for an end tag.
  594. //
  595. Result = AcpipCreateNamespaceObject(Context,
  596. AcpiObjectBuffer,
  597. NULL,
  598. NULL,
  599. Argument0Length + Argument1Length + 2);
  600. if (Result == NULL) {
  601. return STATUS_UNSUCCESSFUL;
  602. }
  603. //
  604. // Copy the templates over, back to back
  605. //
  606. RtlCopyMemory(Result->U.Buffer.Buffer,
  607. Argument0->U.Buffer.Buffer,
  608. Argument0Length);
  609. RtlCopyMemory(Result->U.Buffer.Buffer + Argument0Length,
  610. Argument1->U.Buffer.Buffer,
  611. Argument1Length);
  612. //
  613. // Slap a new end tag and checksum on that puppy.
  614. //
  615. BytePointer = (PUCHAR)(Result->U.Buffer.Buffer) +
  616. Argument0Length + Argument1Length;
  617. *BytePointer = ACPI_RESOURCE_END_TAG;
  618. BytePointer += 1;
  619. SumOfTemplate = AcpipChecksumData(Result->U.Buffer.Buffer,
  620. Argument0Length + Argument1Length + 1);
  621. *BytePointer = -SumOfTemplate;
  622. Statement->Reduction = Result;
  623. //
  624. // Store the result in the target if supplied.
  625. //
  626. if (Statement->Argument[2] != NULL) {
  627. return AcpipPerformStoreOperation(Context,
  628. Statement->Reduction,
  629. Statement->Argument[2]);
  630. }
  631. return STATUS_SUCCESS;
  632. }
  633. KSTATUS
  634. AcpipEvaluateConcatenateStatement (
  635. PAML_EXECUTION_CONTEXT Context,
  636. PAML_STATEMENT Statement
  637. )
  638. /*++
  639. Routine Description:
  640. This routine evaluates a concatenate statement.
  641. Arguments:
  642. Context - Supplies a pointer to the current AML execution context.
  643. Statement - Supplies a pointer to the statement to evaluate.
  644. Return Value:
  645. Status code.
  646. --*/
  647. {
  648. PACPI_OBJECT Argument0;
  649. PACPI_OBJECT Argument1;
  650. PACPI_OBJECT NewArgument;
  651. ULONG NewLength;
  652. PACPI_OBJECT Result;
  653. ULONG String0Length;
  654. ULONG String1Length;
  655. //
  656. // If not all arguments are acquired, evaluate the previous statement to get
  657. // the next argument.
  658. //
  659. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  660. //
  661. // Print out the piece of the statement depending on the number of
  662. // arguments acquired.
  663. //
  664. if (Context->PrintStatements != FALSE) {
  665. if (Context->PreviousStatement == NULL) {
  666. RtlDebugPrint("Concat (");
  667. } else if ((Statement->ArgumentsAcquired == 0) ||
  668. (Statement->ArgumentsAcquired == 1)) {
  669. RtlDebugPrint(", ");
  670. } else {
  671. RtlDebugPrint(")");
  672. }
  673. }
  674. if (Context->PreviousStatement == NULL) {
  675. return STATUS_MORE_PROCESSING_REQUIRED;
  676. }
  677. //
  678. // If not executing, then assume the argument would be there but don't
  679. // try to dink with it.
  680. //
  681. if (Context->ExecuteStatements == FALSE) {
  682. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  683. Statement->ArgumentsAcquired += 1;
  684. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  685. return STATUS_MORE_PROCESSING_REQUIRED;
  686. }
  687. } else {
  688. NewArgument = Context->PreviousStatement->Reduction;
  689. if ((Statement->ArgumentsAcquired == 0) ||
  690. (Statement->ArgumentsAcquired == 1)) {
  691. //
  692. // Fail if there is no argument there.
  693. //
  694. if (Context->PreviousStatement->Reduction == NULL) {
  695. return STATUS_ARGUMENT_EXPECTED;
  696. }
  697. //
  698. // Only integers, strings, and buffers are supported.
  699. //
  700. if ((NewArgument->Type != AcpiObjectInteger) &&
  701. (NewArgument->Type != AcpiObjectString) &&
  702. (NewArgument->Type != AcpiObjectBuffer)) {
  703. return STATUS_INVALID_PARAMETER;
  704. }
  705. //
  706. // Perform an implicit conversion on the second argument (to the
  707. // type of the first argument) if needed.
  708. //
  709. if (Statement->ArgumentsAcquired == 0) {
  710. AcpipObjectAddReference(Statement->Argument[0]);
  711. } else if (Statement->ArgumentsAcquired == 1) {
  712. if (Statement->Argument[0]->Type != NewArgument->Type) {
  713. NewArgument = AcpipConvertObjectType(
  714. Context,
  715. NewArgument,
  716. Statement->Argument[0]->Type);
  717. if (NewArgument == NULL) {
  718. return STATUS_CONVERSION_FAILED;
  719. }
  720. //
  721. // No conversion is needed, just add to the reference count.
  722. //
  723. } else {
  724. AcpipObjectAddReference(NewArgument);
  725. }
  726. } else {
  727. ASSERT(Statement->ArgumentsAcquired == 2);
  728. AcpipObjectAddReference(NewArgument);
  729. }
  730. }
  731. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  732. Statement->ArgumentsAcquired += 1;
  733. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  734. return STATUS_MORE_PROCESSING_REQUIRED;
  735. }
  736. }
  737. }
  738. //
  739. // Evaluate the result.
  740. //
  741. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  742. if (Context->ExecuteStatements == FALSE) {
  743. return STATUS_SUCCESS;
  744. }
  745. Argument0 = Statement->Argument[0];
  746. Argument1 = Statement->Argument[1];
  747. switch (Argument0->Type) {
  748. //
  749. // Two integers get put together and make a buffer.
  750. //
  751. case AcpiObjectInteger:
  752. NewLength = 2 * sizeof(ULONGLONG);
  753. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  754. NewLength = 2 * sizeof(ULONG);
  755. }
  756. //
  757. // Create a new buffer.
  758. //
  759. Result = AcpipCreateNamespaceObject(Context,
  760. AcpiObjectBuffer,
  761. NULL,
  762. NULL,
  763. NewLength);
  764. if (Result == NULL) {
  765. return STATUS_UNSUCCESSFUL;
  766. }
  767. //
  768. // Copy the integers in like buffers.
  769. //
  770. RtlCopyMemory(Result->U.Buffer.Buffer,
  771. &(Argument0->U.Integer.Value),
  772. NewLength / 2);
  773. RtlCopyMemory(Result->U.Buffer.Buffer + NewLength / 2,
  774. &(Argument1->U.Integer.Value),
  775. NewLength / 2);
  776. break;
  777. //
  778. // Two buffers simply get glommed together.
  779. //
  780. case AcpiObjectBuffer:
  781. NewLength = Argument0->U.Buffer.Length + Argument1->U.Buffer.Length;
  782. Result = AcpipCreateNamespaceObject(Context,
  783. AcpiObjectBuffer,
  784. NULL,
  785. NULL,
  786. NewLength);
  787. if (Result == NULL) {
  788. return STATUS_UNSUCCESSFUL;
  789. }
  790. RtlCopyMemory(Result->U.Buffer.Buffer,
  791. Argument0->U.Buffer.Buffer,
  792. Argument0->U.Buffer.Length);
  793. RtlCopyMemory(Result->U.Buffer.Buffer + Argument0->U.Buffer.Length,
  794. Argument1->U.Buffer.Buffer,
  795. Argument1->U.Buffer.Length);
  796. break;
  797. //
  798. // Two strings get concatenated into another string.
  799. //
  800. case AcpiObjectString:
  801. String0Length = RtlStringLength(Argument0->U.String.String);
  802. String1Length = RtlStringLength(Argument1->U.String.String);
  803. NewLength = String0Length + String1Length + 1;
  804. Result = AcpipCreateNamespaceObject(Context,
  805. AcpiObjectString,
  806. NULL,
  807. NULL,
  808. NewLength);
  809. if (Result == NULL) {
  810. return STATUS_UNSUCCESSFUL;
  811. }
  812. RtlCopyMemory(Result->U.String.String,
  813. Argument0->U.String.String,
  814. String0Length);
  815. RtlCopyMemory(Result->U.String.String + String0Length,
  816. Argument1->U.String.String,
  817. String1Length);
  818. Result->U.String.String[NewLength - 1] = '\0';
  819. break;
  820. default:
  821. ASSERT(FALSE);
  822. return STATUS_CONVERSION_FAILED;
  823. }
  824. Statement->Reduction = Result;
  825. //
  826. // Store the result in the target if supplied.
  827. //
  828. if (Statement->Argument[2] != NULL) {
  829. return AcpipPerformStoreOperation(Context,
  830. Statement->Reduction,
  831. Statement->Argument[2]);
  832. }
  833. return STATUS_SUCCESS;
  834. }
  835. KSTATUS
  836. AcpipEvaluateConditionalReferenceOfStatement (
  837. PAML_EXECUTION_CONTEXT Context,
  838. PAML_STATEMENT Statement
  839. )
  840. /*++
  841. Routine Description:
  842. This routine evaluates an "Reference Of" statement.
  843. Arguments:
  844. Context - Supplies a pointer to the current AML execution context.
  845. Statement - Supplies a pointer to the statement to evaluate.
  846. Return Value:
  847. Status code.
  848. --*/
  849. {
  850. PACPI_OBJECT NameString;
  851. PACPI_OBJECT NewArgument;
  852. PACPI_OBJECT Reference;
  853. ULONGLONG ResultValue;
  854. //
  855. // Gather arguments if needed.
  856. //
  857. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  858. if (Context->PrintStatements != FALSE) {
  859. if (Context->PreviousStatement == NULL) {
  860. RtlDebugPrint("CondRefOf (");
  861. } else if (Statement->ArgumentsAcquired == 0) {
  862. RtlDebugPrint(", ");
  863. } else {
  864. RtlDebugPrint(")");
  865. }
  866. }
  867. //
  868. // The argument for RefOf is a "SuperName", which is a SimpleName,
  869. // DebugOp, or Type6Opcode. If this is the first time through, try to
  870. // parse a name string.
  871. //
  872. if (Context->PreviousStatement == NULL) {
  873. NameString = AcpipParseNameString(Context);
  874. if (NameString == NULL) {
  875. return STATUS_MORE_PROCESSING_REQUIRED;
  876. }
  877. if (Context->ExecuteStatements != FALSE) {
  878. Statement->Argument[0] =
  879. AcpipGetNamespaceObject(NameString->U.String.String,
  880. Context->CurrentScope);
  881. } else {
  882. Statement->Argument[0] = NULL;
  883. }
  884. if (Statement->Argument[0] != NULL) {
  885. AcpipObjectAddReference(Statement->Argument[0]);
  886. }
  887. Statement->ArgumentsAcquired += 1;
  888. AcpipObjectReleaseReference(NameString);
  889. //
  890. // Increment the reference count on the object.
  891. //
  892. } else {
  893. if (Context->ExecuteStatements != FALSE) {
  894. NewArgument = Context->PreviousStatement->Reduction;
  895. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  896. if (NewArgument != NULL) {
  897. AcpipObjectAddReference(NewArgument);
  898. }
  899. } else {
  900. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  901. }
  902. Statement->ArgumentsAcquired += 1;
  903. }
  904. if (Statement->ArgumentsAcquired != Statement->ArgumentsNeeded) {
  905. return STATUS_MORE_PROCESSING_REQUIRED;
  906. }
  907. }
  908. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  909. if (Context->ExecuteStatements != FALSE) {
  910. //
  911. // The reduction of this statement is a boolean indicating whether the
  912. // object actually exists or not.
  913. //
  914. ResultValue = FALSE;
  915. if ((Statement->Argument[0] != NULL) &&
  916. (Statement->Argument[0]->Type != AcpiObjectUninitialized)) {
  917. ResultValue = TRUE;
  918. }
  919. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  920. AcpiObjectInteger,
  921. NULL,
  922. &ResultValue,
  923. sizeof(ULONGLONG));
  924. if ((Statement->Argument[0] != NULL) &&
  925. (Statement->Argument[1] != NULL)) {
  926. Reference = AcpipCreateNamespaceObject(Context,
  927. AcpiObjectAlias,
  928. NULL,
  929. &(Statement->Argument[0]),
  930. sizeof(PACPI_OBJECT));
  931. if (Reference == NULL) {
  932. return STATUS_UNSUCCESSFUL;
  933. }
  934. AcpipPerformStoreOperation(Context,
  935. Reference,
  936. Statement->Argument[1]);
  937. AcpipObjectReleaseReference(Reference);
  938. }
  939. }
  940. return STATUS_SUCCESS;
  941. }
  942. KSTATUS
  943. AcpipEvaluateCopyObjectStatement (
  944. PAML_EXECUTION_CONTEXT Context,
  945. PAML_STATEMENT Statement
  946. )
  947. /*++
  948. Routine Description:
  949. This routine evaluates a "Copy Object" statement.
  950. Arguments:
  951. Context - Supplies a pointer to the current AML execution context.
  952. Statement - Supplies a pointer to the statement to evaluate.
  953. Return Value:
  954. Status code.
  955. --*/
  956. {
  957. PACPI_OBJECT Destination;
  958. PACPI_OBJECT NewArgument;
  959. PACPI_OBJECT Source;
  960. KSTATUS Status;
  961. //
  962. // If not all arguments are acquired, evaluate the previous statement to get
  963. // the next argument.
  964. //
  965. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  966. //
  967. // Print out the piece of the statement depending on the number of
  968. // arguments acquired.
  969. //
  970. if (Context->PrintStatements != FALSE) {
  971. if (Context->PreviousStatement == NULL) {
  972. RtlDebugPrint("CopyObject (");
  973. } else if (Statement->ArgumentsAcquired == 0) {
  974. RtlDebugPrint(", ");
  975. } else {
  976. RtlDebugPrint(")");
  977. }
  978. }
  979. if (Context->PreviousStatement == NULL) {
  980. return STATUS_MORE_PROCESSING_REQUIRED;
  981. }
  982. //
  983. // If not executing, then assume the argument would be there but don't
  984. // try to dink with it.
  985. //
  986. if (Context->ExecuteStatements == FALSE) {
  987. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  988. Statement->ArgumentsAcquired += 1;
  989. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  990. return STATUS_MORE_PROCESSING_REQUIRED;
  991. }
  992. } else {
  993. NewArgument = Context->PreviousStatement->Reduction;
  994. ASSERT(Statement->ArgumentsAcquired == 0);
  995. if (Context->PreviousStatement->Reduction == NULL) {
  996. return STATUS_ARGUMENT_EXPECTED;
  997. }
  998. AcpipObjectAddReference(NewArgument);
  999. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  1000. Statement->ArgumentsAcquired += 1;
  1001. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1002. return STATUS_MORE_PROCESSING_REQUIRED;
  1003. }
  1004. }
  1005. }
  1006. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1007. Statement->Reduction = NULL;
  1008. if (Context->ExecuteStatements != FALSE) {
  1009. Source = Statement->Argument[0];
  1010. //
  1011. // This needs to perform an implicit source converstion into a
  1012. // DataRefObject (i.e. a DataObject or Reference Object).
  1013. //
  1014. Status = AcpipConvertToDataReferenceObject(Context, Source, &Source);
  1015. if (!KSUCCESS(Status)) {
  1016. goto EvaluateCopyObjectStatementEnd;
  1017. }
  1018. Statement->Reduction = AcpipCopyObject(Source);
  1019. AcpipObjectReleaseReference(Source);
  1020. //
  1021. // If the target is supplied, replace it with the copy.
  1022. //
  1023. Destination = Statement->Argument[1];
  1024. if (Destination != NULL) {
  1025. Status = AcpipResolveStoreDestination(Context,
  1026. Destination,
  1027. &Destination);
  1028. if (!KSUCCESS(Status)) {
  1029. goto EvaluateCopyObjectStatementEnd;
  1030. }
  1031. Status = AcpipReplaceObjectContents(Context,
  1032. Destination,
  1033. Statement->Reduction);
  1034. AcpipObjectReleaseReference(Destination);
  1035. if (!KSUCCESS(Status)) {
  1036. goto EvaluateCopyObjectStatementEnd;
  1037. }
  1038. }
  1039. }
  1040. Status = STATUS_SUCCESS;
  1041. EvaluateCopyObjectStatementEnd:
  1042. return Status;
  1043. }
  1044. KSTATUS
  1045. AcpipEvaluateCreateBufferFieldStatement (
  1046. PAML_EXECUTION_CONTEXT Context,
  1047. PAML_STATEMENT Statement
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. This routine evaluates a CreateField (from a buffer) statement.
  1052. Arguments:
  1053. Context - Supplies a pointer to the current AML execution context.
  1054. Statement - Supplies a pointer to the statement to evaluate.
  1055. Return Value:
  1056. Status code.
  1057. --*/
  1058. {
  1059. ACPI_BUFFER_FIELD_OBJECT BufferField;
  1060. PSTR Name;
  1061. PACPI_OBJECT NewArgument;
  1062. ACPI_OBJECT_TYPE ObjectType;
  1063. NewArgument = NULL;
  1064. //
  1065. // If not all arguments are acquired, evaluate the previous statement to get
  1066. // the next argument.
  1067. //
  1068. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1069. //
  1070. // Print out the piece of the statement depending on the number of
  1071. // arguments acquired.
  1072. //
  1073. if (Context->PrintStatements != FALSE) {
  1074. if (Context->PreviousStatement == NULL) {
  1075. RtlDebugPrint("CreateField (");
  1076. } else if ((Statement->ArgumentsAcquired == 0) ||
  1077. (Statement->ArgumentsAcquired == 1) ||
  1078. (Statement->ArgumentsAcquired == 2)) {
  1079. RtlDebugPrint(", ");
  1080. }
  1081. }
  1082. if (Context->PreviousStatement == NULL) {
  1083. return STATUS_MORE_PROCESSING_REQUIRED;
  1084. }
  1085. //
  1086. // If not executing, then assume the argument would be there but don't
  1087. // try to dink with it.
  1088. //
  1089. if (Context->ExecuteStatements == FALSE) {
  1090. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  1091. Statement->ArgumentsAcquired += 1;
  1092. if ((Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) &&
  1093. (Statement->ArgumentsAcquired != 3)) {
  1094. return STATUS_MORE_PROCESSING_REQUIRED;
  1095. }
  1096. } else {
  1097. NewArgument = Context->PreviousStatement->Reduction;
  1098. //
  1099. // Fail if there is no argument there.
  1100. //
  1101. if (Context->PreviousStatement->Reduction == NULL) {
  1102. return STATUS_ARGUMENT_EXPECTED;
  1103. }
  1104. //
  1105. // The first required argument is a buffer, the second is the
  1106. // bit index (Integer), and the third is the bit length (Integer).
  1107. //
  1108. ObjectType = AcpiObjectBuffer;
  1109. if ((Statement->ArgumentsAcquired == 1) ||
  1110. (Statement->ArgumentsAcquired == 2)) {
  1111. ObjectType = AcpiObjectInteger;
  1112. }
  1113. //
  1114. // Perform an implicit conversion if needed.
  1115. //
  1116. if (NewArgument->Type != ObjectType) {
  1117. NewArgument = AcpipConvertObjectType(Context,
  1118. NewArgument,
  1119. ObjectType);
  1120. if (NewArgument == NULL) {
  1121. return STATUS_CONVERSION_FAILED;
  1122. }
  1123. //
  1124. // The object is fine, take ownership of it.
  1125. //
  1126. } else {
  1127. AcpipObjectAddReference(NewArgument);
  1128. }
  1129. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  1130. Statement->ArgumentsAcquired += 1;
  1131. if (Statement->ArgumentsAcquired != 3) {
  1132. return STATUS_MORE_PROCESSING_REQUIRED;
  1133. }
  1134. }
  1135. //
  1136. // The fourth argument is a name string, which can be parsed now.
  1137. //
  1138. ASSERT(Statement->ArgumentsAcquired == 3);
  1139. Statement->Argument[3] = AcpipParseNameString(Context);
  1140. if (Statement->Argument[3] == NULL) {
  1141. return STATUS_UNSUCCESSFUL;
  1142. }
  1143. Statement->ArgumentsAcquired += 1;
  1144. }
  1145. //
  1146. // Evaluate the result.
  1147. //
  1148. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1149. ASSERT(Statement->Argument[3]->Type == AcpiObjectString);
  1150. Name = Statement->Argument[3]->U.String.String;
  1151. if (Context->PrintStatements != FALSE) {
  1152. RtlDebugPrint("%s)", Name);
  1153. }
  1154. Statement->Reduction = NULL;
  1155. if (Context->ExecuteStatements == FALSE) {
  1156. return STATUS_SUCCESS;
  1157. }
  1158. ASSERT(Statement->Argument[0]->Type == AcpiObjectBuffer);
  1159. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  1160. ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
  1161. //
  1162. // Create the buffer field object. Remember that additional data holds the
  1163. // bit field length.
  1164. //
  1165. RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
  1166. BufferField.DestinationObject = Statement->Argument[0];
  1167. BufferField.BitOffset = Statement->Argument[1]->U.Integer.Value;
  1168. BufferField.BitLength = Statement->Argument[2]->U.Integer.Value;
  1169. Statement->Reduction = AcpipCreateNamespaceObject(
  1170. Context,
  1171. AcpiObjectBufferField,
  1172. Name,
  1173. &BufferField,
  1174. sizeof(ACPI_BUFFER_FIELD_OBJECT));
  1175. if (Statement->Reduction == NULL) {
  1176. return STATUS_UNSUCCESSFUL;
  1177. }
  1178. return STATUS_SUCCESS;
  1179. }
  1180. KSTATUS
  1181. AcpipEvaluateCreateFixedBufferFieldStatement (
  1182. PAML_EXECUTION_CONTEXT Context,
  1183. PAML_STATEMENT Statement
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This routine evaluates a CreateBitField, CreateByteField, CreateWordField,
  1188. CreateDWordField, or CreateQWordField statement, which creates a Buffer
  1189. Field object pointing at a buffer.
  1190. Arguments:
  1191. Context - Supplies a pointer to the current AML execution context.
  1192. Statement - Supplies a pointer to the statement to evaluate.
  1193. Return Value:
  1194. Status code.
  1195. --*/
  1196. {
  1197. ACPI_BUFFER_FIELD_OBJECT BufferField;
  1198. PSTR Name;
  1199. PACPI_OBJECT NewArgument;
  1200. ACPI_OBJECT_TYPE ObjectType;
  1201. NewArgument = NULL;
  1202. //
  1203. // If not all arguments are acquired, evaluate the previous statement to get
  1204. // the next argument.
  1205. //
  1206. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1207. //
  1208. // Print out the piece of the statement depending on the number of
  1209. // arguments acquired.
  1210. //
  1211. if (Context->PrintStatements != FALSE) {
  1212. if (Context->PreviousStatement == NULL) {
  1213. switch (Statement->AdditionalData) {
  1214. case 1:
  1215. RtlDebugPrint("CreateBitField (");
  1216. break;
  1217. case BITS_PER_BYTE:
  1218. RtlDebugPrint("CreateByteField (");
  1219. break;
  1220. case sizeof(USHORT) * BITS_PER_BYTE:
  1221. RtlDebugPrint("CreateWordField (");
  1222. break;
  1223. case sizeof(ULONG) * BITS_PER_BYTE:
  1224. RtlDebugPrint("CreateDWordField (");
  1225. break;
  1226. case sizeof(ULONGLONG) * BITS_PER_BYTE:
  1227. RtlDebugPrint("CreateQWordField (");
  1228. break;
  1229. default:
  1230. ASSERT(FALSE);
  1231. return STATUS_NOT_SUPPORTED;
  1232. }
  1233. } else if ((Statement->ArgumentsAcquired == 0) ||
  1234. (Statement->ArgumentsAcquired == 1)) {
  1235. RtlDebugPrint(", ");
  1236. }
  1237. }
  1238. if (Context->PreviousStatement == NULL) {
  1239. return STATUS_MORE_PROCESSING_REQUIRED;
  1240. }
  1241. ASSERT(Statement->ArgumentsAcquired != 2);
  1242. //
  1243. // If not executing, then assume the argument would be there but
  1244. // don't try to dink with it.
  1245. //
  1246. if (Context->ExecuteStatements == FALSE) {
  1247. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  1248. Statement->ArgumentsAcquired += 1;
  1249. //
  1250. // Grab the first or second argument.
  1251. //
  1252. } else {
  1253. NewArgument = Context->PreviousStatement->Reduction;
  1254. //
  1255. // Fail if there is no argument there.
  1256. //
  1257. if (Context->PreviousStatement->Reduction == NULL) {
  1258. return STATUS_ARGUMENT_EXPECTED;
  1259. }
  1260. //
  1261. // The first required argument is a buffer, and the second is the
  1262. // bit index (Integer).
  1263. //
  1264. ObjectType = AcpiObjectBuffer;
  1265. if (Statement->ArgumentsAcquired == 1) {
  1266. ObjectType = AcpiObjectInteger;
  1267. }
  1268. //
  1269. // Perform an implicit conversion if needed.
  1270. //
  1271. if (NewArgument->Type != ObjectType) {
  1272. NewArgument = AcpipConvertObjectType(Context,
  1273. NewArgument,
  1274. ObjectType);
  1275. if (NewArgument == NULL) {
  1276. return STATUS_CONVERSION_FAILED;
  1277. }
  1278. //
  1279. // The object is fine, take ownership of it.
  1280. //
  1281. } else {
  1282. AcpipObjectAddReference(NewArgument);
  1283. }
  1284. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  1285. Statement->ArgumentsAcquired += 1;
  1286. }
  1287. //
  1288. // If only the first argument has been parsed, then another one is
  1289. // needed. If two have, then continue to parse the third.
  1290. //
  1291. if (Statement->ArgumentsAcquired == 1) {
  1292. return STATUS_MORE_PROCESSING_REQUIRED;
  1293. }
  1294. //
  1295. // The third argument is a name string, which can be parsed now.
  1296. //
  1297. if (Statement->ArgumentsAcquired == 2) {
  1298. ASSERT(Statement->ArgumentsAcquired == 2);
  1299. Statement->Argument[2] = AcpipParseNameString(Context);
  1300. if (Statement->Argument[2] == NULL) {
  1301. return STATUS_UNSUCCESSFUL;
  1302. }
  1303. Statement->ArgumentsAcquired += 1;
  1304. }
  1305. }
  1306. //
  1307. // Evaluate the result.
  1308. //
  1309. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1310. ASSERT(Statement->Argument[2]->Type == AcpiObjectString);
  1311. Name = Statement->Argument[2]->U.String.String;
  1312. if (Context->PrintStatements != FALSE) {
  1313. RtlDebugPrint("%s)", Name);
  1314. }
  1315. Statement->Reduction = NULL;
  1316. if (Context->ExecuteStatements == FALSE) {
  1317. return STATUS_SUCCESS;
  1318. }
  1319. ASSERT(Statement->Argument[0]->Type == AcpiObjectBuffer);
  1320. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  1321. //
  1322. // Create the buffer field object. Remember that additional data holds the
  1323. // bit field length.
  1324. //
  1325. RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
  1326. BufferField.DestinationObject = Statement->Argument[0];
  1327. BufferField.BitLength = Statement->AdditionalData;
  1328. BufferField.BitOffset = Statement->Argument[1]->U.Integer.Value;
  1329. //
  1330. // Bitfields are specified in bits, but all other sized fields are
  1331. // specified in bytes.
  1332. //
  1333. if (BufferField.BitLength > 1) {
  1334. BufferField.BitOffset *= BITS_PER_BYTE;
  1335. }
  1336. Statement->Reduction = AcpipCreateNamespaceObject(
  1337. Context,
  1338. AcpiObjectBufferField,
  1339. Name,
  1340. &BufferField,
  1341. sizeof(ACPI_BUFFER_FIELD_OBJECT));
  1342. if (Statement->Reduction == NULL) {
  1343. return STATUS_UNSUCCESSFUL;
  1344. }
  1345. return STATUS_SUCCESS;
  1346. }
  1347. KSTATUS
  1348. AcpipEvaluateDataStatement (
  1349. PAML_EXECUTION_CONTEXT Context,
  1350. PAML_STATEMENT Statement
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. This routine evaluates constant data coming from ByteData, WordData,
  1355. DWordData, QWordData, and StringData.
  1356. Arguments:
  1357. Context - Supplies a pointer to the current AML execution context.
  1358. Statement - Supplies a pointer to the statement to evaluate.
  1359. Return Value:
  1360. Status code.
  1361. --*/
  1362. {
  1363. PUCHAR DataPointer;
  1364. DataPointer = (PUCHAR)Context->AmlCode + Statement->AdditionalData;
  1365. //
  1366. // For string data, just create the string from the buffer pointer. A copy
  1367. // will be made.
  1368. //
  1369. if (Statement->AdditionalData2 == 0) {
  1370. Statement->Reduction = AcpipCreateNamespaceObject(
  1371. Context,
  1372. AcpiObjectString,
  1373. NULL,
  1374. DataPointer,
  1375. RtlStringLength((PSTR)DataPointer) + 1);
  1376. if (Statement->Reduction == NULL) {
  1377. return STATUS_UNSUCCESSFUL;
  1378. }
  1379. if (Context->PrintStatements != FALSE) {
  1380. RtlDebugPrint("\"");
  1381. RtlDebugPrint(Statement->Reduction->U.String.String);
  1382. RtlDebugPrint("\"");
  1383. }
  1384. //
  1385. // The other types are integers.
  1386. //
  1387. } else {
  1388. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  1389. AcpiObjectInteger,
  1390. NULL,
  1391. NULL,
  1392. 0);
  1393. if (Statement->Reduction == NULL) {
  1394. return STATUS_UNSUCCESSFUL;
  1395. }
  1396. Statement->Reduction->U.Integer.Value = 0;
  1397. RtlCopyMemory(&(Statement->Reduction->U.Integer.Value),
  1398. DataPointer,
  1399. Statement->AdditionalData2);
  1400. if (Context->PrintStatements != FALSE) {
  1401. RtlDebugPrint("0x%I64x", Statement->Reduction->U.Integer.Value);
  1402. }
  1403. }
  1404. return STATUS_SUCCESS;
  1405. }
  1406. KSTATUS
  1407. AcpipEvaluateDelayStatement (
  1408. PAML_EXECUTION_CONTEXT Context,
  1409. PAML_STATEMENT Statement
  1410. )
  1411. /*++
  1412. Routine Description:
  1413. This routine evaluates both the Sleep and Stall statements.
  1414. Arguments:
  1415. Context - Supplies a pointer to the current AML execution context.
  1416. Statement - Supplies a pointer to the statement to evaluate.
  1417. Return Value:
  1418. Status code.
  1419. --*/
  1420. {
  1421. PACPI_OBJECT NewArgument;
  1422. ULONG Operand;
  1423. //
  1424. // If not all arguments are acquired, evaluate the previous statement to get
  1425. // the next argument.
  1426. //
  1427. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1428. //
  1429. // Print out the piece of the statement depending on the number of
  1430. // arguments acquired.
  1431. //
  1432. if (Context->PrintStatements != FALSE) {
  1433. if (Context->PreviousStatement == NULL) {
  1434. if (Statement->Type == AmlStatementSleep) {
  1435. RtlDebugPrint("Sleep (");
  1436. } else {
  1437. ASSERT(Statement->Type == AmlStatementStall);
  1438. RtlDebugPrint("Stall (");
  1439. }
  1440. } else {
  1441. RtlDebugPrint(")");
  1442. }
  1443. }
  1444. if (Context->PreviousStatement == NULL) {
  1445. return STATUS_MORE_PROCESSING_REQUIRED;
  1446. }
  1447. //
  1448. // If not executing, then assume the argument would be there but don't
  1449. // try to dink with it.
  1450. //
  1451. if (Context->ExecuteStatements == FALSE) {
  1452. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  1453. Statement->ArgumentsAcquired += 1;
  1454. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1455. return STATUS_MORE_PROCESSING_REQUIRED;
  1456. }
  1457. } else {
  1458. NewArgument = Context->PreviousStatement->Reduction;
  1459. //
  1460. // Fail if there is no argument there.
  1461. //
  1462. if (Context->PreviousStatement->Reduction == NULL) {
  1463. return STATUS_ARGUMENT_EXPECTED;
  1464. }
  1465. //
  1466. // Perform an implicit conversion if needed.
  1467. //
  1468. if (NewArgument->Type != AcpiObjectInteger) {
  1469. NewArgument = AcpipConvertObjectType(Context,
  1470. NewArgument,
  1471. AcpiObjectInteger);
  1472. if (NewArgument == NULL) {
  1473. return STATUS_CONVERSION_FAILED;
  1474. }
  1475. //
  1476. // The object is fine, take ownership of it.
  1477. //
  1478. } else {
  1479. AcpipObjectAddReference(NewArgument);
  1480. }
  1481. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  1482. Statement->ArgumentsAcquired += 1;
  1483. }
  1484. }
  1485. //
  1486. // Evaluate the result.
  1487. //
  1488. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1489. Statement->Reduction = NULL;
  1490. if (Context->ExecuteStatements == FALSE) {
  1491. return STATUS_SUCCESS;
  1492. }
  1493. //
  1494. // For sleep statements, use the scheduler and relinquish the processor.
  1495. //
  1496. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  1497. Operand = (ULONG)Statement->Argument[0]->U.Integer.Value;
  1498. if (Statement->Type == AmlStatementSleep) {
  1499. AcpipSleep(Operand);
  1500. //
  1501. // For stall statements, perform a busy spin.
  1502. //
  1503. } else {
  1504. ASSERT(Statement->Type == AmlStatementStall);
  1505. AcpipBusySpin(Operand);
  1506. }
  1507. return STATUS_SUCCESS;
  1508. }
  1509. KSTATUS
  1510. AcpipEvaluateDebugStatement (
  1511. PAML_EXECUTION_CONTEXT Context,
  1512. PAML_STATEMENT Statement
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. This routine evaluates a Debug statement.
  1517. Arguments:
  1518. Context - Supplies a pointer to the current AML execution context.
  1519. Statement - Supplies a pointer to the statement to evaluate.
  1520. Return Value:
  1521. Status code.
  1522. --*/
  1523. {
  1524. if (Context->PrintStatements != FALSE) {
  1525. RtlDebugPrint("Debug");
  1526. }
  1527. if (Context->ExecuteStatements != FALSE) {
  1528. //
  1529. // Create a debug object. Simple as that.
  1530. //
  1531. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  1532. AcpiObjectDebug,
  1533. NULL,
  1534. NULL,
  1535. 0);
  1536. if (Statement->Reduction == NULL) {
  1537. return STATUS_UNSUCCESSFUL;
  1538. }
  1539. }
  1540. return STATUS_SUCCESS;
  1541. }
  1542. KSTATUS
  1543. AcpipEvaluateDereferenceOfStatement (
  1544. PAML_EXECUTION_CONTEXT Context,
  1545. PAML_STATEMENT Statement
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This routine evaluates a "Dereference Of" statement.
  1550. Arguments:
  1551. Context - Supplies a pointer to the current AML execution context.
  1552. Statement - Supplies a pointer to the statement to evaluate.
  1553. Return Value:
  1554. Status code.
  1555. --*/
  1556. {
  1557. PACPI_OBJECT Source;
  1558. KSTATUS Status;
  1559. //
  1560. // Gather arguments.
  1561. //
  1562. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1563. if (Context->PrintStatements != FALSE) {
  1564. if (Context->PreviousStatement == NULL) {
  1565. RtlDebugPrint("DerefOf (");
  1566. }
  1567. }
  1568. if (Context->PreviousStatement == NULL) {
  1569. return STATUS_MORE_PROCESSING_REQUIRED;
  1570. } else {
  1571. Statement->Argument[0] = NULL;
  1572. if (Context->ExecuteStatements != FALSE) {
  1573. Statement->Argument[0] = Context->PreviousStatement->Reduction;
  1574. AcpipObjectAddReference(Statement->Argument[0]);
  1575. }
  1576. Statement->ArgumentsAcquired += 1;
  1577. }
  1578. }
  1579. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1580. if (Context->PrintStatements != FALSE) {
  1581. RtlDebugPrint(")");
  1582. }
  1583. Statement->Reduction = NULL;
  1584. if (Context->ExecuteStatements != FALSE) {
  1585. Source = Statement->Argument[0];
  1586. switch (Source->Type) {
  1587. case AcpiObjectAlias:
  1588. Statement->Reduction = Source->U.Alias.DestinationObject;
  1589. AcpipObjectAddReference(Statement->Reduction);
  1590. break;
  1591. case AcpiObjectString:
  1592. Statement->Reduction =
  1593. AcpipGetNamespaceObject(Source->U.String.String,
  1594. Context->CurrentScope);
  1595. if (Statement->Reduction == NULL) {
  1596. return STATUS_NOT_FOUND;
  1597. }
  1598. AcpipObjectAddReference(Statement->Reduction);
  1599. break;
  1600. case AcpiObjectBufferField:
  1601. Status = AcpipReadFromBufferField(Context,
  1602. Source,
  1603. &(Statement->Reduction));
  1604. if (!KSUCCESS(Status)) {
  1605. return Status;
  1606. }
  1607. break;
  1608. default:
  1609. ASSERT(FALSE);
  1610. return STATUS_UNEXPECTED_TYPE;
  1611. }
  1612. }
  1613. return STATUS_SUCCESS;
  1614. }
  1615. KSTATUS
  1616. AcpipEvaluateDeviceStatement (
  1617. PAML_EXECUTION_CONTEXT Context,
  1618. PAML_STATEMENT Statement
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. This routine evaluates a Device declaration statement.
  1623. Arguments:
  1624. Context - Supplies a pointer to the current AML execution context.
  1625. Statement - Supplies a pointer to the statement to evaluate.
  1626. Return Value:
  1627. Status code.
  1628. --*/
  1629. {
  1630. PSTR DeviceName;
  1631. PACPI_OBJECT DeviceObject;
  1632. if (Context->PreviousStatement == NULL) {
  1633. Statement->SavedScope = NULL;
  1634. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  1635. DeviceName = Statement->Argument[0]->U.String.String;
  1636. if (Context->PrintStatements != FALSE) {
  1637. RtlDebugPrint("Device (%s) {", DeviceName);
  1638. }
  1639. if (Context->ExecuteStatements != FALSE) {
  1640. //
  1641. // Create the device object.
  1642. //
  1643. DeviceObject = AcpipCreateNamespaceObject(Context,
  1644. AcpiObjectDevice,
  1645. DeviceName,
  1646. NULL,
  1647. 0);
  1648. if (DeviceObject == NULL) {
  1649. return STATUS_UNSUCCESSFUL;
  1650. }
  1651. //
  1652. // Make this device the current scope.
  1653. //
  1654. Statement->SavedScope = Context->CurrentScope;
  1655. Context->CurrentScope = DeviceObject;
  1656. Statement->Reduction = DeviceObject;
  1657. }
  1658. Context->IndentationLevel += 1;
  1659. }
  1660. //
  1661. // If execution is not done with the scope, keep this statement on the
  1662. // stack.
  1663. //
  1664. if (Context->CurrentOffset < Statement->AdditionalData) {
  1665. AcpipPrintIndentedNewLine(Context);
  1666. return STATUS_MORE_PROCESSING_REQUIRED;
  1667. }
  1668. //
  1669. // Pop this puppy off the stack.
  1670. //
  1671. Context->CurrentScope = Statement->SavedScope;
  1672. Context->IndentationLevel -= 1;
  1673. if (Context->PrintStatements != FALSE) {
  1674. AcpipPrintIndentedNewLine(Context);
  1675. RtlDebugPrint("}");
  1676. AcpipPrintIndentedNewLine(Context);
  1677. }
  1678. return STATUS_SUCCESS;
  1679. }
  1680. KSTATUS
  1681. AcpipEvaluateDivideStatement (
  1682. PAML_EXECUTION_CONTEXT Context,
  1683. PAML_STATEMENT Statement
  1684. )
  1685. /*++
  1686. Routine Description:
  1687. This routine evaluates a divide statement.
  1688. Arguments:
  1689. Context - Supplies a pointer to the current AML execution context.
  1690. Statement - Supplies a pointer to the statement to evaluate.
  1691. Return Value:
  1692. Status code.
  1693. --*/
  1694. {
  1695. ULONGLONG Dividend;
  1696. ULONGLONG Divisor;
  1697. PACPI_OBJECT NewArgument;
  1698. ULONGLONG Quotient;
  1699. ULONGLONG Remainder;
  1700. PACPI_OBJECT RemainderObject;
  1701. KSTATUS Status;
  1702. //
  1703. // If not all arguments are acquired, evaluate the previous statement to get
  1704. // the next argument.
  1705. //
  1706. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1707. //
  1708. // Print out the piece of the statement depending on the number of
  1709. // arguments acquired.
  1710. //
  1711. if (Context->PrintStatements != FALSE) {
  1712. if (Context->PreviousStatement == NULL) {
  1713. RtlDebugPrint("Divide (");
  1714. } else if ((Statement->ArgumentsAcquired == 0) ||
  1715. (Statement->ArgumentsAcquired == 1) ||
  1716. (Statement->ArgumentsAcquired == 2)) {
  1717. RtlDebugPrint(", ");
  1718. } else {
  1719. RtlDebugPrint(")");
  1720. }
  1721. }
  1722. if (Context->PreviousStatement == NULL) {
  1723. return STATUS_MORE_PROCESSING_REQUIRED;
  1724. }
  1725. //
  1726. // If not executing, then assume the argument would be there but don't
  1727. // try to dink with it.
  1728. //
  1729. if (Context->ExecuteStatements == FALSE) {
  1730. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  1731. Statement->ArgumentsAcquired += 1;
  1732. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  1733. return STATUS_MORE_PROCESSING_REQUIRED;
  1734. }
  1735. } else {
  1736. NewArgument = Context->PreviousStatement->Reduction;
  1737. if ((Statement->ArgumentsAcquired == 0) ||
  1738. (Statement->ArgumentsAcquired == 1)) {
  1739. //
  1740. // Fail if there is no argument there.
  1741. //
  1742. if (Context->PreviousStatement->Reduction == NULL) {
  1743. return STATUS_ARGUMENT_EXPECTED;
  1744. }
  1745. //
  1746. // Perform an implicit conversion if needed.
  1747. //
  1748. if (NewArgument->Type != AcpiObjectInteger) {
  1749. NewArgument = AcpipConvertObjectType(Context,
  1750. NewArgument,
  1751. AcpiObjectInteger);
  1752. if (NewArgument == NULL) {
  1753. return STATUS_CONVERSION_FAILED;
  1754. }
  1755. //
  1756. // The object is fine, take ownership of it.
  1757. //
  1758. } else {
  1759. AcpipObjectAddReference(NewArgument);
  1760. }
  1761. } else {
  1762. ASSERT((Statement->ArgumentsAcquired == 2) ||
  1763. (Statement->ArgumentsAcquired == 3));
  1764. AcpipObjectAddReference(NewArgument);
  1765. }
  1766. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  1767. Statement->ArgumentsAcquired += 1;
  1768. if (Statement->ArgumentsAcquired < 3) {
  1769. return STATUS_MORE_PROCESSING_REQUIRED;
  1770. }
  1771. }
  1772. }
  1773. //
  1774. // Evaluate the result.
  1775. //
  1776. if (Context->ExecuteStatements == FALSE) {
  1777. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1778. return STATUS_SUCCESS;
  1779. }
  1780. //
  1781. // The first time around, perform the divide and try to store the remainder.
  1782. //
  1783. if (Statement->ArgumentsAcquired == 3) {
  1784. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  1785. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  1786. Dividend = Statement->Argument[0]->U.Integer.Value;
  1787. Divisor = Statement->Argument[1]->U.Integer.Value;
  1788. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  1789. Dividend &= 0xFFFFFFFF;
  1790. Dividend &= 0xFFFFFFFF;
  1791. }
  1792. //
  1793. // Fail to divide by 0, otherwise do the divide.
  1794. //
  1795. if (Divisor == 0) {
  1796. return STATUS_DIVIDE_BY_ZERO;
  1797. }
  1798. Quotient = Dividend / Divisor;
  1799. Remainder = Dividend % Divisor;
  1800. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  1801. Quotient &= 0xFFFFFFFF;
  1802. Remainder &= 0xFFFFFFFF;
  1803. }
  1804. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  1805. AcpiObjectInteger,
  1806. NULL,
  1807. &Quotient,
  1808. sizeof(ULONGLONG));
  1809. if (Statement->Reduction == NULL) {
  1810. return STATUS_UNSUCCESSFUL;
  1811. }
  1812. //
  1813. // Store the remainder if supplied.
  1814. //
  1815. if (Statement->Argument[2] != NULL) {
  1816. RemainderObject = AcpipCreateNamespaceObject(Context,
  1817. AcpiObjectInteger,
  1818. NULL,
  1819. &Remainder,
  1820. sizeof(ULONGLONG));
  1821. if (RemainderObject == NULL) {
  1822. return STATUS_UNSUCCESSFUL;
  1823. }
  1824. Status = AcpipPerformStoreOperation(Context,
  1825. RemainderObject,
  1826. Statement->Argument[2]);
  1827. AcpipObjectReleaseReference(RemainderObject);
  1828. if (!KSUCCESS(Status)) {
  1829. return Status;
  1830. }
  1831. }
  1832. ASSERT(Statement->ArgumentsAcquired < Statement->ArgumentsNeeded);
  1833. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1834. //
  1835. // The second time around store the quotient.
  1836. //
  1837. } else {
  1838. ASSERT(Statement->ArgumentsAcquired == 4);
  1839. //
  1840. // Store the quotient in the target if supplied.
  1841. //
  1842. if (Statement->Argument[3] != NULL) {
  1843. return AcpipPerformStoreOperation(Context,
  1844. Statement->Reduction,
  1845. Statement->Argument[3]);
  1846. }
  1847. }
  1848. return STATUS_SUCCESS;
  1849. }
  1850. KSTATUS
  1851. AcpipEvaluateElseStatement (
  1852. PAML_EXECUTION_CONTEXT Context,
  1853. PAML_STATEMENT Statement
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. This routine evaluates an Else statement.
  1858. Arguments:
  1859. Context - Supplies a pointer to the current AML execution context.
  1860. Statement - Supplies a pointer to the statement to evaluate.
  1861. Return Value:
  1862. Status code.
  1863. --*/
  1864. {
  1865. //
  1866. // If this is the first time through, up the indentation level.
  1867. //
  1868. if (Context->PreviousStatement == NULL) {
  1869. Context->IndentationLevel += 1;
  1870. if (Context->PrintStatements != FALSE) {
  1871. RtlDebugPrint("Else {");
  1872. }
  1873. }
  1874. if (Context->ExecuteStatements != FALSE) {
  1875. //
  1876. // Check the result of the last If statement. Skip over the Else if the
  1877. // IF succeeded.
  1878. //
  1879. if (Context->LastIfStatementResult != FALSE) {
  1880. Context->CurrentOffset = Statement->AdditionalData;
  1881. }
  1882. }
  1883. //
  1884. // If execution is not done with the scope, keep this statement on the
  1885. // stack.
  1886. //
  1887. if (Context->CurrentOffset < Statement->AdditionalData) {
  1888. AcpipPrintIndentedNewLine(Context);
  1889. return STATUS_MORE_PROCESSING_REQUIRED;
  1890. }
  1891. Context->IndentationLevel -= 1;
  1892. if (Context->PrintStatements != FALSE) {
  1893. AcpipPrintIndentedNewLine(Context);
  1894. RtlDebugPrint("}");
  1895. }
  1896. AcpipPrintIndentedNewLine(Context);
  1897. return STATUS_SUCCESS;
  1898. }
  1899. KSTATUS
  1900. AcpipEvaluateEventStatement (
  1901. PAML_EXECUTION_CONTEXT Context,
  1902. PAML_STATEMENT Statement
  1903. )
  1904. /*++
  1905. Routine Description:
  1906. This routine evaluates an Event (creation) statement.
  1907. Arguments:
  1908. Context - Supplies a pointer to the current AML execution context.
  1909. Statement - Supplies a pointer to the statement to evaluate.
  1910. Return Value:
  1911. Status code.
  1912. --*/
  1913. {
  1914. PSTR Name;
  1915. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  1916. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  1917. Name = Statement->Argument[0]->U.String.String;
  1918. if (Context->PrintStatements != FALSE) {
  1919. RtlDebugPrint("Event (%s)", Name);
  1920. }
  1921. if (Context->ExecuteStatements != FALSE) {
  1922. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  1923. AcpiObjectEvent,
  1924. Name,
  1925. NULL,
  1926. 0);
  1927. if (Statement->Reduction == NULL) {
  1928. return STATUS_UNSUCCESSFUL;
  1929. }
  1930. }
  1931. return STATUS_SUCCESS;
  1932. }
  1933. KSTATUS
  1934. AcpipEvaluateExecutingMethodStatement (
  1935. PAML_EXECUTION_CONTEXT Context,
  1936. PAML_STATEMENT Statement
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. This routine evaluates an Executing Method statement. This does not
  1941. translate to a real ACPI opcode, but is a dummy object placed on the
  1942. currently-executing statement stack so that return statements know how
  1943. far to pop back up.
  1944. Arguments:
  1945. Context - Supplies a pointer to the current AML execution context.
  1946. Statement - Supplies a pointer to the statement to evaluate.
  1947. Return Value:
  1948. Status code.
  1949. --*/
  1950. {
  1951. PACPI_OBJECT Method;
  1952. PAML_STATEMENT PreviousStatement;
  1953. KSTATUS Status;
  1954. ULONGLONG Zero;
  1955. ASSERT(Context->ExecuteStatements != FALSE);
  1956. //
  1957. // If the method context to wait for is set, wait until the method context
  1958. // comes back to the original routine.
  1959. //
  1960. if (Statement->AdditionalData2 != (UINTN)NULL) {
  1961. if ((UINTN)Context->CurrentMethod == Statement->AdditionalData2) {
  1962. Statement->Reduction = Context->ReturnValue;
  1963. AcpipObjectAddReference(Statement->Reduction);
  1964. Context->IndentationLevel -= 1;
  1965. if (Context->PrintStatements != FALSE) {
  1966. AcpipPrintIndentedNewLine(Context);
  1967. RtlDebugPrint("}");
  1968. }
  1969. return STATUS_SUCCESS;
  1970. }
  1971. //
  1972. // While not in the spec, folklore has it that an old version of the
  1973. // Windows AML interpreter allowed for AML methods without return
  1974. // statements (even though ACPI said it was required). The behavior
  1975. // instead was that the function returned a constant zero integer.
  1976. // Many BIOSes took advantage of that, so now it basically is part
  1977. // of the spec. If the current function seems to have just finished,
  1978. // then pop its context.
  1979. //
  1980. if (Context->CurrentOffset == Context->AmlCodeSize) {
  1981. if (Context->ReturnValue == NULL) {
  1982. Zero = 0;
  1983. Context->ReturnValue =
  1984. AcpipCreateNamespaceObject(Context,
  1985. AcpiObjectInteger,
  1986. NULL,
  1987. &Zero,
  1988. sizeof(ULONGLONG));
  1989. }
  1990. AcpipPopExecutingStatements(Context, FALSE, FALSE);
  1991. AcpipPopCurrentMethodContext(Context);
  1992. Context->IndentationLevel -= 1;
  1993. if (Context->PrintStatements != FALSE) {
  1994. AcpipPrintIndentedNewLine(Context);
  1995. RtlDebugPrint("}");
  1996. }
  1997. return STATUS_SUCCESS;
  1998. }
  1999. AcpipPrintIndentedNewLine(Context);
  2000. return STATUS_MORE_PROCESSING_REQUIRED;
  2001. }
  2002. PreviousStatement = Context->PreviousStatement;
  2003. //
  2004. // The evaluate executing method statement is special in that it will not
  2005. // get called once with a previous statement of NULL. Since it is a side
  2006. // effect of another statement spitting out a reduction of type method, this
  2007. // statement always gets passed a previous statement. The first time it's
  2008. // called, the previous statement should have a pointer to the method
  2009. // object. Use that to determine the argument count. Additional data was
  2010. // initialized to 0 to indicate the first time this statement is being
  2011. // evaluated.
  2012. //
  2013. if (Statement->AdditionalData == (UINTN)NULL) {
  2014. ASSERT((PreviousStatement != NULL) &&
  2015. (PreviousStatement->Reduction != NULL) &&
  2016. (PreviousStatement->Reduction->Type == AcpiObjectMethod));
  2017. Method = PreviousStatement->Reduction;
  2018. Statement->AdditionalData = (UINTN)Method;
  2019. Statement->ArgumentsNeeded = Method->U.Method.ArgumentCount;
  2020. if (Context->PrintStatements != FALSE) {
  2021. RtlDebugPrint(" (");
  2022. }
  2023. if (Statement->ArgumentsNeeded != 0) {
  2024. return STATUS_MORE_PROCESSING_REQUIRED;
  2025. }
  2026. }
  2027. //
  2028. // If not all arguments are acquired, wait for them to come in, and collect
  2029. // 'em.
  2030. //
  2031. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2032. if ((PreviousStatement == NULL) ||
  2033. (PreviousStatement->Reduction == NULL)) {
  2034. return STATUS_ARGUMENT_EXPECTED;
  2035. }
  2036. Statement->Argument[Statement->ArgumentsAcquired] =
  2037. PreviousStatement->Reduction;
  2038. Statement->ArgumentsAcquired += 1;
  2039. AcpipObjectAddReference(PreviousStatement->Reduction);
  2040. }
  2041. //
  2042. // If all arguments are still not acquired, wait for more.
  2043. //
  2044. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2045. if (Context->PrintStatements != FALSE) {
  2046. RtlDebugPrint(", ");
  2047. }
  2048. return STATUS_MORE_PROCESSING_REQUIRED;
  2049. }
  2050. Context->IndentationLevel += 1;
  2051. if (Context->PrintStatements != FALSE) {
  2052. RtlDebugPrint(") {");
  2053. AcpipPrintIndentedNewLine(Context);
  2054. }
  2055. //
  2056. // Store the current method context in Additional Data 2, and use that
  2057. // to determine when to complete this statement (complete the statement
  2058. // when this context comes back.
  2059. //
  2060. Statement->AdditionalData2 = (UINTN)Context->CurrentMethod;
  2061. //
  2062. // Push the method execution context on as the current context.
  2063. //
  2064. Method = (PVOID)(UINTN)Statement->AdditionalData;
  2065. Status = AcpipPushMethodOnExecutionContext(
  2066. Context,
  2067. Method,
  2068. Method->U.Method.OsMutex,
  2069. Method->U.Method.IntegerWidthIs32,
  2070. Method->U.Method.AmlCode,
  2071. Method->U.Method.AmlCodeSize,
  2072. Statement->ArgumentsNeeded,
  2073. Statement->Argument);
  2074. if (!KSUCCESS(Status)) {
  2075. return Status;
  2076. }
  2077. return STATUS_MORE_PROCESSING_REQUIRED;
  2078. }
  2079. KSTATUS
  2080. AcpipEvaluateFatalStatement (
  2081. PAML_EXECUTION_CONTEXT Context,
  2082. PAML_STATEMENT Statement
  2083. )
  2084. /*++
  2085. Routine Description:
  2086. This routine evaluates a fatal execution statement. This will stop the
  2087. operating system.
  2088. Arguments:
  2089. Context - Supplies a pointer to the current AML execution context.
  2090. Statement - Supplies a pointer to the statement to evaluate.
  2091. Return Value:
  2092. Status code.
  2093. --*/
  2094. {
  2095. PUCHAR DataPointer;
  2096. ULONGLONG FatalArgument;
  2097. ULONG FatalCode;
  2098. UCHAR FatalType;
  2099. PACPI_OBJECT NewArgument;
  2100. DataPointer = (PUCHAR)Context->AmlCode + Statement->AdditionalData;
  2101. FatalType = *DataPointer;
  2102. FatalCode = *(PULONG)(DataPointer + 1);
  2103. //
  2104. // If not all arguments are acquired, evaluate the previous statement to get
  2105. // the next argument.
  2106. //
  2107. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2108. //
  2109. // Print out the piece of the statement depending on the number of
  2110. // arguments acquired.
  2111. //
  2112. if (Context->PrintStatements != FALSE) {
  2113. if (Context->PreviousStatement == NULL) {
  2114. RtlDebugPrint("Fatal (%x, %x, ", FatalType, FatalCode);
  2115. } else {
  2116. RtlDebugPrint(")");
  2117. }
  2118. }
  2119. if (Context->PreviousStatement == NULL) {
  2120. return STATUS_MORE_PROCESSING_REQUIRED;
  2121. }
  2122. //
  2123. // If not executing, then assume the argument would be there but don't
  2124. // try to dink with it.
  2125. //
  2126. if (Context->ExecuteStatements == FALSE) {
  2127. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2128. Statement->ArgumentsAcquired += 1;
  2129. } else {
  2130. NewArgument = Context->PreviousStatement->Reduction;
  2131. ASSERT(Statement->ArgumentsAcquired == 0);
  2132. //
  2133. // Convert the argument if it is there. The argument is
  2134. // technically required, but since this is a fatal error, be a
  2135. // bit more forgiving.
  2136. //
  2137. if (Context->PreviousStatement->Reduction != NULL) {
  2138. //
  2139. // Perform an implicit conversion if needed.
  2140. //
  2141. if (NewArgument->Type != AcpiObjectInteger) {
  2142. NewArgument = AcpipConvertObjectType(Context,
  2143. NewArgument,
  2144. AcpiObjectInteger);
  2145. //
  2146. // The object is fine, take ownership of it.
  2147. //
  2148. } else {
  2149. AcpipObjectAddReference(NewArgument);
  2150. }
  2151. }
  2152. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2153. Statement->ArgumentsAcquired += 1;
  2154. }
  2155. }
  2156. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2157. //
  2158. // Die... so sad.
  2159. //
  2160. FatalArgument = 0;
  2161. if ((Statement->Argument[0] != NULL) &&
  2162. (Statement->Argument[0]->Type == AcpiObjectInteger)) {
  2163. FatalArgument = Statement->Argument[0]->U.Integer.Value;
  2164. }
  2165. RtlDebugPrint("\n\n*** ACPI Fatal Error ***\n"
  2166. "Type: 0x%x, Code: 0x%x, Argument: 0x%I64x\n"
  2167. "Execution Context: 0x%x\n",
  2168. FatalType,
  2169. FatalCode,
  2170. FatalArgument,
  2171. Context);
  2172. AcpipFatalError(ACPI_CRASH_FATAL_INSTRUCTION,
  2173. FatalType,
  2174. FatalCode,
  2175. FatalArgument);
  2176. //
  2177. // Execution will never get here, but the compiler will get sassy if there's
  2178. // just nothing.
  2179. //
  2180. return STATUS_SUCCESS;
  2181. }
  2182. KSTATUS
  2183. AcpipEvaluateFieldStatement (
  2184. PAML_EXECUTION_CONTEXT Context,
  2185. PAML_STATEMENT Statement
  2186. )
  2187. /*++
  2188. Routine Description:
  2189. This routine evaluates a Field (in an Operation Region) statement.
  2190. Arguments:
  2191. Context - Supplies a pointer to the current AML execution context.
  2192. Statement - Supplies a pointer to the statement to evaluate.
  2193. Return Value:
  2194. STATUS_SUCCESS always.
  2195. --*/
  2196. {
  2197. PACPI_OBJECT OperationRegion;
  2198. KSTATUS Status;
  2199. OperationRegion = NULL;
  2200. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2201. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  2202. if (Context->ExecuteStatements != FALSE) {
  2203. //
  2204. // Get the operation region this Field refers to.
  2205. //
  2206. OperationRegion = AcpipGetNamespaceObject(
  2207. Statement->Argument[0]->U.String.String,
  2208. Context->CurrentScope);
  2209. if (OperationRegion == NULL) {
  2210. return STATUS_NOT_FOUND;
  2211. }
  2212. }
  2213. //
  2214. // Parse the field list.
  2215. //
  2216. Status = AcpipParseFieldList(Context,
  2217. Statement->Type,
  2218. OperationRegion,
  2219. NULL,
  2220. NULL,
  2221. NULL,
  2222. NULL,
  2223. Statement->AdditionalData,
  2224. (UCHAR)Statement->AdditionalData2);
  2225. return Status;
  2226. }
  2227. KSTATUS
  2228. AcpipEvaluateFindSetBitStatement (
  2229. PAML_EXECUTION_CONTEXT Context,
  2230. PAML_STATEMENT Statement
  2231. )
  2232. /*++
  2233. Routine Description:
  2234. This routine evaluates a find set left bit or find set right bit statement.
  2235. Arguments:
  2236. Context - Supplies a pointer to the current AML execution context.
  2237. Statement - Supplies a pointer to the statement to evaluate.
  2238. Return Value:
  2239. Status code.
  2240. --*/
  2241. {
  2242. ULONGLONG Mask;
  2243. PACPI_OBJECT NewArgument;
  2244. ULONGLONG Result;
  2245. ULONGLONG Value;
  2246. //
  2247. // If not all arguments are acquired, evaluate the previous statement to get
  2248. // the next argument.
  2249. //
  2250. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2251. //
  2252. // Print out the piece of the statement depending on the number of
  2253. // arguments acquired.
  2254. //
  2255. if (Context->PrintStatements != FALSE) {
  2256. if (Context->PreviousStatement == NULL) {
  2257. switch (Statement->Type) {
  2258. case AmlStatementFindSetLeftBit:
  2259. RtlDebugPrint("FindSetLeftBit (");
  2260. break;
  2261. case AmlStatementFindSetRightBit:
  2262. RtlDebugPrint("FindSetRightBit (");
  2263. break;
  2264. default:
  2265. ASSERT(FALSE);
  2266. return STATUS_NOT_SUPPORTED;
  2267. }
  2268. } else if (Statement->ArgumentsAcquired == 0) {
  2269. RtlDebugPrint(", ");
  2270. } else {
  2271. RtlDebugPrint(")");
  2272. }
  2273. }
  2274. if (Context->PreviousStatement == NULL) {
  2275. return STATUS_MORE_PROCESSING_REQUIRED;
  2276. }
  2277. //
  2278. // If not executing, then assume the argument would be there but don't
  2279. // try to dink with it.
  2280. //
  2281. if (Context->ExecuteStatements == FALSE) {
  2282. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2283. Statement->ArgumentsAcquired += 1;
  2284. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2285. return STATUS_MORE_PROCESSING_REQUIRED;
  2286. }
  2287. } else {
  2288. NewArgument = Context->PreviousStatement->Reduction;
  2289. if (Statement->ArgumentsAcquired == 0) {
  2290. //
  2291. // Fail if there is no argument there.
  2292. //
  2293. if (Context->PreviousStatement->Reduction == NULL) {
  2294. return STATUS_ARGUMENT_EXPECTED;
  2295. }
  2296. //
  2297. // Perform an implicit conversion if needed.
  2298. //
  2299. if (NewArgument->Type != AcpiObjectInteger) {
  2300. NewArgument = AcpipConvertObjectType(Context,
  2301. NewArgument,
  2302. AcpiObjectInteger);
  2303. if (NewArgument == NULL) {
  2304. return STATUS_CONVERSION_FAILED;
  2305. }
  2306. //
  2307. // The object is fine, take ownership of it.
  2308. //
  2309. } else {
  2310. AcpipObjectAddReference(NewArgument);
  2311. }
  2312. } else {
  2313. ASSERT(Statement->ArgumentsAcquired == 1);
  2314. AcpipObjectAddReference(NewArgument);
  2315. }
  2316. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2317. Statement->ArgumentsAcquired += 1;
  2318. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2319. return STATUS_MORE_PROCESSING_REQUIRED;
  2320. }
  2321. }
  2322. }
  2323. //
  2324. // Evaluate the result.
  2325. //
  2326. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2327. Statement->Reduction = NULL;
  2328. if (Context->ExecuteStatements == FALSE) {
  2329. return STATUS_SUCCESS;
  2330. }
  2331. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  2332. Value = Statement->Argument[0]->U.Integer.Value;
  2333. if (Value != 0) {
  2334. if (Statement->Type == AmlStatementFindSetLeftBit) {
  2335. Result = 64;
  2336. Mask = 0x8000000000000000ULL;
  2337. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  2338. Result = 32;
  2339. Mask = 0x80000000;
  2340. ASSERT(Value <= MAX_ULONG);
  2341. }
  2342. while ((Value & Mask) == 0) {
  2343. Value = Value << 1;
  2344. Result -= 1;
  2345. }
  2346. } else {
  2347. ASSERT(Statement->Type == AmlStatementFindSetRightBit);
  2348. Mask = 1;
  2349. Result = 1;
  2350. while ((Value & Mask) == 0) {
  2351. Value = Value >> 1;
  2352. Result += 1;
  2353. }
  2354. }
  2355. }
  2356. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  2357. AcpiObjectInteger,
  2358. NULL,
  2359. &Result,
  2360. sizeof(ULONGLONG));
  2361. if (Statement->Reduction == NULL) {
  2362. return STATUS_UNSUCCESSFUL;
  2363. }
  2364. //
  2365. // Store the result in the target if supplied.
  2366. //
  2367. if (Statement->Argument[1] != NULL) {
  2368. return AcpipPerformStoreOperation(Context,
  2369. Statement->Reduction,
  2370. Statement->Argument[1]);
  2371. }
  2372. return STATUS_SUCCESS;
  2373. }
  2374. KSTATUS
  2375. AcpipEvaluateIfStatement (
  2376. PAML_EXECUTION_CONTEXT Context,
  2377. PAML_STATEMENT Statement
  2378. )
  2379. /*++
  2380. Routine Description:
  2381. This routine evaluates an If statement.
  2382. Arguments:
  2383. Context - Supplies a pointer to the current AML execution context.
  2384. Statement - Supplies a pointer to the statement to evaluate.
  2385. Return Value:
  2386. Status code.
  2387. --*/
  2388. {
  2389. PACPI_OBJECT NewArgument;
  2390. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2391. //
  2392. // Print out the piece of the statement depending on the number of
  2393. // arguments acquired.
  2394. //
  2395. if (Context->PrintStatements != FALSE) {
  2396. if (Context->PreviousStatement == NULL) {
  2397. RtlDebugPrint("If (");
  2398. } else {
  2399. ASSERT(Statement->ArgumentsAcquired == 0);
  2400. RtlDebugPrint(") {");
  2401. }
  2402. }
  2403. if (Context->PreviousStatement == NULL) {
  2404. Context->IndentationLevel += 1;
  2405. return STATUS_MORE_PROCESSING_REQUIRED;
  2406. }
  2407. //
  2408. // If not executing, then assume the argument would be there but don't
  2409. // try to dink with it.
  2410. //
  2411. if (Context->ExecuteStatements == FALSE) {
  2412. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2413. } else {
  2414. NewArgument = Context->PreviousStatement->Reduction;
  2415. //
  2416. // Fail if there is no argument there.
  2417. //
  2418. if (Context->PreviousStatement->Reduction == NULL) {
  2419. return STATUS_ARGUMENT_EXPECTED;
  2420. }
  2421. //
  2422. // Perform an implicit conversion if needed.
  2423. //
  2424. if (NewArgument->Type != AcpiObjectInteger) {
  2425. NewArgument = AcpipConvertObjectType(Context,
  2426. NewArgument,
  2427. AcpiObjectInteger);
  2428. if (NewArgument == NULL) {
  2429. return STATUS_CONVERSION_FAILED;
  2430. }
  2431. //
  2432. // The object is fine, take ownership of it.
  2433. //
  2434. } else {
  2435. AcpipObjectAddReference(NewArgument);
  2436. }
  2437. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2438. }
  2439. Statement->ArgumentsAcquired += 1;
  2440. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2441. if (Context->ExecuteStatements != FALSE) {
  2442. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  2443. //
  2444. // Evaluate the if statement by skipping the package length if it's
  2445. // zero.
  2446. //
  2447. Statement->AdditionalData2 = TRUE;
  2448. if (Statement->Argument[0]->U.Integer.Value == 0) {
  2449. Statement->AdditionalData2 = FALSE;
  2450. Context->CurrentOffset = Statement->AdditionalData;
  2451. }
  2452. }
  2453. }
  2454. //
  2455. // If execution is not done with the scope, keep this statement on the
  2456. // stack.
  2457. //
  2458. if (Context->CurrentOffset < Statement->AdditionalData) {
  2459. AcpipPrintIndentedNewLine(Context);
  2460. return STATUS_MORE_PROCESSING_REQUIRED;
  2461. }
  2462. Context->IndentationLevel -= 1;
  2463. if (Context->PrintStatements != FALSE) {
  2464. AcpipPrintIndentedNewLine(Context);
  2465. RtlDebugPrint("}");
  2466. }
  2467. AcpipPrintIndentedNewLine(Context);
  2468. //
  2469. // Save the result of the If statement into the context so that an Else
  2470. // can be properly evaluated if it's coming up next.
  2471. //
  2472. if (Statement->AdditionalData2 != FALSE) {
  2473. Context->LastIfStatementResult = TRUE;
  2474. } else {
  2475. Context->LastIfStatementResult = FALSE;
  2476. }
  2477. return STATUS_SUCCESS;
  2478. }
  2479. KSTATUS
  2480. AcpipEvaluateIncrementOrDecrementStatement (
  2481. PAML_EXECUTION_CONTEXT Context,
  2482. PAML_STATEMENT Statement
  2483. )
  2484. /*++
  2485. Routine Description:
  2486. This routine evaluates an Increment or Decrement statement.
  2487. Arguments:
  2488. Context - Supplies a pointer to the current AML execution context.
  2489. Statement - Supplies a pointer to the statement to evaluate.
  2490. Return Value:
  2491. Status code.
  2492. --*/
  2493. {
  2494. PACPI_OBJECT IntegerObject;
  2495. PACPI_OBJECT NewArgument;
  2496. //
  2497. // Gather arguments if needed.
  2498. //
  2499. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2500. if (Context->PrintStatements != FALSE) {
  2501. if (Context->PreviousStatement == NULL) {
  2502. if (Statement->Type == AmlStatementIncrement) {
  2503. RtlDebugPrint("Increment (");
  2504. } else {
  2505. ASSERT(Statement->Type == AmlStatementDecrement);
  2506. RtlDebugPrint("Decrement (");
  2507. }
  2508. } else {
  2509. RtlDebugPrint(")");
  2510. }
  2511. }
  2512. //
  2513. // If there is no previous statement, wait for the argument to come in.
  2514. //
  2515. if (Context->PreviousStatement == NULL) {
  2516. return STATUS_MORE_PROCESSING_REQUIRED;
  2517. }
  2518. //
  2519. // If not executing, assume the argument would be there, and move on.
  2520. //
  2521. if (Context->ExecuteStatements == FALSE) {
  2522. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2523. Statement->ArgumentsAcquired += 1;
  2524. //
  2525. // Increment the reference count on the object (assuming it's there).
  2526. //
  2527. } else {
  2528. NewArgument = Context->PreviousStatement->Reduction;
  2529. if (NewArgument == NULL) {
  2530. return STATUS_ARGUMENT_EXPECTED;
  2531. }
  2532. AcpipObjectAddReference(NewArgument);
  2533. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2534. Statement->ArgumentsAcquired += 1;
  2535. }
  2536. }
  2537. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2538. if (Context->ExecuteStatements != FALSE) {
  2539. //
  2540. // Perform an implicit conversion if necessary.
  2541. //
  2542. if (Statement->Argument[0]->Type != AcpiObjectInteger) {
  2543. IntegerObject = AcpipConvertObjectType(Context,
  2544. Statement->Argument[0],
  2545. AcpiObjectInteger);
  2546. if (IntegerObject == NULL) {
  2547. return STATUS_CONVERSION_FAILED;
  2548. }
  2549. } else {
  2550. IntegerObject = Statement->Argument[0];
  2551. AcpipObjectAddReference(IntegerObject);
  2552. }
  2553. //
  2554. // Do the increment or decrement.
  2555. //
  2556. if (Statement->Type == AmlStatementIncrement) {
  2557. IntegerObject->U.Integer.Value += 1;
  2558. } else {
  2559. IntegerObject->U.Integer.Value -= 1;
  2560. }
  2561. //
  2562. // Store the result back if this is not the argument. This also implies
  2563. // a conversion back to the original type is necessary.
  2564. //
  2565. Statement->Reduction = IntegerObject;
  2566. if (IntegerObject != Statement->Argument[0]) {
  2567. AcpipPerformStoreOperation(Context,
  2568. IntegerObject,
  2569. Statement->Argument[0]);
  2570. }
  2571. }
  2572. return STATUS_SUCCESS;
  2573. }
  2574. KSTATUS
  2575. AcpipEvaluateIndexFieldStatement (
  2576. PAML_EXECUTION_CONTEXT Context,
  2577. PAML_STATEMENT Statement
  2578. )
  2579. /*++
  2580. Routine Description:
  2581. This routine evaluates an IndexField (in an Operation Region) statement.
  2582. Arguments:
  2583. Context - Supplies a pointer to the current AML execution context.
  2584. Statement - Supplies a pointer to the statement to evaluate.
  2585. Return Value:
  2586. STATUS_SUCCESS always.
  2587. --*/
  2588. {
  2589. PACPI_OBJECT DataRegister;
  2590. PACPI_OBJECT IndexRegister;
  2591. KSTATUS Status;
  2592. IndexRegister = NULL;
  2593. DataRegister = NULL;
  2594. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2595. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  2596. ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
  2597. if (Context->ExecuteStatements != FALSE) {
  2598. //
  2599. // Get the Index field object.
  2600. //
  2601. IndexRegister = AcpipGetNamespaceObject(
  2602. Statement->Argument[0]->U.String.String,
  2603. Context->CurrentScope);
  2604. if (IndexRegister == NULL) {
  2605. return STATUS_NOT_FOUND;
  2606. }
  2607. //
  2608. // Get the Data field object.
  2609. //
  2610. DataRegister = AcpipGetNamespaceObject(
  2611. Statement->Argument[1]->U.String.String,
  2612. Context->CurrentScope);
  2613. if (DataRegister == NULL) {
  2614. return STATUS_NOT_FOUND;
  2615. }
  2616. }
  2617. //
  2618. // Parse the field list.
  2619. //
  2620. Status = AcpipParseFieldList(Context,
  2621. Statement->Type,
  2622. NULL,
  2623. NULL,
  2624. NULL,
  2625. IndexRegister,
  2626. DataRegister,
  2627. Statement->AdditionalData,
  2628. (UCHAR)Statement->AdditionalData2);
  2629. return Status;
  2630. }
  2631. KSTATUS
  2632. AcpipEvaluateIndexStatement (
  2633. PAML_EXECUTION_CONTEXT Context,
  2634. PAML_STATEMENT Statement
  2635. )
  2636. /*++
  2637. Routine Description:
  2638. This routine evaluates an Index statement, which creates a reference to the
  2639. nth object in a buffer, string, or package.
  2640. Arguments:
  2641. Context - Supplies a pointer to the current AML execution context.
  2642. Statement - Supplies a pointer to the statement to evaluate.
  2643. Return Value:
  2644. Status code.
  2645. --*/
  2646. {
  2647. ACPI_ALIAS_OBJECT Alias;
  2648. ACPI_OBJECT_TYPE ArgumentType;
  2649. ACPI_BUFFER_FIELD_OBJECT BufferField;
  2650. PACPI_OBJECT NewArgument;
  2651. ULONG PackageIndex;
  2652. KSTATUS Status;
  2653. //
  2654. // If not all arguments are acquired, evaluate the previous statement to get
  2655. // the next argument.
  2656. //
  2657. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2658. //
  2659. // Print out the piece of the statement depending on the number of
  2660. // arguments acquired.
  2661. //
  2662. if (Context->PrintStatements != FALSE) {
  2663. if (Context->PreviousStatement == NULL) {
  2664. RtlDebugPrint("Index (");
  2665. } else if ((Statement->ArgumentsAcquired == 0) ||
  2666. (Statement->ArgumentsAcquired == 1)) {
  2667. RtlDebugPrint(", ");
  2668. } else {
  2669. RtlDebugPrint(")");
  2670. }
  2671. }
  2672. if (Context->PreviousStatement == NULL) {
  2673. return STATUS_MORE_PROCESSING_REQUIRED;
  2674. }
  2675. //
  2676. // If not executing, then assume the argument would be there but don't
  2677. // try to dink with it.
  2678. //
  2679. if (Context->ExecuteStatements == FALSE) {
  2680. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2681. Statement->ArgumentsAcquired += 1;
  2682. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2683. return STATUS_MORE_PROCESSING_REQUIRED;
  2684. }
  2685. } else {
  2686. NewArgument = Context->PreviousStatement->Reduction;
  2687. if ((Statement->ArgumentsAcquired == 0) ||
  2688. (Statement->ArgumentsAcquired == 1)) {
  2689. //
  2690. // Fail if there is no argument there.
  2691. //
  2692. if (Context->PreviousStatement->Reduction == NULL) {
  2693. return STATUS_ARGUMENT_EXPECTED;
  2694. }
  2695. //
  2696. // The first argument must be a buffer, package, or string.
  2697. //
  2698. ArgumentType = AcpiObjectUninitialized;
  2699. if (Statement->ArgumentsAcquired == 0) {
  2700. if ((NewArgument->Type != AcpiObjectBuffer) &&
  2701. (NewArgument->Type != AcpiObjectPackage) &&
  2702. (NewArgument->Type != AcpiObjectString)) {
  2703. ArgumentType = AcpiObjectBuffer;
  2704. }
  2705. //
  2706. // The second object must evaluate to an integer.
  2707. //
  2708. } else if (NewArgument->Type != AcpiObjectInteger) {
  2709. ArgumentType = AcpiObjectInteger;
  2710. }
  2711. //
  2712. // Perform an implicit conversion if needed.
  2713. //
  2714. if (ArgumentType != AcpiObjectUninitialized) {
  2715. NewArgument = AcpipConvertObjectType(Context,
  2716. NewArgument,
  2717. ArgumentType);
  2718. if (NewArgument == NULL) {
  2719. return STATUS_CONVERSION_FAILED;
  2720. }
  2721. //
  2722. // The object is fine, take ownership of it.
  2723. //
  2724. } else {
  2725. AcpipObjectAddReference(NewArgument);
  2726. }
  2727. } else {
  2728. ASSERT(Statement->ArgumentsAcquired == 2);
  2729. if (NewArgument != NULL) {
  2730. AcpipObjectAddReference(NewArgument);
  2731. }
  2732. }
  2733. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2734. Statement->ArgumentsAcquired += 1;
  2735. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2736. return STATUS_MORE_PROCESSING_REQUIRED;
  2737. }
  2738. }
  2739. }
  2740. //
  2741. // Evaluate the result.
  2742. //
  2743. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2744. Statement->Reduction = NULL;
  2745. if (Context->ExecuteStatements == FALSE) {
  2746. return STATUS_SUCCESS;
  2747. }
  2748. ASSERT((Statement->Argument[0]->Type == AcpiObjectBuffer) ||
  2749. (Statement->Argument[0]->Type == AcpiObjectString) ||
  2750. (Statement->Argument[0]->Type == AcpiObjectPackage));
  2751. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  2752. //
  2753. // For strings, create a field that points into the string.
  2754. //
  2755. if ((Statement->Argument[0]->Type == AcpiObjectString) ||
  2756. (Statement->Argument[0]->Type == AcpiObjectBuffer)) {
  2757. RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
  2758. BufferField.DestinationObject = Statement->Argument[0];
  2759. BufferField.BitOffset =
  2760. Statement->Argument[1]->U.Integer.Value * BITS_PER_BYTE;
  2761. BufferField.BitLength = BITS_PER_BYTE;
  2762. Statement->Reduction = AcpipCreateNamespaceObject(
  2763. Context,
  2764. AcpiObjectBufferField,
  2765. NULL,
  2766. &BufferField,
  2767. sizeof(ACPI_BUFFER_FIELD_OBJECT));
  2768. } else if (Statement->Argument[0]->Type == AcpiObjectPackage) {
  2769. RtlZeroMemory(&Alias, sizeof(ACPI_ALIAS_OBJECT));
  2770. PackageIndex = (ULONG)Statement->Argument[1]->U.Integer.Value;
  2771. Alias.DestinationObject = AcpipGetPackageObject(Statement->Argument[0],
  2772. PackageIndex,
  2773. TRUE);
  2774. if (Alias.DestinationObject == NULL) {
  2775. return STATUS_NOT_FOUND;
  2776. }
  2777. Statement->Reduction = AcpipCreateNamespaceObject(
  2778. Context,
  2779. AcpiObjectAlias,
  2780. NULL,
  2781. &Alias,
  2782. sizeof(ACPI_ALIAS_OBJECT));
  2783. }
  2784. if (Statement->Reduction == NULL) {
  2785. return STATUS_UNSUCCESSFUL;
  2786. }
  2787. //
  2788. // Store the result in the target if supplied.
  2789. //
  2790. if (Statement->Argument[2] != NULL) {
  2791. Status = AcpipPerformStoreOperation(Context,
  2792. Statement->Reduction,
  2793. Statement->Argument[2]);
  2794. return Status;
  2795. }
  2796. return STATUS_SUCCESS;
  2797. }
  2798. KSTATUS
  2799. AcpipEvaluateIntegerArithmeticStatement (
  2800. PAML_EXECUTION_CONTEXT Context,
  2801. PAML_STATEMENT Statement
  2802. )
  2803. /*++
  2804. Routine Description:
  2805. This routine evaluates simple arithmetic operations that take two operands
  2806. and a target.
  2807. Arguments:
  2808. Context - Supplies a pointer to the current AML execution context.
  2809. Statement - Supplies a pointer to the statement to evaluate.
  2810. Return Value:
  2811. Status code.
  2812. --*/
  2813. {
  2814. PACPI_OBJECT NewArgument;
  2815. ULONGLONG Operand1;
  2816. ULONGLONG Operand2;
  2817. ULONGLONG ResultValue;
  2818. //
  2819. // If not all arguments are acquired, evaluate the previous statement to get
  2820. // the next argument.
  2821. //
  2822. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2823. //
  2824. // Print out the piece of the statement depending on the number of
  2825. // arguments acquired.
  2826. //
  2827. if (Context->PrintStatements != FALSE) {
  2828. if (Context->PreviousStatement == NULL) {
  2829. switch (Statement->Type) {
  2830. case AmlStatementAdd:
  2831. RtlDebugPrint("Add (");
  2832. break;
  2833. case AmlStatementAnd:
  2834. RtlDebugPrint("And (");
  2835. break;
  2836. case AmlStatementMod:
  2837. RtlDebugPrint("Mod (");
  2838. break;
  2839. case AmlStatementMultiply:
  2840. RtlDebugPrint("Multiply (");
  2841. break;
  2842. case AmlStatementNand:
  2843. RtlDebugPrint("Nand (");
  2844. break;
  2845. case AmlStatementNor:
  2846. RtlDebugPrint("Nor (");
  2847. break;
  2848. case AmlStatementOr:
  2849. RtlDebugPrint("Or (");
  2850. break;
  2851. case AmlStatementSubtract:
  2852. RtlDebugPrint("Subtract (");
  2853. break;
  2854. case AmlStatementShiftLeft:
  2855. RtlDebugPrint("ShiftLeft (");
  2856. break;
  2857. case AmlStatementShiftRight:
  2858. RtlDebugPrint("ShiftRight (");
  2859. break;
  2860. case AmlStatementXor:
  2861. RtlDebugPrint("XOr (");
  2862. break;
  2863. default:
  2864. ASSERT(FALSE);
  2865. return STATUS_NOT_SUPPORTED;
  2866. }
  2867. } else if ((Statement->ArgumentsAcquired == 0) ||
  2868. (Statement->ArgumentsAcquired == 1)) {
  2869. RtlDebugPrint(", ");
  2870. } else {
  2871. RtlDebugPrint(")");
  2872. }
  2873. }
  2874. if (Context->PreviousStatement == NULL) {
  2875. return STATUS_MORE_PROCESSING_REQUIRED;
  2876. }
  2877. //
  2878. // If not executing, then assume the argument would be there but don't
  2879. // try to dink with it.
  2880. //
  2881. if (Context->ExecuteStatements == FALSE) {
  2882. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  2883. Statement->ArgumentsAcquired += 1;
  2884. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2885. return STATUS_MORE_PROCESSING_REQUIRED;
  2886. }
  2887. } else {
  2888. NewArgument = Context->PreviousStatement->Reduction;
  2889. if ((Statement->ArgumentsAcquired == 0) ||
  2890. (Statement->ArgumentsAcquired == 1)) {
  2891. //
  2892. // Fail if there is no argument there.
  2893. //
  2894. if (Context->PreviousStatement->Reduction == NULL) {
  2895. return STATUS_ARGUMENT_EXPECTED;
  2896. }
  2897. //
  2898. // Perform an implicit conversion if needed.
  2899. //
  2900. if (NewArgument->Type != AcpiObjectInteger) {
  2901. NewArgument = AcpipConvertObjectType(Context,
  2902. NewArgument,
  2903. AcpiObjectInteger);
  2904. if (NewArgument == NULL) {
  2905. return STATUS_CONVERSION_FAILED;
  2906. }
  2907. //
  2908. // The object is fine, take ownership of it.
  2909. //
  2910. } else {
  2911. AcpipObjectAddReference(NewArgument);
  2912. }
  2913. } else {
  2914. ASSERT(Statement->ArgumentsAcquired == 2);
  2915. if (NewArgument != NULL) {
  2916. AcpipObjectAddReference(NewArgument);
  2917. }
  2918. }
  2919. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  2920. Statement->ArgumentsAcquired += 1;
  2921. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  2922. return STATUS_MORE_PROCESSING_REQUIRED;
  2923. }
  2924. }
  2925. }
  2926. //
  2927. // Evaluate the result.
  2928. //
  2929. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  2930. Statement->Reduction = NULL;
  2931. if (Context->ExecuteStatements == FALSE) {
  2932. return STATUS_SUCCESS;
  2933. }
  2934. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  2935. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  2936. Operand1 = Statement->Argument[0]->U.Integer.Value;
  2937. Operand2 = Statement->Argument[1]->U.Integer.Value;
  2938. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  2939. Operand1 &= 0xFFFFFFFF;
  2940. Operand2 &= 0xFFFFFFFF;
  2941. }
  2942. switch (Statement->Type) {
  2943. case AmlStatementAdd:
  2944. ResultValue = Operand1 + Operand2;
  2945. break;
  2946. case AmlStatementAnd:
  2947. ResultValue = Operand1 & Operand2;
  2948. break;
  2949. case AmlStatementMod:
  2950. if (Operand2 == 0) {
  2951. return STATUS_DIVIDE_BY_ZERO;
  2952. }
  2953. ResultValue = Operand1 % Operand2;
  2954. break;
  2955. case AmlStatementMultiply:
  2956. ResultValue = Operand1 * Operand2;
  2957. break;
  2958. case AmlStatementNand:
  2959. ResultValue = ~(Operand1 & Operand2);
  2960. break;
  2961. case AmlStatementNor:
  2962. ResultValue = ~(Operand1 | Operand2);
  2963. break;
  2964. case AmlStatementOr:
  2965. ResultValue = Operand1 | Operand2;
  2966. break;
  2967. case AmlStatementSubtract:
  2968. ResultValue = Operand1 - Operand2;
  2969. break;
  2970. case AmlStatementShiftLeft:
  2971. ResultValue = Operand1 << Operand2;
  2972. break;
  2973. case AmlStatementShiftRight:
  2974. ResultValue = Operand1 >> Operand2;
  2975. break;
  2976. case AmlStatementXor:
  2977. ResultValue = Operand1 ^ Operand2;
  2978. break;
  2979. default:
  2980. ASSERT(FALSE);
  2981. return STATUS_NOT_SUPPORTED;
  2982. }
  2983. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  2984. ResultValue &= 0xFFFFFFFF;
  2985. }
  2986. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  2987. AcpiObjectInteger,
  2988. NULL,
  2989. &ResultValue,
  2990. sizeof(ULONGLONG));
  2991. if (Statement->Reduction == NULL) {
  2992. return STATUS_UNSUCCESSFUL;
  2993. }
  2994. //
  2995. // Store the result in the target if supplied.
  2996. //
  2997. if (Statement->Argument[2] != NULL) {
  2998. return AcpipPerformStoreOperation(Context,
  2999. Statement->Reduction,
  3000. Statement->Argument[2]);
  3001. }
  3002. return STATUS_SUCCESS;
  3003. }
  3004. KSTATUS
  3005. AcpipEvaluateIntegerStatement (
  3006. PAML_EXECUTION_CONTEXT Context,
  3007. PAML_STATEMENT Statement
  3008. )
  3009. /*++
  3010. Routine Description:
  3011. This routine evaluates statements that take no arguments and generate an
  3012. integer output. This includes the constant statements Zero, One, and Ones,
  3013. as well as the AML Revision and Timer statement.
  3014. Arguments:
  3015. Context - Supplies a pointer to the current AML execution context.
  3016. Statement - Supplies a pointer to the statement to evaluate.
  3017. Return Value:
  3018. STATUS_SUCCESS almost always.
  3019. STATUS_INVALID_PARAMETER if this routine was called for the wrong statement
  3020. type (an internal error for sure).
  3021. STATUS_UNSUCCESSFUL if a namespace object could not be created.
  3022. --*/
  3023. {
  3024. BOOL PrintParentheses;
  3025. PACPI_OBJECT Reduction;
  3026. ULONGLONG Value;
  3027. Reduction = NULL;
  3028. PrintParentheses = FALSE;
  3029. switch (Statement->Type) {
  3030. case AmlStatementZero:
  3031. Value = 0;
  3032. Reduction = &AcpiZero;
  3033. break;
  3034. case AmlStatementOne:
  3035. Value = 1;
  3036. Reduction = &AcpiOne;
  3037. break;
  3038. case AmlStatementOnes:
  3039. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  3040. Value = 0xFFFFFFFF;
  3041. Reduction = &AcpiOnes32;
  3042. } else {
  3043. Value = 0xFFFFFFFFFFFFFFFFULL;
  3044. Reduction = &AcpiOnes64;
  3045. }
  3046. break;
  3047. case AmlStatementRevision:
  3048. if (Context->PrintStatements != FALSE) {
  3049. PrintParentheses = TRUE;
  3050. RtlDebugPrint("Revision (");
  3051. }
  3052. Value = AML_REVISION;
  3053. break;
  3054. case AmlStatementTimer:
  3055. if (Context->PrintStatements != FALSE) {
  3056. PrintParentheses = TRUE;
  3057. RtlDebugPrint("Timer (");
  3058. }
  3059. Value = AcpipGetTimerValue();
  3060. break;
  3061. default:
  3062. ASSERT(FALSE);
  3063. return STATUS_INVALID_PARAMETER;
  3064. }
  3065. if (Context->PrintStatements != FALSE) {
  3066. RtlDebugPrint("0x%I64x", Value);
  3067. if (PrintParentheses != FALSE) {
  3068. RtlDebugPrint(")");
  3069. }
  3070. }
  3071. if (Context->ExecuteStatements != FALSE) {
  3072. if (Reduction != NULL) {
  3073. AcpipObjectAddReference(Reduction);
  3074. } else {
  3075. Reduction = AcpipCreateNamespaceObject(Context,
  3076. AcpiObjectInteger,
  3077. NULL,
  3078. &Value,
  3079. sizeof(ULONGLONG));
  3080. if (Reduction == NULL) {
  3081. return STATUS_UNSUCCESSFUL;
  3082. }
  3083. }
  3084. Statement->Reduction = Reduction;
  3085. }
  3086. return STATUS_SUCCESS;
  3087. }
  3088. KSTATUS
  3089. AcpipEvaluateLoadStatement (
  3090. PAML_EXECUTION_CONTEXT Context,
  3091. PAML_STATEMENT Statement
  3092. )
  3093. /*++
  3094. Routine Description:
  3095. This routine evaluates a Load statement, which adds the contents of a
  3096. memory op-region as an SSDT to the namespace.
  3097. Arguments:
  3098. Context - Supplies a pointer to the current AML execution context.
  3099. Statement - Supplies a pointer to the statement to evaluate.
  3100. Return Value:
  3101. Status code.
  3102. --*/
  3103. {
  3104. PDESCRIPTION_HEADER Buffer;
  3105. PACPI_OBJECT BufferObject;
  3106. UINTN BufferSize;
  3107. PACPI_OBJECT DdbHandle;
  3108. PACPI_OBJECT NewArgument;
  3109. PACPI_OPERATION_REGION_OBJECT OperationRegion;
  3110. PACPI_OBJECT Source;
  3111. KSTATUS Status;
  3112. Buffer = NULL;
  3113. BufferObject = NULL;
  3114. //
  3115. // If not all arguments are acquired, evaluate the previous statement to get
  3116. // the next argument.
  3117. //
  3118. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3119. //
  3120. // Print out the piece of the statement depending on the number of
  3121. // arguments acquired.
  3122. //
  3123. if (Context->PrintStatements != FALSE) {
  3124. if (Context->PreviousStatement == NULL) {
  3125. RtlDebugPrint("Load (");
  3126. } else if (Statement->ArgumentsAcquired == 0) {
  3127. RtlDebugPrint(", ");
  3128. } else {
  3129. RtlDebugPrint(")");
  3130. }
  3131. }
  3132. if (Context->PreviousStatement == NULL) {
  3133. return STATUS_MORE_PROCESSING_REQUIRED;
  3134. }
  3135. //
  3136. // If not executing, then assume the argument would be there but don't
  3137. // try to dink with it.
  3138. //
  3139. if (Context->ExecuteStatements == FALSE) {
  3140. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  3141. Statement->ArgumentsAcquired += 1;
  3142. } else {
  3143. NewArgument = Context->PreviousStatement->Reduction;
  3144. ASSERT(Statement->ArgumentsAcquired <= 1);
  3145. if (Context->PreviousStatement->Reduction != NULL) {
  3146. AcpipObjectAddReference(NewArgument);
  3147. }
  3148. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  3149. Statement->ArgumentsAcquired += 1;
  3150. }
  3151. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3152. return STATUS_MORE_PROCESSING_REQUIRED;
  3153. }
  3154. }
  3155. Statement->Reduction = NULL;
  3156. if (Context->ExecuteStatements == FALSE) {
  3157. return STATUS_SUCCESS;
  3158. }
  3159. //
  3160. // The source can either be an operation region itself or a field unit.
  3161. //
  3162. Source = Statement->Argument[0];
  3163. DdbHandle = Statement->Argument[1];
  3164. //
  3165. // If it's an operation region, read it directly. It had better be a memory
  3166. // region.
  3167. //
  3168. if (Source->Type == AcpiObjectOperationRegion) {
  3169. OperationRegion = &(Source->U.OperationRegion);
  3170. if ((OperationRegion->Space != OperationRegionSystemMemory) ||
  3171. (OperationRegion->Length < sizeof(DESCRIPTION_HEADER))) {
  3172. ASSERT(FALSE);
  3173. return STATUS_INVALID_PARAMETER;
  3174. }
  3175. BufferSize = OperationRegion->Length;
  3176. ASSERT(BufferSize == OperationRegion->Length);
  3177. Buffer = AcpipAllocateMemory(BufferSize);
  3178. if (Buffer == NULL) {
  3179. return STATUS_INSUFFICIENT_RESOURCES;
  3180. }
  3181. Status = OperationRegion->FunctionTable->Read(
  3182. OperationRegion->OsContext,
  3183. 0,
  3184. OperationRegion->Length * BITS_PER_BYTE,
  3185. Buffer);
  3186. ASSERT(KSUCCESS(Status));
  3187. //
  3188. // Convert the field unit into a buffer, which performs a read of the
  3189. // op-region.
  3190. //
  3191. } else if (Source->Type == AcpiObjectFieldUnit) {
  3192. BufferObject = AcpipConvertObjectType(Context,
  3193. Source,
  3194. AcpiObjectBuffer);
  3195. if (BufferObject == NULL) {
  3196. return STATUS_UNSUCCESSFUL;
  3197. }
  3198. //
  3199. // Steal the buffer from the buffer object.
  3200. //
  3201. Buffer = BufferObject->U.Buffer.Buffer;
  3202. BufferSize = BufferObject->U.Buffer.Length;
  3203. BufferObject->U.Buffer.Buffer = NULL;
  3204. BufferObject->U.Buffer.Length = 0;
  3205. } else {
  3206. RtlDebugPrint("ACPI: Load source should be an op-region or field.\n");
  3207. ASSERT(FALSE);
  3208. return STATUS_UNEXPECTED_TYPE;
  3209. }
  3210. //
  3211. // Validate the buffer a bit.
  3212. //
  3213. if ((BufferSize < sizeof(DESCRIPTION_HEADER)) ||
  3214. (BufferSize < Buffer->Length)) {
  3215. Status = STATUS_DATA_LENGTH_MISMATCH;
  3216. goto EvaluateLoadStatementEnd;
  3217. }
  3218. if (AcpipChecksumData(Buffer, Buffer->Length) != 0) {
  3219. Status = STATUS_CHECKSUM_MISMATCH;
  3220. goto EvaluateLoadStatementEnd;
  3221. }
  3222. //
  3223. // Load the definition block synchronously.
  3224. //
  3225. if (Context->PrintStatements != FALSE) {
  3226. RtlDebugPrint("\nLoading Definition Block...\n");
  3227. }
  3228. Status = AcpiLoadDefinitionBlock(Buffer, DdbHandle);
  3229. if (!KSUCCESS(Status)) {
  3230. RtlDebugPrint("ACPI: Failed to execute Load: %d\n", Status);
  3231. goto EvaluateLoadStatementEnd;
  3232. }
  3233. //
  3234. // Run any _INI methods.
  3235. //
  3236. Status = AcpipRunInitializationMethods(NULL);
  3237. if (!KSUCCESS(Status)) {
  3238. goto EvaluateLoadStatementEnd;
  3239. }
  3240. //
  3241. // The definition block owns the buffer now.
  3242. //
  3243. Buffer = NULL;
  3244. if (Context->PrintStatements != FALSE) {
  3245. RtlDebugPrint("\nDone Loading Definition Block\n");
  3246. }
  3247. EvaluateLoadStatementEnd:
  3248. if (BufferObject != NULL) {
  3249. AcpipObjectReleaseReference(BufferObject);
  3250. }
  3251. if (Buffer != NULL) {
  3252. AcpipFreeMemory(Buffer);
  3253. }
  3254. return Status;
  3255. }
  3256. KSTATUS
  3257. AcpipEvaluateLocalStatement (
  3258. PAML_EXECUTION_CONTEXT Context,
  3259. PAML_STATEMENT Statement
  3260. )
  3261. /*++
  3262. Routine Description:
  3263. This routine evaluates the LocalX opcodes.
  3264. Arguments:
  3265. Context - Supplies a pointer to the current AML execution context.
  3266. Statement - Supplies a pointer to the statement to evaluate.
  3267. Return Value:
  3268. Status code.
  3269. --*/
  3270. {
  3271. ULONG LocalNumber;
  3272. PACPI_OBJECT LocalObject;
  3273. LocalNumber = (ULONG)Statement->AdditionalData;
  3274. if (Context->PrintStatements != FALSE) {
  3275. RtlDebugPrint("Local%d", LocalNumber);
  3276. }
  3277. Statement->Reduction = NULL;
  3278. if (Context->ExecuteStatements != FALSE) {
  3279. LocalObject = Context->CurrentMethod->LocalVariable[LocalNumber];
  3280. //
  3281. // Create an uninitialized object if none exists yet.
  3282. //
  3283. if (LocalObject == NULL) {
  3284. LocalObject = AcpipCreateNamespaceObject(Context,
  3285. AcpiObjectUninitialized,
  3286. NULL,
  3287. NULL,
  3288. 0);
  3289. if (LocalObject == NULL) {
  3290. return STATUS_UNSUCCESSFUL;
  3291. }
  3292. Context->CurrentMethod->LocalVariable[LocalNumber] = LocalObject;
  3293. }
  3294. Statement->Reduction = LocalObject;
  3295. AcpipObjectAddReference(LocalObject);
  3296. Context->CurrentMethod->LastLocalIndex = LocalNumber;
  3297. }
  3298. return STATUS_SUCCESS;
  3299. }
  3300. KSTATUS
  3301. AcpipEvaluateLogicalExpressionStatement (
  3302. PAML_EXECUTION_CONTEXT Context,
  3303. PAML_STATEMENT Statement
  3304. )
  3305. /*++
  3306. Routine Description:
  3307. This routine evaluates logical binary operators (Logical and, equal,
  3308. greater, less, and or).
  3309. Arguments:
  3310. Context - Supplies a pointer to the current AML execution context.
  3311. Statement - Supplies a pointer to the statement to evaluate.
  3312. Return Value:
  3313. Status code.
  3314. --*/
  3315. {
  3316. PACPI_OBJECT NewArgument;
  3317. ULONGLONG Operand1;
  3318. ULONGLONG Operand2;
  3319. ULONGLONG ResultValue;
  3320. //
  3321. // If not all arguments are acquired, evaluate the previous statement to get
  3322. // the next argument.
  3323. //
  3324. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3325. //
  3326. // Print out the piece of the statement depending on the number of
  3327. // arguments acquired.
  3328. //
  3329. if (Context->PrintStatements != FALSE) {
  3330. if (Context->PreviousStatement == NULL) {
  3331. switch (Statement->Type) {
  3332. case AmlStatementLogicalAnd:
  3333. RtlDebugPrint("LAnd (");
  3334. break;
  3335. case AmlStatementLogicalEqual:
  3336. RtlDebugPrint("LEqual (");
  3337. break;
  3338. case AmlStatementLogicalGreater:
  3339. RtlDebugPrint("LGreater (");
  3340. break;
  3341. case AmlStatementLogicalLess:
  3342. RtlDebugPrint("LLess (");
  3343. break;
  3344. case AmlStatementLogicalOr:
  3345. RtlDebugPrint("LOr (");
  3346. break;
  3347. default:
  3348. ASSERT(FALSE);
  3349. return STATUS_NOT_SUPPORTED;
  3350. }
  3351. } else if (Statement->ArgumentsAcquired == 0) {
  3352. RtlDebugPrint(", ");
  3353. } else {
  3354. RtlDebugPrint(")");
  3355. }
  3356. }
  3357. if (Context->PreviousStatement == NULL) {
  3358. return STATUS_MORE_PROCESSING_REQUIRED;
  3359. }
  3360. //
  3361. // If not executing, then assume the argument would be there but don't
  3362. // try to dink with it.
  3363. //
  3364. if (Context->ExecuteStatements == FALSE) {
  3365. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  3366. Statement->ArgumentsAcquired += 1;
  3367. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3368. return STATUS_MORE_PROCESSING_REQUIRED;
  3369. }
  3370. } else {
  3371. NewArgument = Context->PreviousStatement->Reduction;
  3372. //
  3373. // Fail if there is no argument there.
  3374. //
  3375. if (Context->PreviousStatement->Reduction == NULL) {
  3376. return STATUS_ARGUMENT_EXPECTED;
  3377. }
  3378. //
  3379. // Perform an implicit conversion if needed.
  3380. //
  3381. if (NewArgument->Type != AcpiObjectInteger) {
  3382. NewArgument = AcpipConvertObjectType(Context,
  3383. NewArgument,
  3384. AcpiObjectInteger);
  3385. if (NewArgument == NULL) {
  3386. return STATUS_CONVERSION_FAILED;
  3387. }
  3388. //
  3389. // The object is fine, take ownership of it.
  3390. //
  3391. } else {
  3392. AcpipObjectAddReference(NewArgument);
  3393. }
  3394. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  3395. Statement->ArgumentsAcquired += 1;
  3396. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3397. return STATUS_MORE_PROCESSING_REQUIRED;
  3398. }
  3399. }
  3400. }
  3401. //
  3402. // Evaluate the result.
  3403. //
  3404. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  3405. Statement->Reduction = NULL;
  3406. if (Context->ExecuteStatements == FALSE) {
  3407. return STATUS_SUCCESS;
  3408. }
  3409. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  3410. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  3411. Operand1 = Statement->Argument[0]->U.Integer.Value;
  3412. Operand2 = Statement->Argument[1]->U.Integer.Value;
  3413. ResultValue = FALSE;
  3414. switch (Statement->Type) {
  3415. case AmlStatementLogicalAnd:
  3416. if ((Operand1 != 0) && (Operand2 != 0)) {
  3417. ResultValue = TRUE;
  3418. }
  3419. break;
  3420. case AmlStatementLogicalEqual:
  3421. if (Operand1 == Operand2) {
  3422. ResultValue = TRUE;
  3423. }
  3424. break;
  3425. case AmlStatementLogicalGreater:
  3426. if (Operand1 > Operand2) {
  3427. ResultValue = TRUE;
  3428. }
  3429. break;
  3430. case AmlStatementLogicalLess:
  3431. if (Operand1 < Operand2) {
  3432. ResultValue = TRUE;
  3433. }
  3434. break;
  3435. case AmlStatementLogicalOr:
  3436. if ((Operand1 != 0) || (Operand2 != 0)) {
  3437. ResultValue = TRUE;
  3438. }
  3439. break;
  3440. default:
  3441. ASSERT(FALSE);
  3442. return STATUS_NOT_SUPPORTED;
  3443. }
  3444. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  3445. AcpiObjectInteger,
  3446. NULL,
  3447. &ResultValue,
  3448. sizeof(ULONGLONG));
  3449. if (Statement->Reduction == NULL) {
  3450. return STATUS_UNSUCCESSFUL;
  3451. }
  3452. return STATUS_SUCCESS;
  3453. }
  3454. KSTATUS
  3455. AcpipEvaluateLogicalNotStatement (
  3456. PAML_EXECUTION_CONTEXT Context,
  3457. PAML_STATEMENT Statement
  3458. )
  3459. /*++
  3460. Routine Description:
  3461. This routine evaluates logical NOT operator.
  3462. Arguments:
  3463. Context - Supplies a pointer to the current AML execution context.
  3464. Statement - Supplies a pointer to the statement to evaluate.
  3465. Return Value:
  3466. Status code.
  3467. --*/
  3468. {
  3469. PACPI_OBJECT NewArgument;
  3470. ULONGLONG ResultValue;
  3471. //
  3472. // If not all arguments are acquired, evaluate the previous statement to get
  3473. // the next argument.
  3474. //
  3475. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3476. //
  3477. // Print out the piece of the statement depending on the number of
  3478. // arguments acquired.
  3479. //
  3480. if (Context->PrintStatements != FALSE) {
  3481. if (Context->PreviousStatement == NULL) {
  3482. RtlDebugPrint("LNot (");
  3483. } else {
  3484. RtlDebugPrint(")");
  3485. }
  3486. }
  3487. if (Context->PreviousStatement == NULL) {
  3488. return STATUS_MORE_PROCESSING_REQUIRED;
  3489. }
  3490. //
  3491. // If not executing, then assume the argument would be there but don't
  3492. // try to dink with it.
  3493. //
  3494. if (Context->ExecuteStatements == FALSE) {
  3495. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  3496. Statement->ArgumentsAcquired += 1;
  3497. } else {
  3498. NewArgument = Context->PreviousStatement->Reduction;
  3499. //
  3500. // Fail if there is no argument there.
  3501. //
  3502. if (Context->PreviousStatement->Reduction == NULL) {
  3503. return STATUS_ARGUMENT_EXPECTED;
  3504. }
  3505. //
  3506. // Perform an implicit conversion if needed.
  3507. //
  3508. if (NewArgument->Type != AcpiObjectInteger) {
  3509. NewArgument = AcpipConvertObjectType(Context,
  3510. NewArgument,
  3511. AcpiObjectInteger);
  3512. if (NewArgument == NULL) {
  3513. return STATUS_CONVERSION_FAILED;
  3514. }
  3515. //
  3516. // The object is fine, take ownership of it.
  3517. //
  3518. } else {
  3519. AcpipObjectAddReference(NewArgument);
  3520. }
  3521. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  3522. Statement->ArgumentsAcquired += 1;
  3523. }
  3524. }
  3525. //
  3526. // Evaluate the result.
  3527. //
  3528. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  3529. Statement->Reduction = NULL;
  3530. if (Context->ExecuteStatements == FALSE) {
  3531. return STATUS_SUCCESS;
  3532. }
  3533. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  3534. ResultValue = FALSE;
  3535. if (Statement->Argument[0]->U.Integer.Value == 0) {
  3536. ResultValue = TRUE;
  3537. }
  3538. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  3539. AcpiObjectInteger,
  3540. NULL,
  3541. &ResultValue,
  3542. sizeof(ULONGLONG));
  3543. if (Statement->Reduction == NULL) {
  3544. return STATUS_UNSUCCESSFUL;
  3545. }
  3546. return STATUS_SUCCESS;
  3547. }
  3548. KSTATUS
  3549. AcpipEvaluateMatchStatement (
  3550. PAML_EXECUTION_CONTEXT Context,
  3551. PAML_STATEMENT Statement
  3552. )
  3553. /*++
  3554. Routine Description:
  3555. This routine evaluates a Match statement, which iterates over a package
  3556. doing some simple comparisons.
  3557. Arguments:
  3558. Context - Supplies a pointer to the current AML execution context.
  3559. Statement - Supplies a pointer to the statement to evaluate.
  3560. Return Value:
  3561. Status code.
  3562. --*/
  3563. {
  3564. PUCHAR InstructionPointer;
  3565. ULONGLONG ItemCount;
  3566. ULONGLONG ItemIndex;
  3567. BOOL Match;
  3568. PACPI_OBJECT NewArgument;
  3569. PACPI_OBJECT Operand1;
  3570. PACPI_OBJECT Operand2;
  3571. ACPI_MATCH_OPERATOR Operator1;
  3572. ACPI_MATCH_OPERATOR Operator2;
  3573. PACPI_OBJECT Package;
  3574. PACPI_OBJECT PackageElement;
  3575. PACPI_OBJECT StartIndex;
  3576. //
  3577. // If not all arguments are acquired, evaluate the previous statement to get
  3578. // the next argument.
  3579. //
  3580. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3581. //
  3582. // Print out the piece of the statement depending on the number of
  3583. // arguments acquired.
  3584. //
  3585. if (Context->PrintStatements != FALSE) {
  3586. if (Context->PreviousStatement == NULL) {
  3587. RtlDebugPrint("Match (");
  3588. } else if (Statement->ArgumentsAcquired < 3) {
  3589. RtlDebugPrint(", ");
  3590. } else {
  3591. RtlDebugPrint(")");
  3592. }
  3593. }
  3594. if (Context->PreviousStatement == NULL) {
  3595. return STATUS_MORE_PROCESSING_REQUIRED;
  3596. }
  3597. //
  3598. // If not executing, then assume the argument would be there but don't
  3599. // try to dink with it.
  3600. //
  3601. if (Context->ExecuteStatements == FALSE) {
  3602. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  3603. Statement->ArgumentsAcquired += 1;
  3604. } else {
  3605. NewArgument = Context->PreviousStatement->Reduction;
  3606. //
  3607. // An argument is required.
  3608. //
  3609. if (NewArgument == NULL) {
  3610. return STATUS_ARGUMENT_EXPECTED;
  3611. }
  3612. //
  3613. // The first object must be a package.
  3614. //
  3615. if (Statement->ArgumentsAcquired == 0) {
  3616. if (NewArgument->Type != AcpiObjectPackage) {
  3617. return STATUS_CONVERSION_FAILED;
  3618. }
  3619. AcpipObjectAddReference(NewArgument);
  3620. //
  3621. // The second and third arguments must be an integer, buffer, or
  3622. // string. Convert that to an integer. The fourth argument
  3623. // (StartIndex) is also an integer.
  3624. //
  3625. } else if ((Statement->ArgumentsAcquired == 1) ||
  3626. (Statement->ArgumentsAcquired == 2) ||
  3627. (Statement->ArgumentsAcquired == 3)) {
  3628. if (NewArgument->Type != AcpiObjectInteger) {
  3629. NewArgument = AcpipConvertObjectType(Context,
  3630. NewArgument,
  3631. AcpiObjectInteger);
  3632. if (NewArgument == NULL) {
  3633. return STATUS_CONVERSION_FAILED;
  3634. }
  3635. } else {
  3636. AcpipObjectAddReference(NewArgument);
  3637. }
  3638. }
  3639. //
  3640. // Save the argument and return if not all arguments have been
  3641. // collected yet.
  3642. //
  3643. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  3644. Statement->ArgumentsAcquired += 1;
  3645. }
  3646. //
  3647. // After the first and second arguments come match opcodes. Pull
  3648. // those out and store them in additional data.
  3649. //
  3650. if ((Statement->ArgumentsAcquired == 1) ||
  3651. (Statement->ArgumentsAcquired == 2)) {
  3652. InstructionPointer =
  3653. (PUCHAR)(Context->AmlCode) + Context->CurrentOffset;
  3654. if (Context->CurrentOffset >= Context->AmlCodeSize) {
  3655. return STATUS_MALFORMED_DATA_STREAM;
  3656. }
  3657. Statement->AdditionalData = (Statement->AdditionalData << 8) |
  3658. *InstructionPointer;
  3659. if (*InstructionPointer >= MatchOperatorCount) {
  3660. return STATUS_MALFORMED_DATA_STREAM;
  3661. }
  3662. if (Context->PrintStatements != FALSE) {
  3663. RtlDebugPrint("%s, ",
  3664. AcpiMatchOpcodeString[*InstructionPointer]);
  3665. }
  3666. Context->CurrentOffset += 1;
  3667. }
  3668. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3669. return STATUS_MORE_PROCESSING_REQUIRED;
  3670. }
  3671. }
  3672. //
  3673. // Evaluate the result.
  3674. //
  3675. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  3676. Statement->Reduction = NULL;
  3677. if (Context->ExecuteStatements == FALSE) {
  3678. return STATUS_SUCCESS;
  3679. }
  3680. //
  3681. // Assert that all the arguments are the expected types.
  3682. //
  3683. Package = Statement->Argument[0];
  3684. Operand1 = Statement->Argument[1];
  3685. Operand2 = Statement->Argument[2];
  3686. StartIndex = Statement->Argument[3];
  3687. Operator1 = (Statement->AdditionalData >> 8) & 0xFF;
  3688. Operator2 = Statement->AdditionalData & 0xFF;
  3689. ASSERT((Package->Type == AcpiObjectPackage) &&
  3690. (StartIndex->Type == AcpiObjectInteger));
  3691. ASSERT((Operand1->Type == AcpiObjectInteger) &&
  3692. (Operand2->Type == AcpiObjectInteger));
  3693. ASSERT((Operator1 < MatchOperatorCount) &&
  3694. (Operator2 < MatchOperatorCount));
  3695. //
  3696. // Perform the match operation.
  3697. //
  3698. ItemIndex = StartIndex->U.Integer.Value;
  3699. ItemCount = Package->U.Package.ElementCount;
  3700. while (ItemIndex < ItemCount) {
  3701. PackageElement = AcpipGetPackageObject(Package, ItemIndex, FALSE);
  3702. Match = AcpipEvaluateMatchComparison(Context,
  3703. PackageElement,
  3704. Operand1,
  3705. Operator1,
  3706. Operand2,
  3707. Operator2);
  3708. if (Match != FALSE) {
  3709. break;
  3710. }
  3711. ItemIndex += 1;
  3712. }
  3713. //
  3714. // If a match was never found (as evidenced by the index being all the way
  3715. // at the end), the ACPI says to return the constant "Ones".
  3716. //
  3717. if (ItemIndex == ItemCount) {
  3718. Statement->Reduction = &AcpiOnes64;
  3719. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  3720. Statement->Reduction = &AcpiOnes32;
  3721. }
  3722. AcpipObjectAddReference(Statement->Reduction);
  3723. //
  3724. // Otherwise, return the result value.
  3725. //
  3726. } else {
  3727. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  3728. AcpiObjectInteger,
  3729. NULL,
  3730. &ItemIndex,
  3731. sizeof(ULONGLONG));
  3732. if (Statement->Reduction == NULL) {
  3733. return STATUS_INSUFFICIENT_RESOURCES;
  3734. }
  3735. }
  3736. return STATUS_SUCCESS;
  3737. }
  3738. KSTATUS
  3739. AcpipEvaluateMethodStatement (
  3740. PAML_EXECUTION_CONTEXT Context,
  3741. PAML_STATEMENT Statement
  3742. )
  3743. /*++
  3744. Routine Description:
  3745. This routine evaluates a Method declaration statement.
  3746. Arguments:
  3747. Context - Supplies a pointer to the current AML execution context.
  3748. Statement - Supplies a pointer to the statement to evaluate.
  3749. Return Value:
  3750. Status code.
  3751. --*/
  3752. {
  3753. ACPI_METHOD_OBJECT Method;
  3754. UCHAR MethodFlags;
  3755. PACPI_OBJECT MethodObject;
  3756. PSTR Name;
  3757. //
  3758. // If the previous statement is NULL, this is the first time through.
  3759. //
  3760. if (Context->PreviousStatement == NULL) {
  3761. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  3762. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  3763. //
  3764. // Get the method flags out of additional data 2.
  3765. //
  3766. MethodFlags = (UCHAR)Statement->AdditionalData2;
  3767. //
  3768. // Initialize the method structure.
  3769. //
  3770. RtlZeroMemory(&Method, sizeof(ACPI_METHOD_OBJECT));
  3771. Method.IntegerWidthIs32 = Context->CurrentMethod->IntegerWidthIs32;
  3772. Method.ArgumentCount = MethodFlags & METHOD_ARGUMENT_COUNT_MASK;
  3773. Method.Serialized = FALSE;
  3774. if ((MethodFlags & METHOD_SERIALIZED_FLAG) != 0) {
  3775. Method.Serialized = TRUE;
  3776. }
  3777. Method.SyncLevel = (MethodFlags & METHOD_SYNC_LEVEL_MASK) >>
  3778. METHOD_SYNC_LEVEL_SHIFT;
  3779. Method.AmlCode = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
  3780. //
  3781. // Additional Data stored the end offset, so the size is the end offset
  3782. // minus the current offset.
  3783. //
  3784. Method.AmlCodeSize = Statement->AdditionalData - Context->CurrentOffset;
  3785. Name = Statement->Argument[0]->U.String.String;
  3786. if (Context->PrintStatements != FALSE) {
  3787. RtlDebugPrint("Method (%s, 0x%02x)", Name, MethodFlags);
  3788. }
  3789. //
  3790. // Create the object if execution is enabled.
  3791. //
  3792. if (Context->ExecuteStatements != FALSE) {
  3793. MethodObject = AcpipCreateNamespaceObject(
  3794. Context,
  3795. AcpiObjectMethod,
  3796. Name,
  3797. &Method,
  3798. sizeof(ACPI_METHOD_OBJECT));
  3799. if (MethodObject == NULL) {
  3800. return STATUS_UNSUCCESSFUL;
  3801. }
  3802. //
  3803. // Advance the current offset to the end of the method, as it's not
  3804. // being executed now, and complete the statement.
  3805. //
  3806. Context->CurrentOffset = Statement->AdditionalData;
  3807. return STATUS_SUCCESS;
  3808. //
  3809. // If the context is printing but not executing, add to the indentation
  3810. // level and delve into the function for execution.
  3811. //
  3812. } else {
  3813. Context->IndentationLevel += 1;
  3814. if (Context->PrintStatements != FALSE) {
  3815. RtlDebugPrint(" {");
  3816. }
  3817. }
  3818. }
  3819. //
  3820. // Wait for the end of the routine.
  3821. //
  3822. if (Context->CurrentOffset < Statement->AdditionalData) {
  3823. AcpipPrintIndentedNewLine(Context);
  3824. return STATUS_MORE_PROCESSING_REQUIRED;
  3825. }
  3826. //
  3827. // Decrease the indentation level and print the closing curly brace if
  3828. // needed.
  3829. //
  3830. Context->IndentationLevel -= 1;
  3831. if (Context->PrintStatements != FALSE) {
  3832. AcpipPrintIndentedNewLine(Context);
  3833. RtlDebugPrint("}");
  3834. }
  3835. AcpipPrintIndentedNewLine(Context);
  3836. return STATUS_SUCCESS;
  3837. }
  3838. KSTATUS
  3839. AcpipEvaluateMidStatement (
  3840. PAML_EXECUTION_CONTEXT Context,
  3841. PAML_STATEMENT Statement
  3842. )
  3843. /*++
  3844. Routine Description:
  3845. This routine evaluates a mid statement, which splits a string up.
  3846. Arguments:
  3847. Context - Supplies a pointer to the current AML execution context.
  3848. Statement - Supplies a pointer to the statement to evaluate.
  3849. Return Value:
  3850. Status code.
  3851. --*/
  3852. {
  3853. PVOID Buffer;
  3854. ULONGLONG BufferLength;
  3855. ULONGLONG MidIndex;
  3856. ULONGLONG MidLength;
  3857. PACPI_OBJECT NewArgument;
  3858. //
  3859. // If not all arguments are acquired, evaluate the previous statement to get
  3860. // the next argument.
  3861. //
  3862. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3863. //
  3864. // Print out the piece of the statement depending on the number of
  3865. // arguments acquired.
  3866. //
  3867. if (Context->PrintStatements != FALSE) {
  3868. if (Context->PreviousStatement == NULL) {
  3869. RtlDebugPrint("Mid (");
  3870. } else if ((Statement->ArgumentsAcquired == 0) ||
  3871. (Statement->ArgumentsAcquired == 1) ||
  3872. (Statement->ArgumentsAcquired == 2)) {
  3873. RtlDebugPrint(", ");
  3874. } else {
  3875. RtlDebugPrint(")");
  3876. }
  3877. }
  3878. if (Context->PreviousStatement == NULL) {
  3879. return STATUS_MORE_PROCESSING_REQUIRED;
  3880. }
  3881. //
  3882. // If not executing, then assume the argument would be there but don't
  3883. // try to dink with it.
  3884. //
  3885. if (Context->ExecuteStatements == FALSE) {
  3886. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  3887. Statement->ArgumentsAcquired += 1;
  3888. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3889. return STATUS_MORE_PROCESSING_REQUIRED;
  3890. }
  3891. } else {
  3892. NewArgument = Context->PreviousStatement->Reduction;
  3893. if (Statement->ArgumentsAcquired == 0) {
  3894. if (Context->PreviousStatement->Reduction == NULL) {
  3895. return STATUS_ARGUMENT_EXPECTED;
  3896. }
  3897. if ((NewArgument->Type != AcpiObjectString) &&
  3898. (NewArgument->Type != AcpiObjectBuffer)) {
  3899. //
  3900. // Perform an implicit conversion if needed.
  3901. //
  3902. NewArgument = AcpipConvertObjectType(Context,
  3903. NewArgument,
  3904. AcpiObjectBuffer);
  3905. if (NewArgument == NULL) {
  3906. return STATUS_CONVERSION_FAILED;
  3907. }
  3908. //
  3909. // The object is fine, take ownership of it.
  3910. //
  3911. } else {
  3912. AcpipObjectAddReference(NewArgument);
  3913. }
  3914. } else if ((Statement->ArgumentsAcquired == 1) ||
  3915. (Statement->ArgumentsAcquired == 2)) {
  3916. //
  3917. // Fail if there is no argument there.
  3918. //
  3919. if (Context->PreviousStatement->Reduction == NULL) {
  3920. return STATUS_ARGUMENT_EXPECTED;
  3921. }
  3922. //
  3923. // Perform an implicit conversion if needed.
  3924. //
  3925. if (NewArgument->Type != AcpiObjectInteger) {
  3926. NewArgument = AcpipConvertObjectType(Context,
  3927. NewArgument,
  3928. AcpiObjectInteger);
  3929. if (NewArgument == NULL) {
  3930. return STATUS_CONVERSION_FAILED;
  3931. }
  3932. //
  3933. // The object is fine, take ownership of it.
  3934. //
  3935. } else {
  3936. AcpipObjectAddReference(NewArgument);
  3937. }
  3938. //
  3939. // Parse the target argument.
  3940. //
  3941. } else {
  3942. ASSERT(Statement->ArgumentsAcquired == 3);
  3943. if (NewArgument != NULL) {
  3944. AcpipObjectAddReference(NewArgument);
  3945. }
  3946. }
  3947. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  3948. Statement->ArgumentsAcquired += 1;
  3949. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  3950. return STATUS_MORE_PROCESSING_REQUIRED;
  3951. }
  3952. }
  3953. }
  3954. //
  3955. // Evaluate the result.
  3956. //
  3957. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  3958. Statement->Reduction = NULL;
  3959. if (Context->ExecuteStatements == FALSE) {
  3960. return STATUS_SUCCESS;
  3961. }
  3962. ASSERT((Statement->Argument[0]->Type == AcpiObjectString) ||
  3963. (Statement->Argument[0]->Type == AcpiObjectBuffer));
  3964. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  3965. ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
  3966. //
  3967. // The Mid statement gets a portion of a string or buffer at an offset
  3968. // (Index) with a length. If the mid statement tries to go over, the
  3969. // resulting buffer is clipped with the original. If the offset is beyond
  3970. // the end of the buffer, an empty buffer is created.
  3971. //
  3972. MidIndex = Statement->Argument[1]->U.Integer.Value;
  3973. MidLength = Statement->Argument[2]->U.Integer.Value;
  3974. BufferLength = 0;
  3975. if (Statement->Argument[0]->Type == AcpiObjectString) {
  3976. Buffer = Statement->Argument[0]->U.String.String;
  3977. if (Buffer != NULL) {
  3978. BufferLength = RtlStringLength(Buffer) + 1;
  3979. }
  3980. } else {
  3981. Buffer = Statement->Argument[0]->U.Buffer.Buffer;
  3982. BufferLength = Statement->Argument[0]->U.Buffer.Length;
  3983. }
  3984. //
  3985. // Cap the mid statement from going over the buffer.
  3986. //
  3987. if (MidIndex >= BufferLength) {
  3988. MidIndex = 0;
  3989. MidLength = 0;
  3990. }
  3991. if (MidIndex + MidLength > BufferLength) {
  3992. MidLength = BufferLength - MidIndex;
  3993. }
  3994. //
  3995. // Create the mid buffer.
  3996. //
  3997. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  3998. AcpiObjectInteger,
  3999. NULL,
  4000. Buffer + MidIndex,
  4001. MidLength);
  4002. if (Statement->Reduction == NULL) {
  4003. return STATUS_UNSUCCESSFUL;
  4004. }
  4005. //
  4006. // Store the result in the target if supplied.
  4007. //
  4008. if (Statement->Argument[3] != NULL) {
  4009. return AcpipPerformStoreOperation(Context,
  4010. Statement->Reduction,
  4011. Statement->Argument[2]);
  4012. }
  4013. return STATUS_SUCCESS;
  4014. }
  4015. KSTATUS
  4016. AcpipEvaluateMutexStatement (
  4017. PAML_EXECUTION_CONTEXT Context,
  4018. PAML_STATEMENT Statement
  4019. )
  4020. /*++
  4021. Routine Description:
  4022. This routine evaluates a Mutex (creation) statement.
  4023. Arguments:
  4024. Context - Supplies a pointer to the current AML execution context.
  4025. Statement - Supplies a pointer to the statement to evaluate.
  4026. Return Value:
  4027. Status code.
  4028. --*/
  4029. {
  4030. PSTR NameString;
  4031. UCHAR SyncLevel;
  4032. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4033. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4034. NameString = Statement->Argument[0]->U.String.String;
  4035. SyncLevel = Statement->AdditionalData & MUTEX_FLAG_SYNC_LEVEL_MASK;
  4036. if (Context->PrintStatements != FALSE) {
  4037. RtlDebugPrint("Mutex (%s, %d)", NameString, SyncLevel);
  4038. }
  4039. Statement->Reduction = NULL;
  4040. if (Context->ExecuteStatements == FALSE) {
  4041. return STATUS_SUCCESS;
  4042. }
  4043. //
  4044. // Create the mutex object.
  4045. //
  4046. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  4047. AcpiObjectMutex,
  4048. NameString,
  4049. NULL,
  4050. 0);
  4051. if (Statement->Reduction == NULL) {
  4052. return STATUS_UNSUCCESSFUL;
  4053. }
  4054. return STATUS_SUCCESS;
  4055. }
  4056. KSTATUS
  4057. AcpipEvaluateNameStatement (
  4058. PAML_EXECUTION_CONTEXT Context,
  4059. PAML_STATEMENT Statement
  4060. )
  4061. /*++
  4062. Routine Description:
  4063. This routine evaluates a Name statement, which creates a new named object
  4064. in the namespace given an existing one.
  4065. Arguments:
  4066. Context - Supplies a pointer to the current AML execution context.
  4067. Statement - Supplies a pointer to the statement to evaluate.
  4068. Return Value:
  4069. Status code.
  4070. --*/
  4071. {
  4072. PACPI_OBJECT NamedObject;
  4073. PACPI_OBJECT NewArgument;
  4074. PACPI_OBJECT ObjectWithContents;
  4075. KSTATUS Status;
  4076. //
  4077. // If not all arguments are acquired, evaluate the previous statement to get
  4078. // the next argument.
  4079. //
  4080. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4081. //
  4082. // Print out the piece of the statement depending on the number of
  4083. // arguments acquired.
  4084. //
  4085. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4086. if (Context->PrintStatements != FALSE) {
  4087. if (Context->PreviousStatement == NULL) {
  4088. RtlDebugPrint("Name (%s,",
  4089. Statement->Argument[0]->U.String.String);
  4090. } else {
  4091. RtlDebugPrint(")");
  4092. }
  4093. }
  4094. if (Context->PreviousStatement == NULL) {
  4095. return STATUS_MORE_PROCESSING_REQUIRED;
  4096. }
  4097. //
  4098. // If not executing, then assume the argument would be there but don't
  4099. // try to dink with it.
  4100. //
  4101. if (Context->ExecuteStatements == FALSE) {
  4102. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4103. Statement->ArgumentsAcquired += 1;
  4104. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4105. return STATUS_MORE_PROCESSING_REQUIRED;
  4106. }
  4107. } else {
  4108. NewArgument = Context->PreviousStatement->Reduction;
  4109. //
  4110. // Fail if there is no argument there.
  4111. //
  4112. if (Context->PreviousStatement->Reduction == NULL) {
  4113. return STATUS_ARGUMENT_EXPECTED;
  4114. }
  4115. AcpipObjectAddReference(NewArgument);
  4116. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4117. Statement->ArgumentsAcquired += 1;
  4118. }
  4119. }
  4120. //
  4121. // The arguments should be all gathered.
  4122. //
  4123. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4124. Statement->Reduction = NULL;
  4125. if (Context->ExecuteStatements == FALSE) {
  4126. return STATUS_SUCCESS;
  4127. }
  4128. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4129. //
  4130. // Create the new object without the stuff in it.
  4131. //
  4132. ObjectWithContents = Statement->Argument[1];
  4133. NamedObject = AcpipCreateNamespaceObject(
  4134. Context,
  4135. AcpiObjectUninitialized,
  4136. Statement->Argument[0]->U.String.String,
  4137. NULL,
  4138. 0);
  4139. if (NamedObject == NULL) {
  4140. return STATUS_UNSUCCESSFUL;
  4141. }
  4142. //
  4143. // Put the stuff from the other object in this new named object.
  4144. //
  4145. Status = AcpipPerformStoreOperation(Context,
  4146. ObjectWithContents,
  4147. NamedObject);
  4148. if (!KSUCCESS(Status)) {
  4149. return Status;
  4150. }
  4151. Statement->Reduction = NamedObject;
  4152. return STATUS_SUCCESS;
  4153. }
  4154. KSTATUS
  4155. AcpipEvaluateNameStringStatement (
  4156. PAML_EXECUTION_CONTEXT Context,
  4157. PAML_STATEMENT Statement
  4158. )
  4159. /*++
  4160. Routine Description:
  4161. This routine evaluates a NameString statement, which evaluates to an
  4162. object that is expected to exist in the namespace.
  4163. Arguments:
  4164. Context - Supplies a pointer to the current AML execution context.
  4165. Statement - Supplies a pointer to the statement to evaluate.
  4166. Return Value:
  4167. Status code.
  4168. --*/
  4169. {
  4170. PSTR Name;
  4171. ACPI_UNRESOLVED_NAME_OBJECT UnresolvedName;
  4172. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4173. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4174. Name = Statement->Argument[0]->U.String.String;
  4175. if (Context->PrintStatements != FALSE) {
  4176. RtlDebugPrint(Name);
  4177. }
  4178. //
  4179. // Get the object if the interpreter is executing statements.
  4180. //
  4181. Statement->Reduction = NULL;
  4182. if (Context->ExecuteStatements != FALSE) {
  4183. Statement->Reduction = AcpipGetNamespaceObject(Name,
  4184. Context->CurrentScope);
  4185. //
  4186. // If the object could not be found, then a name is being referenced
  4187. // before it is defined. In certain situations this is alright, such as
  4188. // the definition of a package object during a load operation. Create
  4189. // an unresolved name object to remember to re-evaluate this name
  4190. // when the object is referenced.
  4191. //
  4192. if (Statement->Reduction == NULL) {
  4193. RtlZeroMemory(&UnresolvedName, sizeof(ACPI_UNRESOLVED_NAME_OBJECT));
  4194. UnresolvedName.Name = Name;
  4195. UnresolvedName.Scope = Context->CurrentScope;
  4196. Statement->Reduction = AcpipCreateNamespaceObject(
  4197. Context,
  4198. AcpiObjectUnresolvedName,
  4199. NULL,
  4200. &UnresolvedName,
  4201. sizeof(ACPI_UNRESOLVED_NAME_OBJECT));
  4202. if (Statement->Reduction == NULL) {
  4203. return STATUS_UNSUCCESSFUL;
  4204. }
  4205. if (Context->PrintStatements != FALSE) {
  4206. RtlDebugPrint(" ?");
  4207. }
  4208. } else {
  4209. AcpipObjectAddReference(Statement->Reduction);
  4210. }
  4211. }
  4212. return STATUS_SUCCESS;
  4213. }
  4214. KSTATUS
  4215. AcpipEvaluateNoOpStatement (
  4216. PAML_EXECUTION_CONTEXT Context,
  4217. PAML_STATEMENT Statement
  4218. )
  4219. /*++
  4220. Routine Description:
  4221. This routine evaluates a No-Op statement, which is really quite easy since
  4222. it doesn't do anything.
  4223. Arguments:
  4224. Context - Supplies a pointer to the current AML execution context.
  4225. Statement - Supplies a pointer to the statement to evaluate.
  4226. Return Value:
  4227. STATUS_SUCCESS always.
  4228. --*/
  4229. {
  4230. //
  4231. // Finally, an easy one!
  4232. //
  4233. if (Context->PrintStatements != FALSE) {
  4234. RtlDebugPrint("NoOp");
  4235. }
  4236. return STATUS_SUCCESS;
  4237. }
  4238. KSTATUS
  4239. AcpipEvaluateNotifyStatement (
  4240. PAML_EXECUTION_CONTEXT Context,
  4241. PAML_STATEMENT Statement
  4242. )
  4243. /*++
  4244. Routine Description:
  4245. This routine evaluates a Notify (the operating system) statement.
  4246. Arguments:
  4247. Context - Supplies a pointer to the current AML execution context.
  4248. Statement - Supplies a pointer to the statement to evaluate.
  4249. Return Value:
  4250. Status code.
  4251. --*/
  4252. {
  4253. PACPI_OBJECT NewArgument;
  4254. KSTATUS Status;
  4255. //
  4256. // If not all arguments are acquired, evaluate the previous statement to get
  4257. // the next argument.
  4258. //
  4259. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4260. //
  4261. // Print out the piece of the statement depending on the number of
  4262. // arguments acquired.
  4263. //
  4264. if (Context->PrintStatements != FALSE) {
  4265. if (Context->PreviousStatement == NULL) {
  4266. RtlDebugPrint("Notify (");
  4267. } else if (Statement->ArgumentsAcquired == 0) {
  4268. RtlDebugPrint(", ");
  4269. } else {
  4270. RtlDebugPrint(")");
  4271. }
  4272. }
  4273. if (Context->PreviousStatement == NULL) {
  4274. return STATUS_MORE_PROCESSING_REQUIRED;
  4275. }
  4276. //
  4277. // If not executing, then assume the argument would be there but don't
  4278. // try to dink with it.
  4279. //
  4280. if (Context->ExecuteStatements == FALSE) {
  4281. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4282. Statement->ArgumentsAcquired += 1;
  4283. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4284. return STATUS_MORE_PROCESSING_REQUIRED;
  4285. }
  4286. } else {
  4287. NewArgument = Context->PreviousStatement->Reduction;
  4288. //
  4289. // Fail if there is no argument there.
  4290. //
  4291. if (Context->PreviousStatement->Reduction == NULL) {
  4292. return STATUS_ARGUMENT_EXPECTED;
  4293. }
  4294. //
  4295. // The first argument needs to be a Thermal Zone, Processor, or
  4296. // Device.
  4297. //
  4298. if (Statement->ArgumentsAcquired == 0) {
  4299. if ((NewArgument->Type != AcpiObjectProcessor) &&
  4300. (NewArgument->Type != AcpiObjectThermalZone) &&
  4301. (NewArgument->Type != AcpiObjectDevice)) {
  4302. return STATUS_INVALID_PARAMETER;
  4303. } else {
  4304. AcpipObjectAddReference(NewArgument);
  4305. }
  4306. //
  4307. // The second argument needs to come out as an integer.
  4308. //
  4309. } else {
  4310. ASSERT(Statement->ArgumentsAcquired == 1);
  4311. if (NewArgument->Type != AcpiObjectInteger) {
  4312. NewArgument = AcpipConvertObjectType(Context,
  4313. NewArgument,
  4314. AcpiObjectInteger);
  4315. if (NewArgument == NULL) {
  4316. return STATUS_CONVERSION_FAILED;
  4317. }
  4318. //
  4319. // The object is fine, take ownership of it.
  4320. //
  4321. } else {
  4322. AcpipObjectAddReference(NewArgument);
  4323. }
  4324. }
  4325. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4326. Statement->ArgumentsAcquired += 1;
  4327. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4328. return STATUS_MORE_PROCESSING_REQUIRED;
  4329. }
  4330. }
  4331. }
  4332. //
  4333. // Evaluate the result.
  4334. //
  4335. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4336. Statement->Reduction = NULL;
  4337. if (Context->ExecuteStatements == FALSE) {
  4338. return STATUS_SUCCESS;
  4339. }
  4340. ASSERT((Statement->Argument[0]->Type == AcpiObjectProcessor) ||
  4341. (Statement->Argument[0]->Type == AcpiObjectThermalZone) ||
  4342. (Statement->Argument[0]->Type == AcpiObjectDevice));
  4343. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  4344. //
  4345. // Pass the notification on to the rest of the system.
  4346. //
  4347. Status = AcpipNotifyOperatingSystem(
  4348. Statement->Argument[0],
  4349. Statement->Argument[1]->U.Integer.Value);
  4350. return Status;
  4351. }
  4352. KSTATUS
  4353. AcpipEvaluateNotStatement (
  4354. PAML_EXECUTION_CONTEXT Context,
  4355. PAML_STATEMENT Statement
  4356. )
  4357. /*++
  4358. Routine Description:
  4359. This routine evaluates bitwise NOT operator.
  4360. Arguments:
  4361. Context - Supplies a pointer to the current AML execution context.
  4362. Statement - Supplies a pointer to the statement to evaluate.
  4363. Return Value:
  4364. Status code.
  4365. --*/
  4366. {
  4367. PACPI_OBJECT NewArgument;
  4368. ULONGLONG ResultValue;
  4369. //
  4370. // If not all arguments are acquired, evaluate the previous statement to get
  4371. // the next argument.
  4372. //
  4373. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4374. //
  4375. // Print out the piece of the statement depending on the number of
  4376. // arguments acquired.
  4377. //
  4378. if (Context->PrintStatements != FALSE) {
  4379. if (Context->PreviousStatement == NULL) {
  4380. RtlDebugPrint("Not (");
  4381. } else if (Statement->ArgumentsAcquired == 0) {
  4382. RtlDebugPrint(", ");
  4383. } else {
  4384. RtlDebugPrint(")");
  4385. }
  4386. }
  4387. if (Context->PreviousStatement == NULL) {
  4388. return STATUS_MORE_PROCESSING_REQUIRED;
  4389. }
  4390. //
  4391. // If not executing, then assume the argument would be there but don't
  4392. // try to dink with it.
  4393. //
  4394. if (Context->ExecuteStatements == FALSE) {
  4395. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4396. Statement->ArgumentsAcquired += 1;
  4397. } else {
  4398. NewArgument = Context->PreviousStatement->Reduction;
  4399. if (Statement->ArgumentsAcquired == 0) {
  4400. //
  4401. // Fail if there is no argument there.
  4402. //
  4403. if (Context->PreviousStatement->Reduction == NULL) {
  4404. return STATUS_ARGUMENT_EXPECTED;
  4405. }
  4406. //
  4407. // Perform an implicit conversion if needed.
  4408. //
  4409. if (NewArgument->Type != AcpiObjectInteger) {
  4410. NewArgument = AcpipConvertObjectType(Context,
  4411. NewArgument,
  4412. AcpiObjectInteger);
  4413. if (NewArgument == NULL) {
  4414. return STATUS_CONVERSION_FAILED;
  4415. }
  4416. //
  4417. // The object is fine, take ownership of it.
  4418. //
  4419. } else {
  4420. AcpipObjectAddReference(NewArgument);
  4421. }
  4422. } else {
  4423. if (NewArgument != NULL) {
  4424. AcpipObjectAddReference(NewArgument);
  4425. }
  4426. }
  4427. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4428. Statement->ArgumentsAcquired += 1;
  4429. }
  4430. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4431. return STATUS_MORE_PROCESSING_REQUIRED;
  4432. }
  4433. }
  4434. //
  4435. // Evaluate the result.
  4436. //
  4437. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4438. Statement->Reduction = NULL;
  4439. if (Context->ExecuteStatements == FALSE) {
  4440. return STATUS_SUCCESS;
  4441. }
  4442. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  4443. //
  4444. // Seems like so much build up just for this...
  4445. //
  4446. ResultValue = ~(Statement->Argument[0]->U.Integer.Value);
  4447. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  4448. AcpiObjectInteger,
  4449. NULL,
  4450. &ResultValue,
  4451. sizeof(ULONGLONG));
  4452. if (Statement->Reduction == NULL) {
  4453. return STATUS_UNSUCCESSFUL;
  4454. }
  4455. if (Statement->Argument[1] != NULL) {
  4456. return AcpipPerformStoreOperation(Context,
  4457. Statement->Reduction,
  4458. Statement->Argument[0]);
  4459. }
  4460. return STATUS_SUCCESS;
  4461. }
  4462. KSTATUS
  4463. AcpipEvaluateObjectTypeStatement (
  4464. PAML_EXECUTION_CONTEXT Context,
  4465. PAML_STATEMENT Statement
  4466. )
  4467. /*++
  4468. Routine Description:
  4469. This routine evaluates an Object Type statement.
  4470. Arguments:
  4471. Context - Supplies a pointer to the current AML execution context.
  4472. Statement - Supplies a pointer to the statement to evaluate.
  4473. Return Value:
  4474. Status code.
  4475. --*/
  4476. {
  4477. PACPI_OBJECT NewArgument;
  4478. PACPI_OBJECT Object;
  4479. ULONGLONG ObjectType;
  4480. //
  4481. // If not all arguments are acquired, evaluate the previous statement to get
  4482. // the next argument.
  4483. //
  4484. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4485. //
  4486. // Print out the piece of the statement depending on the number of
  4487. // arguments acquired.
  4488. //
  4489. if (Context->PrintStatements != FALSE) {
  4490. if (Context->PreviousStatement == NULL) {
  4491. RtlDebugPrint("ObjectType (");
  4492. } else {
  4493. RtlDebugPrint(")");
  4494. }
  4495. }
  4496. if (Context->PreviousStatement == NULL) {
  4497. return STATUS_MORE_PROCESSING_REQUIRED;
  4498. }
  4499. //
  4500. // If not executing, then assume the argument would be there but don't
  4501. // try to dink with it.
  4502. //
  4503. if (Context->ExecuteStatements == FALSE) {
  4504. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4505. Statement->ArgumentsAcquired += 1;
  4506. } else {
  4507. NewArgument = Context->PreviousStatement->Reduction;
  4508. if (Statement->ArgumentsAcquired == 0) {
  4509. //
  4510. // Fail if there is no argument there.
  4511. //
  4512. if (Context->PreviousStatement->Reduction == NULL) {
  4513. return STATUS_ARGUMENT_EXPECTED;
  4514. }
  4515. AcpipObjectAddReference(NewArgument);
  4516. } else {
  4517. if (NewArgument != NULL) {
  4518. AcpipObjectAddReference(NewArgument);
  4519. }
  4520. }
  4521. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4522. Statement->ArgumentsAcquired += 1;
  4523. }
  4524. }
  4525. //
  4526. // Evaluate the result.
  4527. //
  4528. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4529. Statement->Reduction = NULL;
  4530. if (Context->ExecuteStatements == FALSE) {
  4531. return STATUS_SUCCESS;
  4532. }
  4533. Object = Statement->Argument[0];
  4534. while (Object->Type == AcpiObjectAlias) {
  4535. Object = Object->U.Alias.DestinationObject;
  4536. }
  4537. ObjectType = Object->Type;
  4538. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  4539. AcpiObjectInteger,
  4540. NULL,
  4541. &ObjectType,
  4542. sizeof(ULONGLONG));
  4543. if (Statement->Reduction == NULL) {
  4544. return STATUS_UNSUCCESSFUL;
  4545. }
  4546. return STATUS_SUCCESS;
  4547. }
  4548. KSTATUS
  4549. AcpipEvaluateOperationRegionStatement (
  4550. PAML_EXECUTION_CONTEXT Context,
  4551. PAML_STATEMENT Statement
  4552. )
  4553. /*++
  4554. Routine Description:
  4555. This routine evaluates an Operation Region statement.
  4556. Arguments:
  4557. Context - Supplies a pointer to the current AML execution context.
  4558. Statement - Supplies a pointer to the statement to evaluate.
  4559. Return Value:
  4560. Status code.
  4561. --*/
  4562. {
  4563. PSTR Name;
  4564. PACPI_OBJECT NewArgument;
  4565. ULONGLONG RegionLength;
  4566. ULONGLONG RegionOffset;
  4567. ACPI_OPERATION_REGION_SPACE RegionSpace;
  4568. KSTATUS Status;
  4569. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4570. //
  4571. // If not all arguments are acquired, evaluate the previous statement to get
  4572. // the next argument.
  4573. //
  4574. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4575. //
  4576. // Print out the piece of the statement depending on the number of
  4577. // arguments acquired.
  4578. //
  4579. if (Context->PrintStatements != FALSE) {
  4580. if (Context->PreviousStatement == NULL) {
  4581. RtlDebugPrint("OpRegion (%s, %x, ",
  4582. Statement->Argument[0]->U.String.String,
  4583. Statement->AdditionalData);
  4584. } else if (Statement->ArgumentsAcquired == 1) {
  4585. RtlDebugPrint(", ");
  4586. } else {
  4587. RtlDebugPrint(")");
  4588. }
  4589. }
  4590. if (Context->PreviousStatement == NULL) {
  4591. return STATUS_MORE_PROCESSING_REQUIRED;
  4592. }
  4593. //
  4594. // If not executing, then assume the argument would be there but don't
  4595. // try to dink with it.
  4596. //
  4597. if (Context->ExecuteStatements == FALSE) {
  4598. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4599. Statement->ArgumentsAcquired += 1;
  4600. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4601. return STATUS_MORE_PROCESSING_REQUIRED;
  4602. }
  4603. } else {
  4604. NewArgument = Context->PreviousStatement->Reduction;
  4605. //
  4606. // Fail if there is no argument there.
  4607. //
  4608. if (Context->PreviousStatement->Reduction == NULL) {
  4609. return STATUS_ARGUMENT_EXPECTED;
  4610. }
  4611. //
  4612. // Perform an implicit conversion if needed.
  4613. //
  4614. if (NewArgument->Type != AcpiObjectInteger) {
  4615. NewArgument = AcpipConvertObjectType(Context,
  4616. NewArgument,
  4617. AcpiObjectInteger);
  4618. if (NewArgument == NULL) {
  4619. return STATUS_CONVERSION_FAILED;
  4620. }
  4621. //
  4622. // The object is fine, take ownership of it.
  4623. //
  4624. } else {
  4625. AcpipObjectAddReference(NewArgument);
  4626. }
  4627. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4628. Statement->ArgumentsAcquired += 1;
  4629. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4630. return STATUS_MORE_PROCESSING_REQUIRED;
  4631. }
  4632. }
  4633. }
  4634. //
  4635. // Evaluate the result.
  4636. //
  4637. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4638. Statement->Reduction = NULL;
  4639. if (Context->ExecuteStatements == FALSE) {
  4640. return STATUS_SUCCESS;
  4641. }
  4642. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4643. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  4644. ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
  4645. Name = Statement->Argument[0]->U.String.String;
  4646. RegionOffset = Statement->Argument[1]->U.Integer.Value;
  4647. RegionLength = Statement->Argument[2]->U.Integer.Value;
  4648. RegionSpace = (UCHAR)Statement->AdditionalData;
  4649. Status = AcpipCreateOperationRegion(Context,
  4650. Name,
  4651. RegionSpace,
  4652. RegionOffset,
  4653. RegionLength);
  4654. if (!KSUCCESS(Status)) {
  4655. return Status;
  4656. }
  4657. return STATUS_SUCCESS;
  4658. }
  4659. KSTATUS
  4660. AcpipEvaluatePackageStatement (
  4661. PAML_EXECUTION_CONTEXT Context,
  4662. PAML_STATEMENT Statement
  4663. )
  4664. /*++
  4665. Routine Description:
  4666. This routine evaluates a Package or Variable Package statement.
  4667. Arguments:
  4668. Context - Supplies a pointer to the current AML execution context.
  4669. Statement - Supplies a pointer to the statement to evaluate.
  4670. Return Value:
  4671. Status code.
  4672. --*/
  4673. {
  4674. ULONG BufferSize;
  4675. PACPI_OBJECT NewArgument;
  4676. if (Context->PreviousStatement == NULL) {
  4677. Context->IndentationLevel += 1;
  4678. if (Context->PrintStatements != FALSE) {
  4679. if (Statement->Type == AmlStatementPackage) {
  4680. RtlDebugPrint("Package (%d) {", Statement->AdditionalData2);
  4681. AcpipPrintIndentedNewLine(Context);
  4682. } else {
  4683. ASSERT(Statement->Type == AmlStatementVariablePackage);
  4684. RtlDebugPrint("VarPackage (");
  4685. }
  4686. }
  4687. }
  4688. //
  4689. // If not all arguments are acquired, evaluate the previous statement to get
  4690. // the next argument. This only occurs in a variable package when looking
  4691. // for the package size.
  4692. //
  4693. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4694. if (Context->PreviousStatement == NULL) {
  4695. return STATUS_MORE_PROCESSING_REQUIRED;
  4696. }
  4697. //
  4698. // If not executing, then assume the argument would be there but don't
  4699. // try to dink with it.
  4700. //
  4701. if (Context->ExecuteStatements == FALSE) {
  4702. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  4703. Statement->ArgumentsAcquired += 1;
  4704. } else {
  4705. NewArgument = Context->PreviousStatement->Reduction;
  4706. ASSERT(Statement->ArgumentsAcquired == 0);
  4707. //
  4708. // Fail if there is no argument there.
  4709. //
  4710. if (NewArgument == NULL) {
  4711. return STATUS_ARGUMENT_EXPECTED;
  4712. }
  4713. //
  4714. // Perform an implicit conversion if needed.
  4715. //
  4716. if (NewArgument->Type != AcpiObjectInteger) {
  4717. NewArgument = AcpipConvertObjectType(Context,
  4718. NewArgument,
  4719. AcpiObjectInteger);
  4720. if (NewArgument == NULL) {
  4721. return STATUS_CONVERSION_FAILED;
  4722. }
  4723. //
  4724. // The object is fine, take ownership of it.
  4725. //
  4726. } else {
  4727. AcpipObjectAddReference(NewArgument);
  4728. }
  4729. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  4730. Statement->ArgumentsAcquired += 1;
  4731. }
  4732. //
  4733. // Finish printing the header for the variable package.
  4734. //
  4735. if (Context->PrintStatements != FALSE) {
  4736. RtlDebugPrint(") {");
  4737. AcpipPrintIndentedNewLine(Context);
  4738. }
  4739. //
  4740. // Assuming the length isn't 0, wait for the first package object.
  4741. //
  4742. if (Context->CurrentOffset != Statement->AdditionalData) {
  4743. return STATUS_MORE_PROCESSING_REQUIRED;
  4744. }
  4745. }
  4746. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  4747. //
  4748. // If not at the end, add this to the collection.
  4749. //
  4750. if ((Context->PrintStatements != FALSE) &&
  4751. (Context->CurrentOffset != Statement->AdditionalData) &&
  4752. (Context->PreviousStatement != NULL)) {
  4753. RtlDebugPrint(", ");
  4754. AcpipPrintIndentedNewLine(Context);
  4755. }
  4756. if (Context->ExecuteStatements != FALSE) {
  4757. //
  4758. // If the object has never been created before, create it now.
  4759. //
  4760. if (Statement->Reduction == NULL) {
  4761. BufferSize = Statement->AdditionalData2 * sizeof(PACPI_OBJECT);
  4762. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  4763. AcpiObjectPackage,
  4764. NULL,
  4765. NULL,
  4766. BufferSize);
  4767. if (Statement->Reduction == NULL) {
  4768. return STATUS_UNSUCCESSFUL;
  4769. }
  4770. //
  4771. // Additional data 2 now becomes a counter of the current
  4772. // element.
  4773. //
  4774. Statement->AdditionalData2 = 0;
  4775. }
  4776. //
  4777. // Add the object to the package/array.
  4778. //
  4779. if (Context->PreviousStatement != NULL) {
  4780. if (Context->PreviousStatement->Reduction == NULL) {
  4781. return STATUS_ARGUMENT_EXPECTED;
  4782. }
  4783. AcpipSetPackageObject(Statement->Reduction,
  4784. Statement->AdditionalData2,
  4785. Context->PreviousStatement->Reduction);
  4786. Statement->AdditionalData2 += 1;
  4787. }
  4788. }
  4789. if (Context->CurrentOffset == Statement->AdditionalData) {
  4790. if (Context->PrintStatements != FALSE) {
  4791. RtlDebugPrint("}");
  4792. }
  4793. Context->IndentationLevel -= 1;
  4794. return STATUS_SUCCESS;
  4795. }
  4796. return STATUS_MORE_PROCESSING_REQUIRED;
  4797. }
  4798. KSTATUS
  4799. AcpipEvaluatePowerResourceStatement (
  4800. PAML_EXECUTION_CONTEXT Context,
  4801. PAML_STATEMENT Statement
  4802. )
  4803. /*++
  4804. Routine Description:
  4805. This routine evaluates a Power Resource declaration statement.
  4806. Arguments:
  4807. Context - Supplies a pointer to the current AML execution context.
  4808. Statement - Supplies a pointer to the statement to evaluate.
  4809. Return Value:
  4810. Status code.
  4811. --*/
  4812. {
  4813. PUCHAR DataPointer;
  4814. PSTR Name;
  4815. ACPI_POWER_RESOURCE_OBJECT PowerResource;
  4816. PACPI_OBJECT PowerResourceObject;
  4817. if (Context->PreviousStatement == NULL) {
  4818. Statement->SavedScope = NULL;
  4819. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4820. Name = Statement->Argument[0]->U.String.String;
  4821. //
  4822. // Get the system level and resource order.
  4823. //
  4824. DataPointer = Context->AmlCode + Statement->AdditionalData2;
  4825. PowerResource.SystemLevel = *DataPointer;
  4826. PowerResource.ResourceOrder = *(PUSHORT)(DataPointer + 1);
  4827. if (Context->PrintStatements != FALSE) {
  4828. RtlDebugPrint("PowerResource (%s, %d, %d) {",
  4829. Name,
  4830. PowerResource.SystemLevel,
  4831. PowerResource.ResourceOrder);
  4832. }
  4833. if (Context->ExecuteStatements != FALSE) {
  4834. //
  4835. // Create the power resource object.
  4836. //
  4837. PowerResourceObject = AcpipCreateNamespaceObject(
  4838. Context,
  4839. AcpiObjectPowerResource,
  4840. Name,
  4841. &PowerResource,
  4842. sizeof(ACPI_POWER_RESOURCE_OBJECT));
  4843. if (PowerResourceObject == NULL) {
  4844. return STATUS_UNSUCCESSFUL;
  4845. }
  4846. //
  4847. // Make this device the current scope.
  4848. //
  4849. Statement->SavedScope = Context->CurrentScope;
  4850. Context->CurrentScope = PowerResourceObject;
  4851. Statement->Reduction = PowerResourceObject;
  4852. }
  4853. Context->IndentationLevel += 1;
  4854. }
  4855. //
  4856. // If execution is not done with the scope, keep this statement on the
  4857. // stack.
  4858. //
  4859. if (Context->CurrentOffset < Statement->AdditionalData) {
  4860. AcpipPrintIndentedNewLine(Context);
  4861. return STATUS_MORE_PROCESSING_REQUIRED;
  4862. }
  4863. //
  4864. // Pop this puppy off the stack.
  4865. //
  4866. Context->CurrentScope = Statement->SavedScope;
  4867. Context->IndentationLevel -= 1;
  4868. if (Context->PrintStatements != FALSE) {
  4869. AcpipPrintIndentedNewLine(Context);
  4870. RtlDebugPrint("}");
  4871. }
  4872. AcpipPrintIndentedNewLine(Context);
  4873. return STATUS_SUCCESS;
  4874. }
  4875. KSTATUS
  4876. AcpipEvaluateProcessorStatement (
  4877. PAML_EXECUTION_CONTEXT Context,
  4878. PAML_STATEMENT Statement
  4879. )
  4880. /*++
  4881. Routine Description:
  4882. This routine evaluates a Power Resource declaration statement.
  4883. Arguments:
  4884. Context - Supplies a pointer to the current AML execution context.
  4885. Statement - Supplies a pointer to the statement to evaluate.
  4886. Return Value:
  4887. Status code.
  4888. --*/
  4889. {
  4890. PUCHAR DataPointer;
  4891. PSTR DeviceName;
  4892. ACPI_PROCESSOR_OBJECT Processor;
  4893. PACPI_OBJECT ProcessorObject;
  4894. if (Context->PreviousStatement == NULL) {
  4895. Statement->SavedScope = NULL;
  4896. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  4897. DeviceName = Statement->Argument[0]->U.String.String;
  4898. //
  4899. // Get the processor ID and processor block register information.
  4900. //
  4901. RtlZeroMemory(&Processor, sizeof(ACPI_PROCESSOR_OBJECT));
  4902. DataPointer = Context->AmlCode + Statement->AdditionalData2;
  4903. Processor.ProcessorId = *DataPointer;
  4904. DataPointer += sizeof(BYTE);
  4905. Processor.ProcessorBlockAddress = *(PULONG)DataPointer;
  4906. DataPointer += sizeof(ULONG);
  4907. Processor.ProcessorBlockLength = *DataPointer;
  4908. if (Context->PrintStatements != FALSE) {
  4909. RtlDebugPrint("Processor (%s, %d, 0x%x, %d) {",
  4910. DeviceName,
  4911. Processor.ProcessorId,
  4912. Processor.ProcessorBlockAddress,
  4913. Processor.ProcessorBlockLength);
  4914. }
  4915. if (Context->ExecuteStatements != FALSE) {
  4916. //
  4917. // Create the processor object.
  4918. //
  4919. ProcessorObject = AcpipCreateNamespaceObject(
  4920. Context,
  4921. AcpiObjectProcessor,
  4922. DeviceName,
  4923. &Processor,
  4924. sizeof(ACPI_PROCESSOR_OBJECT));
  4925. if (ProcessorObject == NULL) {
  4926. return STATUS_UNSUCCESSFUL;
  4927. }
  4928. //
  4929. // Make this device the current scope.
  4930. //
  4931. Statement->SavedScope = Context->CurrentScope;
  4932. Context->CurrentScope = ProcessorObject;
  4933. Statement->Reduction = ProcessorObject;
  4934. }
  4935. Context->IndentationLevel += 1;
  4936. }
  4937. //
  4938. // If execution is not done with the scope, keep this statement on the
  4939. // stack.
  4940. //
  4941. if (Context->CurrentOffset < Statement->AdditionalData) {
  4942. AcpipPrintIndentedNewLine(Context);
  4943. return STATUS_MORE_PROCESSING_REQUIRED;
  4944. }
  4945. //
  4946. // Pop this puppy off the stack.
  4947. //
  4948. Context->CurrentScope = Statement->SavedScope;
  4949. Context->IndentationLevel -= 1;
  4950. if (Context->PrintStatements != FALSE) {
  4951. AcpipPrintIndentedNewLine(Context);
  4952. RtlDebugPrint("}");
  4953. }
  4954. AcpipPrintIndentedNewLine(Context);
  4955. return STATUS_SUCCESS;
  4956. }
  4957. KSTATUS
  4958. AcpipEvaluateReferenceOfStatement (
  4959. PAML_EXECUTION_CONTEXT Context,
  4960. PAML_STATEMENT Statement
  4961. )
  4962. /*++
  4963. Routine Description:
  4964. This routine evaluates an "Reference Of" statement.
  4965. Arguments:
  4966. Context - Supplies a pointer to the current AML execution context.
  4967. Statement - Supplies a pointer to the statement to evaluate.
  4968. Return Value:
  4969. Status code.
  4970. --*/
  4971. {
  4972. //
  4973. // Gather arguments if needed.
  4974. //
  4975. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  4976. if (Context->PrintStatements != FALSE) {
  4977. if (Context->PreviousStatement == NULL) {
  4978. RtlDebugPrint("RefOf (");
  4979. } else {
  4980. RtlDebugPrint(")");
  4981. }
  4982. }
  4983. //
  4984. // If there is no previous statement, wait for the argument to come in.
  4985. //
  4986. if (Context->PreviousStatement == NULL) {
  4987. return STATUS_MORE_PROCESSING_REQUIRED;
  4988. //
  4989. // Increment the reference count on the object.
  4990. //
  4991. } else {
  4992. if (Context->ExecuteStatements == FALSE) {
  4993. Statement->Argument[0] = NULL;
  4994. } else {
  4995. if (Context->PreviousStatement->Reduction == NULL) {
  4996. return STATUS_ARGUMENT_EXPECTED;
  4997. }
  4998. Statement->Argument[0] = Context->PreviousStatement->Reduction;
  4999. AcpipObjectAddReference(Context->PreviousStatement->Reduction);
  5000. }
  5001. Statement->ArgumentsAcquired += 1;
  5002. }
  5003. }
  5004. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5005. if (Context->ExecuteStatements != FALSE) {
  5006. Statement->Reduction = AcpipCreateNamespaceObject(
  5007. Context,
  5008. AcpiObjectAlias,
  5009. NULL,
  5010. &(Statement->Argument[0]),
  5011. sizeof(PACPI_OBJECT));
  5012. if (Statement->Reduction == NULL) {
  5013. return STATUS_UNSUCCESSFUL;
  5014. }
  5015. }
  5016. return STATUS_SUCCESS;
  5017. }
  5018. KSTATUS
  5019. AcpipEvaluateReturnStatement (
  5020. PAML_EXECUTION_CONTEXT Context,
  5021. PAML_STATEMENT Statement
  5022. )
  5023. /*++
  5024. Routine Description:
  5025. This routine evaluates an Return statement.
  5026. Arguments:
  5027. Context - Supplies a pointer to the current AML execution context.
  5028. Statement - Supplies a pointer to the statement to evaluate.
  5029. Return Value:
  5030. Status code.
  5031. --*/
  5032. {
  5033. //
  5034. // Gather arguments if needed.
  5035. //
  5036. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5037. if (Context->PrintStatements != FALSE) {
  5038. if (Context->PreviousStatement == NULL) {
  5039. RtlDebugPrint("Return (");
  5040. }
  5041. }
  5042. if (Context->PreviousStatement == NULL) {
  5043. return STATUS_MORE_PROCESSING_REQUIRED;
  5044. //
  5045. // Increment the reference count on the object.
  5046. //
  5047. } else {
  5048. if (Context->ExecuteStatements != FALSE) {
  5049. if (Context->PreviousStatement->Reduction != NULL) {
  5050. Statement->Argument[0] =
  5051. Context->PreviousStatement->Reduction;
  5052. AcpipObjectAddReference(Statement->Argument[0]);
  5053. }
  5054. } else {
  5055. Statement->Argument[0] = NULL;
  5056. }
  5057. Statement->ArgumentsAcquired += 1;
  5058. }
  5059. }
  5060. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5061. if (Context->PrintStatements != FALSE) {
  5062. RtlDebugPrint(")");
  5063. }
  5064. //
  5065. // Return from the function.
  5066. //
  5067. if (Context->ExecuteStatements != FALSE) {
  5068. //
  5069. // If there was an old return value there (possibly from a nested
  5070. // function call), release it.
  5071. //
  5072. if (Context->ReturnValue != NULL) {
  5073. AcpipObjectReleaseReference(Context->ReturnValue);
  5074. }
  5075. Context->ReturnValue = Statement->Argument[0];
  5076. AcpipObjectAddReference(Context->ReturnValue);
  5077. AcpipPopExecutingStatements(Context, FALSE, FALSE);
  5078. AcpipPopCurrentMethodContext(Context);
  5079. }
  5080. return STATUS_SUCCESS;
  5081. }
  5082. KSTATUS
  5083. AcpipEvaluateScopeStatement (
  5084. PAML_EXECUTION_CONTEXT Context,
  5085. PAML_STATEMENT Statement
  5086. )
  5087. /*++
  5088. Routine Description:
  5089. This routine evaluates a Device declaration statement.
  5090. Arguments:
  5091. Context - Supplies a pointer to the current AML execution context.
  5092. Statement - Supplies a pointer to the statement to evaluate.
  5093. Return Value:
  5094. Status code.
  5095. --*/
  5096. {
  5097. PACPI_OBJECT Object;
  5098. PSTR ScopeName;
  5099. if (Context->PreviousStatement == NULL) {
  5100. Statement->SavedScope = NULL;
  5101. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  5102. ScopeName = Statement->Argument[0]->U.String.String;
  5103. if (Context->PrintStatements != FALSE) {
  5104. RtlDebugPrint("Scope (%s) {", ScopeName);
  5105. }
  5106. if (Context->ExecuteStatements != FALSE) {
  5107. //
  5108. // Go find the object.
  5109. //
  5110. Object = AcpipGetNamespaceObject(ScopeName, Context->CurrentScope);
  5111. //
  5112. // Make this device the current scope.
  5113. //
  5114. Statement->SavedScope = Context->CurrentScope;
  5115. Context->CurrentScope = Object;
  5116. }
  5117. Context->IndentationLevel += 1;
  5118. }
  5119. //
  5120. // If execution is not done with the scope, keep this statement on the
  5121. // stack.
  5122. //
  5123. if (Context->CurrentOffset < Statement->AdditionalData) {
  5124. AcpipPrintIndentedNewLine(Context);
  5125. return STATUS_MORE_PROCESSING_REQUIRED;
  5126. }
  5127. //
  5128. // Pop this puppy off the stack.
  5129. //
  5130. Context->CurrentScope = Statement->SavedScope;
  5131. Context->IndentationLevel -= 1;
  5132. if (Context->PrintStatements != FALSE) {
  5133. AcpipPrintIndentedNewLine(Context);
  5134. RtlDebugPrint("}");
  5135. }
  5136. AcpipPrintIndentedNewLine(Context);
  5137. Statement->Reduction = NULL;
  5138. return STATUS_SUCCESS;
  5139. }
  5140. KSTATUS
  5141. AcpipEvaluateSizeOfStatement (
  5142. PAML_EXECUTION_CONTEXT Context,
  5143. PAML_STATEMENT Statement
  5144. )
  5145. /*++
  5146. Routine Description:
  5147. This routine evaluates a "Size Of" statement.
  5148. Arguments:
  5149. Context - Supplies a pointer to the current AML execution context.
  5150. Statement - Supplies a pointer to the statement to evaluate.
  5151. Return Value:
  5152. Status code.
  5153. --*/
  5154. {
  5155. PACPI_OBJECT Object;
  5156. ULONGLONG Size;
  5157. //
  5158. // Gather arguments.
  5159. //
  5160. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5161. if (Context->PrintStatements != FALSE) {
  5162. if (Context->PreviousStatement == NULL) {
  5163. RtlDebugPrint("SizeOf (");
  5164. }
  5165. }
  5166. if (Context->PreviousStatement == NULL) {
  5167. return STATUS_MORE_PROCESSING_REQUIRED;
  5168. } else {
  5169. Statement->Argument[0] = NULL;
  5170. if (Context->ExecuteStatements != FALSE) {
  5171. Statement->Argument[0] = Context->PreviousStatement->Reduction;
  5172. AcpipObjectAddReference(Statement->Argument[0]);
  5173. }
  5174. Statement->ArgumentsAcquired += 1;
  5175. }
  5176. }
  5177. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5178. if (Context->PrintStatements != FALSE) {
  5179. RtlDebugPrint(")");
  5180. }
  5181. Object = NULL;
  5182. Statement->Reduction = NULL;
  5183. if (Context->ExecuteStatements != FALSE) {
  5184. //
  5185. // If the object is an alias, use the destination.
  5186. //
  5187. Object = Statement->Argument[0];
  5188. while (Object->Type == AcpiObjectAlias) {
  5189. Object = Statement->Argument[0]->U.Alias.DestinationObject;
  5190. }
  5191. Size = 0;
  5192. switch (Object->Type) {
  5193. case AcpiObjectString:
  5194. if (Object->U.String.String != NULL) {
  5195. Size = RtlStringLength(Object->U.String.String);
  5196. }
  5197. break;
  5198. case AcpiObjectBuffer:
  5199. Size = Object->U.Buffer.Length;
  5200. break;
  5201. case AcpiObjectPackage:
  5202. Size = Object->U.Package.ElementCount;
  5203. break;
  5204. default:
  5205. return STATUS_NOT_SUPPORTED;
  5206. }
  5207. //
  5208. // Create the integer result.
  5209. //
  5210. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  5211. AcpiObjectInteger,
  5212. NULL,
  5213. &Size,
  5214. sizeof(ULONGLONG));
  5215. if (Statement->Reduction == NULL) {
  5216. return STATUS_UNSUCCESSFUL;
  5217. }
  5218. }
  5219. return STATUS_SUCCESS;
  5220. }
  5221. KSTATUS
  5222. AcpipEvaluateStoreStatement (
  5223. PAML_EXECUTION_CONTEXT Context,
  5224. PAML_STATEMENT Statement
  5225. )
  5226. /*++
  5227. Routine Description:
  5228. This routine evaluates a Store statement.
  5229. Arguments:
  5230. Context - Supplies a pointer to the current AML execution context.
  5231. Statement - Supplies a pointer to the statement to evaluate.
  5232. Return Value:
  5233. Status code.
  5234. --*/
  5235. {
  5236. PACPI_OBJECT NewArgument;
  5237. KSTATUS Status;
  5238. //
  5239. // If not all arguments are acquired, evaluate the previous statement to get
  5240. // the next argument.
  5241. //
  5242. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5243. //
  5244. // Print out the piece of the statement depending on the number of
  5245. // arguments acquired.
  5246. //
  5247. if (Context->PrintStatements != FALSE) {
  5248. if (Context->PreviousStatement == NULL) {
  5249. RtlDebugPrint("Store (");
  5250. } else if (Statement->ArgumentsAcquired == 0) {
  5251. RtlDebugPrint(", ");
  5252. } else {
  5253. RtlDebugPrint(")");
  5254. }
  5255. }
  5256. if (Context->PreviousStatement == NULL) {
  5257. return STATUS_MORE_PROCESSING_REQUIRED;
  5258. }
  5259. //
  5260. // If not executing, then assume the argument would be there but don't
  5261. // try to dink with it.
  5262. //
  5263. if (Context->ExecuteStatements == FALSE) {
  5264. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  5265. Statement->ArgumentsAcquired += 1;
  5266. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5267. return STATUS_MORE_PROCESSING_REQUIRED;
  5268. }
  5269. } else {
  5270. NewArgument = Context->PreviousStatement->Reduction;
  5271. //
  5272. // Fail if there is no argument there.
  5273. //
  5274. if (Context->PreviousStatement->Reduction == NULL) {
  5275. return STATUS_ARGUMENT_EXPECTED;
  5276. }
  5277. AcpipObjectAddReference(NewArgument);
  5278. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  5279. Statement->ArgumentsAcquired += 1;
  5280. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5281. return STATUS_MORE_PROCESSING_REQUIRED;
  5282. }
  5283. }
  5284. }
  5285. //
  5286. // All arguments have been acquired.
  5287. //
  5288. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5289. Statement->Reduction = NULL;
  5290. if (Context->ExecuteStatements == FALSE) {
  5291. return STATUS_SUCCESS;
  5292. }
  5293. //
  5294. // Store the first argument into the second. The reduction of the statement
  5295. // is the second operand.
  5296. //
  5297. Status = AcpipPerformStoreOperation(Context,
  5298. Statement->Argument[0],
  5299. Statement->Argument[1]);
  5300. if (!KSUCCESS(Status)) {
  5301. return Status;
  5302. }
  5303. Statement->Reduction = Statement->Argument[1];
  5304. AcpipObjectAddReference(Statement->Reduction);
  5305. return STATUS_SUCCESS;
  5306. }
  5307. KSTATUS
  5308. AcpipEvaluateSyncObjectStatement (
  5309. PAML_EXECUTION_CONTEXT Context,
  5310. PAML_STATEMENT Statement
  5311. )
  5312. /*++
  5313. Routine Description:
  5314. This routine evaluates a Release (mutex), Reset (event), or Signal (event)
  5315. statement.
  5316. Arguments:
  5317. Context - Supplies a pointer to the current AML execution context.
  5318. Statement - Supplies a pointer to the statement to evaluate.
  5319. Return Value:
  5320. Status code.
  5321. --*/
  5322. {
  5323. PACPI_OBJECT NameString;
  5324. PACPI_OBJECT NewArgument;
  5325. //
  5326. // Gather arguments if needed.
  5327. //
  5328. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5329. if (Context->PrintStatements != FALSE) {
  5330. if (Context->PreviousStatement == NULL) {
  5331. if (Statement->Type == AmlStatementRelease) {
  5332. RtlDebugPrint("Release (");
  5333. } else if (Statement->Type == AmlStatementSignal) {
  5334. RtlDebugPrint("Signal (");
  5335. } else {
  5336. ASSERT(Statement->Type == AmlStatementReset);
  5337. RtlDebugPrint("Reset (");
  5338. }
  5339. }
  5340. }
  5341. //
  5342. // The argument for Release, Reset, and Signal is a "SuperName", which
  5343. // is a SimpleName, DebugOp, or Type6Opcode. If this is the first time
  5344. // through, try to parse a name string.
  5345. //
  5346. if (Context->PreviousStatement == NULL) {
  5347. NameString = AcpipParseNameString(Context);
  5348. if (NameString == NULL) {
  5349. return STATUS_MORE_PROCESSING_REQUIRED;
  5350. }
  5351. if (Context->PrintStatements != FALSE) {
  5352. RtlDebugPrint(NameString->U.String.String);
  5353. }
  5354. if (Context->ExecuteStatements != FALSE) {
  5355. Statement->Argument[0] =
  5356. AcpipGetNamespaceObject(NameString->U.String.String,
  5357. Context->CurrentScope);
  5358. if (Statement->Argument[0] == NULL) {
  5359. return STATUS_NOT_FOUND;
  5360. }
  5361. } else {
  5362. Statement->Argument[0] = NULL;
  5363. }
  5364. if (Statement->Argument[0] != NULL) {
  5365. AcpipObjectAddReference(Statement->Argument[0]);
  5366. }
  5367. Statement->ArgumentsAcquired += 1;
  5368. AcpipObjectReleaseReference(NameString);
  5369. //
  5370. // Increment the reference count on the object.
  5371. //
  5372. } else {
  5373. if (Context->ExecuteStatements != FALSE) {
  5374. NewArgument = Context->PreviousStatement->Reduction;
  5375. if (NewArgument == NULL) {
  5376. return STATUS_ARGUMENT_EXPECTED;
  5377. }
  5378. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  5379. AcpipObjectAddReference(NewArgument);
  5380. }
  5381. Statement->ArgumentsAcquired += 1;
  5382. }
  5383. }
  5384. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5385. if (Context->PrintStatements != FALSE) {
  5386. RtlDebugPrint(")");
  5387. }
  5388. Statement->Reduction = NULL;
  5389. if (Context->ExecuteStatements != FALSE) {
  5390. if (Statement->Type == AmlStatementRelease) {
  5391. ASSERT(Statement->Argument[0]->Type == AcpiObjectMutex);
  5392. AcpipReleaseMutex(Context,
  5393. Statement->Argument[0]->U.Mutex.OsMutex);
  5394. } else if (Statement->Type == AmlStatementSignal) {
  5395. ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
  5396. AcpipSignalEvent(Statement->Argument[0]->U.Event.OsEvent);
  5397. } else {
  5398. ASSERT(Statement->Type == AmlStatementReset);
  5399. ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
  5400. AcpipResetEvent(Statement->Argument[0]->U.Event.OsEvent);
  5401. }
  5402. }
  5403. return STATUS_SUCCESS;
  5404. }
  5405. KSTATUS
  5406. AcpipEvaluateThermalZoneStatement (
  5407. PAML_EXECUTION_CONTEXT Context,
  5408. PAML_STATEMENT Statement
  5409. )
  5410. /*++
  5411. Routine Description:
  5412. This routine evaluates a Thermal Zone declaration statement.
  5413. Arguments:
  5414. Context - Supplies a pointer to the current AML execution context.
  5415. Statement - Supplies a pointer to the statement to evaluate.
  5416. Return Value:
  5417. Status code.
  5418. --*/
  5419. {
  5420. PSTR Name;
  5421. PACPI_OBJECT ThermalZoneObject;
  5422. if (Context->PreviousStatement == NULL) {
  5423. Statement->SavedScope = NULL;
  5424. ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
  5425. Name = Statement->Argument[0]->U.String.String;
  5426. if (Context->PrintStatements != FALSE) {
  5427. RtlDebugPrint("ThermalZone (%s) {", Name);
  5428. }
  5429. if (Context->ExecuteStatements != FALSE) {
  5430. //
  5431. // Create the thermal zone object.
  5432. //
  5433. ThermalZoneObject = AcpipCreateNamespaceObject(
  5434. Context,
  5435. AcpiObjectPowerResource,
  5436. Name,
  5437. NULL,
  5438. 0);
  5439. if (ThermalZoneObject == NULL) {
  5440. return STATUS_UNSUCCESSFUL;
  5441. }
  5442. //
  5443. // Make this device the current scope.
  5444. //
  5445. Statement->SavedScope = Context->CurrentScope;
  5446. Context->CurrentScope = ThermalZoneObject;
  5447. Statement->Reduction = ThermalZoneObject;
  5448. }
  5449. Context->IndentationLevel += 1;
  5450. }
  5451. //
  5452. // If execution is not done with the scope, keep this statement on the
  5453. // stack.
  5454. //
  5455. if (Context->CurrentOffset < Statement->AdditionalData) {
  5456. AcpipPrintIndentedNewLine(Context);
  5457. return STATUS_MORE_PROCESSING_REQUIRED;
  5458. }
  5459. //
  5460. // Pop this puppy off the stack.
  5461. //
  5462. Context->CurrentScope = Statement->SavedScope;
  5463. Context->IndentationLevel -= 1;
  5464. if (Context->PrintStatements != FALSE) {
  5465. AcpipPrintIndentedNewLine(Context);
  5466. RtlDebugPrint("}");
  5467. }
  5468. AcpipPrintIndentedNewLine(Context);
  5469. return STATUS_SUCCESS;
  5470. }
  5471. KSTATUS
  5472. AcpipEvaluateToFormatStatement (
  5473. PAML_EXECUTION_CONTEXT Context,
  5474. PAML_STATEMENT Statement
  5475. )
  5476. /*++
  5477. Routine Description:
  5478. This routine evaluates the "To" something and "From" something statements,
  5479. including ToBCD, ToBuffer, ToDecimalString, ToHexString, ToInteger,
  5480. ToString, ToUUID, Unicode, and FromBcd.
  5481. Arguments:
  5482. Context - Supplies a pointer to the current AML execution context.
  5483. Statement - Supplies a pointer to the statement to evaluate.
  5484. Return Value:
  5485. Status code.
  5486. --*/
  5487. {
  5488. ULONGLONG BcdValue;
  5489. ULONG ByteCount;
  5490. ULONG ByteIndex;
  5491. PUCHAR BytePointer;
  5492. ULONG ByteStringSize;
  5493. ULONG Digit;
  5494. ULONGLONG IntegerValue;
  5495. PACPI_OBJECT NewArgument;
  5496. ULONG Nibble;
  5497. CHAR ResultString[MAX_DECIMAL_STRING_LENGTH];
  5498. ULONGLONG ResultValue;
  5499. PSTR String;
  5500. ULONG StringSize;
  5501. //
  5502. // If not all arguments are acquired, evaluate the previous statement to get
  5503. // the next argument.
  5504. //
  5505. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5506. //
  5507. // Print out the piece of the statement depending on the number of
  5508. // arguments acquired.
  5509. //
  5510. if (Context->PrintStatements != FALSE) {
  5511. if (Context->PreviousStatement == NULL) {
  5512. switch (Statement->Type) {
  5513. case AmlStatementFromBcd:
  5514. RtlDebugPrint("FromBCD (");
  5515. break;
  5516. case AmlStatementToBcd:
  5517. RtlDebugPrint("ToBCD (");
  5518. break;
  5519. case AmlStatementToBuffer:
  5520. RtlDebugPrint("ToBuffer (");
  5521. break;
  5522. case AmlStatementToDecimalString:
  5523. RtlDebugPrint("ToDecimalString (");
  5524. break;
  5525. case AmlStatementToHexString:
  5526. RtlDebugPrint("ToHexString (");
  5527. break;
  5528. case AmlStatementToInteger:
  5529. RtlDebugPrint("ToInteger (");
  5530. break;
  5531. case AmlStatementToString:
  5532. RtlDebugPrint("ToString (");
  5533. break;
  5534. default:
  5535. ASSERT(FALSE);
  5536. return STATUS_NOT_SUPPORTED;
  5537. }
  5538. } else {
  5539. RtlDebugPrint(")");
  5540. }
  5541. }
  5542. if (Context->PreviousStatement == NULL) {
  5543. return STATUS_MORE_PROCESSING_REQUIRED;
  5544. }
  5545. //
  5546. // If not executing, then assume the argument would be there but don't
  5547. // try to dink with it.
  5548. //
  5549. if (Context->ExecuteStatements == FALSE) {
  5550. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  5551. Statement->ArgumentsAcquired += 1;
  5552. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5553. return STATUS_MORE_PROCESSING_REQUIRED;
  5554. }
  5555. } else {
  5556. NewArgument = Context->PreviousStatement->Reduction;
  5557. if (Statement->ArgumentsAcquired == 0) {
  5558. //
  5559. // Fail if there is no argument there.
  5560. //
  5561. if (Context->PreviousStatement->Reduction == NULL) {
  5562. return STATUS_ARGUMENT_EXPECTED;
  5563. }
  5564. //
  5565. // If it's not an integer, buffer, or string, fail.
  5566. //
  5567. if ((NewArgument->Type != AcpiObjectInteger) &&
  5568. (NewArgument->Type != AcpiObjectBuffer) &&
  5569. (NewArgument->Type != AcpiObjectString)) {
  5570. return STATUS_INVALID_PARAMETER;
  5571. }
  5572. //
  5573. // Perform an implicit conversion if needed.
  5574. //
  5575. if (((Statement->Type == AmlStatementToBcd) ||
  5576. (Statement->Type == AmlStatementFromBcd)) &&
  5577. (NewArgument->Type != AcpiObjectInteger)) {
  5578. NewArgument = AcpipConvertObjectType(Context,
  5579. NewArgument,
  5580. AcpiObjectInteger);
  5581. if (NewArgument == NULL) {
  5582. return STATUS_CONVERSION_FAILED;
  5583. }
  5584. //
  5585. // The object is fine, take ownership of it.
  5586. //
  5587. } else {
  5588. AcpipObjectAddReference(NewArgument);
  5589. }
  5590. } else {
  5591. ASSERT(Statement->ArgumentsAcquired == 1);
  5592. AcpipObjectAddReference(NewArgument);
  5593. }
  5594. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  5595. Statement->ArgumentsAcquired += 1;
  5596. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5597. return STATUS_MORE_PROCESSING_REQUIRED;
  5598. }
  5599. }
  5600. }
  5601. //
  5602. // Evaluate the result.
  5603. //
  5604. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5605. Statement->Reduction = NULL;
  5606. if (Context->ExecuteStatements == FALSE) {
  5607. return STATUS_SUCCESS;
  5608. }
  5609. switch (Statement->Type) {
  5610. case AmlStatementFromBcd:
  5611. //
  5612. // Convert the BCD value to an integer.
  5613. //
  5614. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  5615. BcdValue = Statement->Argument[0]->U.Integer.Value;
  5616. ResultValue = 0;
  5617. for (Nibble = 0; Nibble < sizeof(ULONGLONG) * 2; Nibble += 1) {
  5618. Digit = (BcdValue & 0xF000000000000000ULL) >> 60;
  5619. ResultValue = (ResultValue * 10) + Digit;
  5620. Digit = Digit << 4;
  5621. }
  5622. if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
  5623. ResultValue &= 0xFFFFFFFF;
  5624. }
  5625. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  5626. AcpiObjectInteger,
  5627. NULL,
  5628. &ResultValue,
  5629. sizeof(ULONGLONG));
  5630. break;
  5631. case AmlStatementToBcd:
  5632. //
  5633. // Convert the integer to a BCD value.
  5634. //
  5635. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  5636. IntegerValue = Statement->Argument[0]->U.Integer.Value;
  5637. ResultValue = 0;
  5638. for (Nibble = 0; Nibble < sizeof(ULONGLONG) * 2; Nibble += 1) {
  5639. if (IntegerValue == 0) {
  5640. break;
  5641. }
  5642. Digit = IntegerValue % 10;
  5643. ResultValue = (ResultValue << 4) | Digit;
  5644. IntegerValue = IntegerValue / 10;
  5645. }
  5646. if (IntegerValue != 0) {
  5647. return STATUS_CONVERSION_FAILED;
  5648. }
  5649. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  5650. AcpiObjectInteger,
  5651. NULL,
  5652. &ResultValue,
  5653. sizeof(ULONGLONG));
  5654. break;
  5655. case AmlStatementToBuffer:
  5656. Statement->Reduction = AcpipConvertObjectType(Context,
  5657. Statement->Argument[0],
  5658. AcpiObjectBuffer);
  5659. break;
  5660. case AmlStatementToDecimalString:
  5661. //
  5662. // If the result is already a string, no action is performed.
  5663. //
  5664. if (Statement->Argument[0]->Type == AcpiObjectString) {
  5665. Statement->Reduction = Statement->Argument[0];
  5666. AcpipObjectAddReference(Statement->Reduction);
  5667. //
  5668. // Convert the integer to a string.
  5669. //
  5670. } else if (Statement->Argument[0]->Type == AcpiObjectInteger) {
  5671. RtlPrintToString(ResultString,
  5672. MAX_DECIMAL_STRING_LENGTH,
  5673. CharacterEncodingAscii,
  5674. "%I64d",
  5675. Statement->Argument[0]->U.Integer.Value);
  5676. Statement->Reduction = AcpipCreateNamespaceObject(
  5677. Context,
  5678. AcpiObjectString,
  5679. NULL,
  5680. ResultString,
  5681. MAX_DECIMAL_STRING_LENGTH);
  5682. //
  5683. // Convert the buffer to a comma delimited string of decimal integers.
  5684. //
  5685. } else if (Statement->Argument[0]->Type == AcpiObjectBuffer) {
  5686. //
  5687. // Create the result string with buffer first. The size is up to
  5688. // three decimal digits, plus one comma per byte, minus the comma
  5689. // at the end, plus the null delimiter.
  5690. //
  5691. StringSize = Statement->Argument[0]->U.Buffer.Length * 4;
  5692. if (StringSize == 0) {
  5693. StringSize = 1;
  5694. }
  5695. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  5696. AcpiObjectString,
  5697. NULL,
  5698. NULL,
  5699. StringSize);
  5700. if (Statement->Reduction == NULL) {
  5701. return STATUS_UNSUCCESSFUL;
  5702. }
  5703. //
  5704. // Print out each byte individually, except the last one.
  5705. //
  5706. String = Statement->Reduction->U.String.String;
  5707. BytePointer = Statement->Argument[0]->U.Buffer.Buffer;
  5708. ByteCount = Statement->Argument[0]->U.Buffer.Length;
  5709. for (ByteIndex = 0; ByteIndex < ByteCount - 1; ByteIndex += 1) {
  5710. ByteStringSize = RtlPrintToString(String,
  5711. StringSize,
  5712. CharacterEncodingAscii,
  5713. "%d,",
  5714. *BytePointer);
  5715. if (ByteStringSize > StringSize) {
  5716. ByteStringSize = StringSize;
  5717. }
  5718. BytePointer += 1;
  5719. String += ByteStringSize;
  5720. StringSize -= ByteStringSize;
  5721. }
  5722. //
  5723. // Do the last one without a comma.
  5724. //
  5725. RtlPrintToString(String,
  5726. StringSize,
  5727. CharacterEncodingAscii,
  5728. "%d",
  5729. *BytePointer);
  5730. } else {
  5731. ASSERT(FALSE);
  5732. return STATUS_NOT_SUPPORTED;
  5733. }
  5734. break;
  5735. case AmlStatementToHexString:
  5736. //
  5737. // If the result is already a string, no action is performed.
  5738. //
  5739. if (Statement->Argument[0]->Type == AcpiObjectString) {
  5740. Statement->Reduction = Statement->Argument[0];
  5741. AcpipObjectAddReference(Statement->Reduction);
  5742. //
  5743. // Convert the integer or buffer to a string.
  5744. //
  5745. } else {
  5746. Statement->Reduction = AcpipConvertObjectType(
  5747. Context,
  5748. Statement->Argument[0],
  5749. AcpiObjectString);
  5750. }
  5751. break;
  5752. case AmlStatementToInteger:
  5753. if (Statement->Argument[0]->Type == AcpiObjectInteger) {
  5754. Statement->Reduction = Statement->Argument[0];
  5755. AcpipObjectAddReference(Statement->Reduction);
  5756. } else if (Statement->Argument[0]->Type == AcpiObjectBuffer) {
  5757. Statement->Reduction = AcpipConvertObjectType(
  5758. Context,
  5759. Statement->Argument[0],
  5760. AcpiObjectInteger);
  5761. } else if (Statement->Argument[0]->Type != AcpiObjectString) {
  5762. ASSERT(FALSE);
  5763. return STATUS_NOT_SUPPORTED;
  5764. }
  5765. String = Statement->Argument[0]->U.String.String;
  5766. if (String == NULL) {
  5767. break;
  5768. }
  5769. //
  5770. // Parse the string as a decimal or a hex string depending on whether
  5771. // there is an 0x prepending or not.
  5772. //
  5773. IntegerValue = 0;
  5774. if ((*String == '0') && (*(String + 1) == 'x')) {
  5775. while (((*String >= '0') && (*String <= '9')) ||
  5776. ((*String >= 'a') && (*String <= 'f')) ||
  5777. ((*String >= 'A') && (*String <= 'F'))) {
  5778. if ((*String >= '0') && (*String <= '9')) {
  5779. Digit = *String - '0';
  5780. } else if (((*String >= 'a') && (*String <= 'f'))) {
  5781. Digit = *String - 'a';
  5782. } else {
  5783. ASSERT((*String >= 'A') && (*String <= 'F'));
  5784. Digit = *String - 'A';
  5785. }
  5786. IntegerValue = (IntegerValue << 4) | Digit;
  5787. String += 1;
  5788. }
  5789. //
  5790. // Parse it as a decimal string.
  5791. //
  5792. } else {
  5793. while ((*String >= '0') && (*String <= '9')) {
  5794. Digit = *String - '0';
  5795. IntegerValue = (IntegerValue * 10) + Digit;
  5796. String += 1;
  5797. }
  5798. }
  5799. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  5800. AcpiObjectInteger,
  5801. NULL,
  5802. &IntegerValue,
  5803. sizeof(ULONGLONG));
  5804. break;
  5805. case AmlStatementToString:
  5806. Statement->Reduction = AcpipConvertObjectType(Context,
  5807. Statement->Argument[0],
  5808. AcpiObjectString);
  5809. break;
  5810. default:
  5811. ASSERT(FALSE);
  5812. return STATUS_NOT_SUPPORTED;
  5813. }
  5814. if (Statement->Reduction == NULL) {
  5815. return STATUS_UNSUCCESSFUL;
  5816. }
  5817. //
  5818. // Store the result in the target if supplied.
  5819. //
  5820. if (Statement->Argument[2] != NULL) {
  5821. return AcpipPerformStoreOperation(Context,
  5822. Statement->Reduction,
  5823. Statement->Argument[2]);
  5824. }
  5825. return STATUS_SUCCESS;
  5826. }
  5827. KSTATUS
  5828. AcpipEvaluateUnloadStatement (
  5829. PAML_EXECUTION_CONTEXT Context,
  5830. PAML_STATEMENT Statement
  5831. )
  5832. /*++
  5833. Routine Description:
  5834. This routine evaluates an Unload statement, which unloads a previously
  5835. loaded definition block.
  5836. Arguments:
  5837. Context - Supplies a pointer to the current AML execution context.
  5838. Statement - Supplies a pointer to the statement to evaluate.
  5839. Return Value:
  5840. Status code.
  5841. --*/
  5842. {
  5843. PACPI_OBJECT DdbHandle;
  5844. PACPI_OBJECT NewArgument;
  5845. //
  5846. // If not all arguments are acquired, evaluate the previous statement to get
  5847. // the next argument.
  5848. //
  5849. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5850. //
  5851. // Print out the piece of the statement depending on the number of
  5852. // arguments acquired.
  5853. //
  5854. if (Context->PrintStatements != FALSE) {
  5855. if (Context->PreviousStatement == NULL) {
  5856. RtlDebugPrint("Unload (");
  5857. } else if (Statement->ArgumentsAcquired == 0) {
  5858. RtlDebugPrint(")");
  5859. }
  5860. }
  5861. if (Context->PreviousStatement == NULL) {
  5862. return STATUS_MORE_PROCESSING_REQUIRED;
  5863. }
  5864. //
  5865. // If not executing, then assume the argument would be there but don't
  5866. // try to dink with it.
  5867. //
  5868. if (Context->ExecuteStatements == FALSE) {
  5869. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  5870. Statement->ArgumentsAcquired += 1;
  5871. } else {
  5872. NewArgument = Context->PreviousStatement->Reduction;
  5873. ASSERT(Statement->ArgumentsAcquired <= 1);
  5874. if (Context->PreviousStatement->Reduction != NULL) {
  5875. AcpipObjectAddReference(NewArgument);
  5876. }
  5877. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  5878. Statement->ArgumentsAcquired += 1;
  5879. }
  5880. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5881. return STATUS_MORE_PROCESSING_REQUIRED;
  5882. }
  5883. }
  5884. Statement->Reduction = NULL;
  5885. if (Context->ExecuteStatements == FALSE) {
  5886. return STATUS_SUCCESS;
  5887. }
  5888. DdbHandle = Statement->Argument[0];
  5889. ASSERT(DdbHandle != NULL);
  5890. AcpiUnloadDefinitionBlock(DdbHandle);
  5891. return STATUS_SUCCESS;
  5892. }
  5893. KSTATUS
  5894. AcpipEvaluateWaitStatement (
  5895. PAML_EXECUTION_CONTEXT Context,
  5896. PAML_STATEMENT Statement
  5897. )
  5898. /*++
  5899. Routine Description:
  5900. This routine evaluates an Wait (for Event) statement.
  5901. Arguments:
  5902. Context - Supplies a pointer to the current AML execution context.
  5903. Statement - Supplies a pointer to the statement to evaluate.
  5904. Return Value:
  5905. Status code.
  5906. --*/
  5907. {
  5908. PACPI_OBJECT IntegerObject;
  5909. PACPI_OBJECT NameString;
  5910. PACPI_OBJECT NewArgument;
  5911. ULONGLONG ResultValue;
  5912. ULONG TimeoutValue;
  5913. //
  5914. // Gather arguments if needed.
  5915. //
  5916. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  5917. if (Context->PrintStatements != FALSE) {
  5918. if (Context->PreviousStatement == NULL) {
  5919. RtlDebugPrint("Wait (");
  5920. } else if (Statement->ArgumentsAcquired == 0) {
  5921. RtlDebugPrint(", ");
  5922. } else {
  5923. RtlDebugPrint(")");
  5924. }
  5925. }
  5926. //
  5927. // The argument for Wait is a "SuperName", which is a SimpleName,
  5928. // DebugOp, or Type6Opcode. If this is the first time through, try to
  5929. // parse a name string.
  5930. //
  5931. if (Context->PreviousStatement == NULL) {
  5932. NameString = AcpipParseNameString(Context);
  5933. if (NameString == NULL) {
  5934. return STATUS_MORE_PROCESSING_REQUIRED;
  5935. }
  5936. if (Context->PrintStatements != FALSE) {
  5937. RtlDebugPrint(NameString->U.String.String);
  5938. }
  5939. if (Context->ExecuteStatements != FALSE) {
  5940. Statement->Argument[0] =
  5941. AcpipGetNamespaceObject(NameString->U.String.String,
  5942. Context->CurrentScope);
  5943. if (Statement->Argument[0] == NULL) {
  5944. return STATUS_NOT_FOUND;
  5945. }
  5946. AcpipObjectAddReference(Statement->Argument[0]);
  5947. }
  5948. Statement->ArgumentsAcquired += 1;
  5949. AcpipObjectReleaseReference(NameString);
  5950. //
  5951. // Get the argument from the previous statement.
  5952. //
  5953. } else {
  5954. if (Context->ExecuteStatements != FALSE) {
  5955. NewArgument = Context->PreviousStatement->Reduction;
  5956. if (NewArgument == NULL) {
  5957. return STATUS_ARGUMENT_EXPECTED;
  5958. }
  5959. //
  5960. // The first argument is the Event object.
  5961. //
  5962. if (Statement->ArgumentsAcquired == 0) {
  5963. if (NewArgument->Type != AcpiObjectEvent) {
  5964. return STATUS_INVALID_PARAMETER;
  5965. }
  5966. Statement->Argument[Statement->ArgumentsAcquired] =
  5967. NewArgument;
  5968. AcpipObjectAddReference(NewArgument);
  5969. //
  5970. // The second argument should evaluate to an integer specifying
  5971. // the number of milliseconds to wait for the given event.
  5972. //
  5973. } else {
  5974. if (NewArgument->Type == AcpiObjectInteger) {
  5975. Statement->Argument[Statement->ArgumentsAcquired] =
  5976. NewArgument;
  5977. AcpipObjectAddReference(NewArgument);
  5978. } else {
  5979. IntegerObject = AcpipConvertObjectType(
  5980. Context,
  5981. NewArgument,
  5982. AcpiObjectInteger);
  5983. if (IntegerObject == NULL) {
  5984. return STATUS_UNSUCCESSFUL;
  5985. }
  5986. Statement->Argument[Statement->ArgumentsAcquired] =
  5987. IntegerObject;
  5988. }
  5989. }
  5990. }
  5991. Statement->ArgumentsAcquired += 1;
  5992. }
  5993. }
  5994. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  5995. Statement->Reduction = NULL;
  5996. if (Context->ExecuteStatements != FALSE) {
  5997. ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
  5998. ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
  5999. TimeoutValue = Statement->Argument[1]->U.Integer.Value;
  6000. ResultValue = AcpipWaitForEvent(Statement->Argument[0]->U.Event.OsEvent,
  6001. TimeoutValue);
  6002. Statement->Reduction = AcpipCreateNamespaceObject(Context,
  6003. AcpiObjectInteger,
  6004. NULL,
  6005. &ResultValue,
  6006. sizeof(ULONGLONG));
  6007. if (Statement->Reduction == NULL) {
  6008. return STATUS_UNSUCCESSFUL;
  6009. }
  6010. }
  6011. return STATUS_SUCCESS;
  6012. }
  6013. KSTATUS
  6014. AcpipEvaluateWhileModifierStatement (
  6015. PAML_EXECUTION_CONTEXT Context,
  6016. PAML_STATEMENT Statement
  6017. )
  6018. /*++
  6019. Routine Description:
  6020. This routine evaluates one of the statements that modifies a While loop,
  6021. a Break or Continue.
  6022. Arguments:
  6023. Context - Supplies a pointer to the current AML execution context.
  6024. Statement - Supplies a pointer to the statement to evaluate.
  6025. Return Value:
  6026. Status code.
  6027. --*/
  6028. {
  6029. BOOL Continue;
  6030. if (Context->PrintStatements != FALSE) {
  6031. if (Statement->Type == AmlStatementBreak) {
  6032. RtlDebugPrint("Break");
  6033. } else {
  6034. ASSERT(Statement->Type == AmlStatementContinue);
  6035. RtlDebugPrint("Continue");
  6036. }
  6037. }
  6038. if (Context->ExecuteStatements != FALSE) {
  6039. if (Statement->Type == AmlStatementContinue) {
  6040. Continue = TRUE;
  6041. } else {
  6042. Continue = FALSE;
  6043. }
  6044. AcpipPopExecutingStatements(Context, TRUE, Continue);
  6045. }
  6046. return STATUS_SUCCESS;
  6047. }
  6048. KSTATUS
  6049. AcpipEvaluateWhileStatement (
  6050. PAML_EXECUTION_CONTEXT Context,
  6051. PAML_STATEMENT Statement
  6052. )
  6053. /*++
  6054. Routine Description:
  6055. This routine evaluates a While statement.
  6056. Arguments:
  6057. Context - Supplies a pointer to the current AML execution context.
  6058. Statement - Supplies a pointer to the statement to evaluate.
  6059. Return Value:
  6060. Status code.
  6061. --*/
  6062. {
  6063. PACPI_OBJECT NewArgument;
  6064. if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
  6065. //
  6066. // Print out the piece of the statement depending on the number of
  6067. // arguments acquired.
  6068. //
  6069. if (Context->PrintStatements != FALSE) {
  6070. if (Context->PreviousStatement == NULL) {
  6071. RtlDebugPrint("While (");
  6072. } else {
  6073. ASSERT(Statement->ArgumentsAcquired == 0);
  6074. RtlDebugPrint(") {");
  6075. }
  6076. }
  6077. if (Context->PreviousStatement == NULL) {
  6078. Context->IndentationLevel += 1;
  6079. return STATUS_MORE_PROCESSING_REQUIRED;
  6080. }
  6081. //
  6082. // If not executing, then assume the argument would be there but don't
  6083. // try to dink with it.
  6084. //
  6085. if (Context->ExecuteStatements == FALSE) {
  6086. Statement->Argument[Statement->ArgumentsAcquired] = NULL;
  6087. Statement->ArgumentsAcquired += 1;
  6088. } else {
  6089. NewArgument = Context->PreviousStatement->Reduction;
  6090. //
  6091. // Fail if there is no argument there.
  6092. //
  6093. if (Context->PreviousStatement->Reduction == NULL) {
  6094. return STATUS_ARGUMENT_EXPECTED;
  6095. }
  6096. //
  6097. // Perform an implicit conversion if needed.
  6098. //
  6099. if (NewArgument->Type != AcpiObjectInteger) {
  6100. NewArgument = AcpipConvertObjectType(Context,
  6101. NewArgument,
  6102. AcpiObjectInteger);
  6103. if (NewArgument == NULL) {
  6104. return STATUS_CONVERSION_FAILED;
  6105. }
  6106. //
  6107. // The object is fine, take ownership of it.
  6108. //
  6109. } else {
  6110. AcpipObjectAddReference(NewArgument);
  6111. }
  6112. Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
  6113. Statement->ArgumentsAcquired += 1;
  6114. }
  6115. //
  6116. // Evaluate the predicate.
  6117. //
  6118. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  6119. if (Context->ExecuteStatements != FALSE) {
  6120. ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
  6121. //
  6122. // Evaluate the while statement by skipping the package length if
  6123. // it's zero, and completing the while statement.
  6124. //
  6125. if (Statement->Argument[0]->U.Integer.Value == 0) {
  6126. Context->CurrentOffset = Statement->AdditionalData;
  6127. Context->IndentationLevel -= 1;
  6128. if (Context->PrintStatements != FALSE) {
  6129. AcpipPrintIndentedNewLine(Context);
  6130. RtlDebugPrint("}");
  6131. }
  6132. return STATUS_SUCCESS;
  6133. }
  6134. }
  6135. }
  6136. //
  6137. // If execution is not done with the scope, keep this statement on the
  6138. // stack.
  6139. //
  6140. if (Context->CurrentOffset < Statement->AdditionalData) {
  6141. AcpipPrintIndentedNewLine(Context);
  6142. return STATUS_MORE_PROCESSING_REQUIRED;
  6143. }
  6144. ASSERT(Context->IndentationLevel != 0);
  6145. //
  6146. // Move the offset back to the predicate, release the argument to pretend
  6147. // like the predicate was never seen before, and start again.
  6148. //
  6149. if (Context->ExecuteStatements != FALSE) {
  6150. Context->CurrentOffset = Statement->AdditionalData2;
  6151. AcpipObjectReleaseReference(Statement->Argument[0]);
  6152. Statement->Argument[0] = NULL;
  6153. Statement->ArgumentsAcquired = 0;
  6154. AcpipPrintIndentedNewLine(Context);
  6155. return STATUS_MORE_PROCESSING_REQUIRED;
  6156. }
  6157. AcpipPrintIndentedNewLine(Context);
  6158. return STATUS_SUCCESS;
  6159. }
  6160. PACPI_OBJECT
  6161. AcpipConvertObjectType (
  6162. PAML_EXECUTION_CONTEXT Context,
  6163. PACPI_OBJECT Object,
  6164. ACPI_OBJECT_TYPE NewType
  6165. )
  6166. /*++
  6167. Routine Description:
  6168. This routine performs a conversion between supported ACPI object types.
  6169. Arguments:
  6170. Context - Supplies a pointer to the current execution context.
  6171. Object - Supplies a pointer to the object to convert.
  6172. NewType - Supplies the type to convert the given object to.
  6173. Return Value:
  6174. Returns a pointer to a new object (unlinked to the namespace) of the
  6175. requested type. The caller is responsible for this memory once its returned.
  6176. NULL on failure.
  6177. --*/
  6178. {
  6179. PACPI_OBJECT NewObject;
  6180. PACPI_OBJECT ReadResult;
  6181. KSTATUS Status;
  6182. NewObject = NULL;
  6183. ReadResult = NULL;
  6184. //
  6185. // Get the real object being pointed to here.
  6186. //
  6187. while (Object->Type == AcpiObjectAlias) {
  6188. Object = Object->U.Alias.DestinationObject;
  6189. }
  6190. //
  6191. // Attempting to convert from a Field Unit to something results in a read
  6192. // from the field.
  6193. //
  6194. if (Object->Type == AcpiObjectFieldUnit) {
  6195. Status = AcpipReadFromField(Context, Object, &ReadResult);
  6196. if (!KSUCCESS(Status)) {
  6197. return NULL;
  6198. }
  6199. if (ReadResult->Type == NewType) {
  6200. return ReadResult;
  6201. }
  6202. //
  6203. // The new thing to convert is the result of the field read.
  6204. //
  6205. Object = ReadResult;
  6206. } else if (Object->Type == AcpiObjectBufferField) {
  6207. Status = AcpipReadFromBufferField(Context, Object, &ReadResult);
  6208. if (!KSUCCESS(Status)) {
  6209. return NULL;
  6210. }
  6211. if (ReadResult->Type == NewType) {
  6212. return ReadResult;
  6213. }
  6214. //
  6215. // The new thing to convert is the result of the buffer field read.
  6216. //
  6217. Object = ReadResult;
  6218. }
  6219. switch (NewType) {
  6220. case AcpiObjectInteger:
  6221. NewObject = AcpipConvertObjectTypeToInteger(Context, Object);
  6222. break;
  6223. case AcpiObjectString:
  6224. NewObject = AcpipConvertObjectTypeToString(Context, Object);
  6225. break;
  6226. case AcpiObjectBuffer:
  6227. NewObject = AcpipConvertObjectTypeToBuffer(Context, Object);
  6228. break;
  6229. default:
  6230. ASSERT(FALSE);
  6231. break;
  6232. }
  6233. //
  6234. // Release the intermediate read result object.
  6235. //
  6236. if (ReadResult != NULL) {
  6237. AcpipObjectReleaseReference(ReadResult);
  6238. }
  6239. return NewObject;
  6240. }
  6241. KSTATUS
  6242. AcpipResolveStoreDestination (
  6243. PAML_EXECUTION_CONTEXT Context,
  6244. PACPI_OBJECT Destination,
  6245. PACPI_OBJECT *ResolvedDestination
  6246. )
  6247. /*++
  6248. Routine Description:
  6249. This routine resolves a store destination to the proper ACPI object based
  6250. on its type and the statement type.
  6251. Arguments:
  6252. Context - Supplies a pointer to the current AML execution context.
  6253. Destination - Supplies a pointer to the original store destination object.
  6254. ResolvedDestination - Supplies a pointer that receives a pointer to the
  6255. resolved destination object. This may return a pointer to the
  6256. original destination, but with an extra reference. The caller is always
  6257. responsible for releasing a reference on this object.
  6258. Return Value:
  6259. Status code.
  6260. --*/
  6261. {
  6262. ULONG LastLocalIndex;
  6263. PACPI_OBJECT *LocalVariable;
  6264. PACPI_OBJECT ResolvedObject;
  6265. //
  6266. // Follow all aliases.
  6267. //
  6268. while (Destination->Type == AcpiObjectAlias) {
  6269. Destination = Destination->U.Alias.DestinationObject;
  6270. }
  6271. //
  6272. // If it is a local, then store is meant to release the reference on the
  6273. // existing local variable and set the local to a new copy of the source.
  6274. //
  6275. ResolvedObject = Destination;
  6276. LastLocalIndex = Context->CurrentMethod->LastLocalIndex;
  6277. LocalVariable = Context->CurrentMethod->LocalVariable;
  6278. if ((LastLocalIndex != AML_INVALID_LOCAL_INDEX) &&
  6279. (LocalVariable[LastLocalIndex] == Destination)) {
  6280. AcpipObjectReleaseReference(Destination);
  6281. LocalVariable[LastLocalIndex] = NULL;
  6282. ResolvedObject = AcpipCreateNamespaceObject(Context,
  6283. AcpiObjectUninitialized,
  6284. NULL,
  6285. NULL,
  6286. 0);
  6287. if (ResolvedObject == NULL) {
  6288. return STATUS_INSUFFICIENT_RESOURCES;
  6289. }
  6290. LocalVariable[LastLocalIndex] = ResolvedObject;
  6291. }
  6292. AcpipObjectAddReference(ResolvedObject);
  6293. *ResolvedDestination = ResolvedObject;
  6294. return STATUS_SUCCESS;
  6295. }
  6296. KSTATUS
  6297. AcpipConvertToDataReferenceObject (
  6298. PAML_EXECUTION_CONTEXT Context,
  6299. PACPI_OBJECT Object,
  6300. PACPI_OBJECT *ResultObject
  6301. )
  6302. /*++
  6303. Routine Description:
  6304. This routine performs a conversion of an object to a type in the set of
  6305. DataRefObject types.
  6306. Arguments:
  6307. Context - Supplies a pointer to the current execution context.
  6308. Object - Supplies a pointer to the object to convert.
  6309. ResultObject - Supplies a pointer that receives a pointer to the result
  6310. object after the conversion. If no conversion is necessary, then this
  6311. may be a pointer to the original object. If a conversion is necessary,
  6312. then this will be a pointer to a new object. Either way the caller is
  6313. responsible for releasing one reference on the result object on
  6314. success.
  6315. Return Value:
  6316. Status code.
  6317. --*/
  6318. {
  6319. PACPI_OBJECT DataReferenceObject;
  6320. KSTATUS Status;
  6321. //
  6322. // Get the real object being pointed to here.
  6323. //
  6324. while (Object->Type == AcpiObjectAlias) {
  6325. Object = Object->U.Alias.DestinationObject;
  6326. }
  6327. DataReferenceObject = NULL;
  6328. Status = STATUS_SUCCESS;
  6329. switch (Object->Type) {
  6330. //
  6331. // Convert a field unit to an integer or buffer.
  6332. //
  6333. case AcpiObjectFieldUnit:
  6334. Status = AcpipReadFromField(Context, Object, &DataReferenceObject);
  6335. if (!KSUCCESS(Status)) {
  6336. goto ConvertToDataReferenceObjectEnd;
  6337. }
  6338. ASSERT((DataReferenceObject->Type == AcpiObjectInteger) ||
  6339. (DataReferenceObject->Type == AcpiObjectBuffer));
  6340. break;
  6341. //
  6342. // Convert a buffer field into an integer or buffer.
  6343. //
  6344. case AcpiObjectBufferField:
  6345. Status = AcpipReadFromBufferField(Context,
  6346. Object,
  6347. &DataReferenceObject);
  6348. if (!KSUCCESS(Status)) {
  6349. goto ConvertToDataReferenceObjectEnd;
  6350. }
  6351. ASSERT((DataReferenceObject->Type == AcpiObjectInteger) ||
  6352. (DataReferenceObject->Type == AcpiObjectBuffer));
  6353. break;
  6354. //
  6355. // Just add a new reference if it is already a DataReferenceObject type.
  6356. //
  6357. case AcpiObjectInteger:
  6358. case AcpiObjectString:
  6359. case AcpiObjectBuffer:
  6360. case AcpiObjectPackage:
  6361. case AcpiObjectDdbHandle:
  6362. DataReferenceObject = Object;
  6363. AcpipObjectAddReference(DataReferenceObject);
  6364. break;
  6365. //
  6366. // Anything else cannot be converted and results in failure.
  6367. //
  6368. default:
  6369. RtlDebugPrint("\nACPI: Unable to convert object of type %d to a "
  6370. "DataRefObject. Context: 0x%08x, Object 0x%08x.\n",
  6371. Object->Type,
  6372. Context,
  6373. Object);
  6374. ASSERT(FALSE);
  6375. Status = STATUS_NOT_SUPPORTED;
  6376. break;
  6377. }
  6378. ConvertToDataReferenceObjectEnd:
  6379. if (!KSUCCESS(Status)) {
  6380. if (DataReferenceObject != NULL) {
  6381. AcpipObjectReleaseReference(DataReferenceObject);
  6382. DataReferenceObject = NULL;
  6383. }
  6384. }
  6385. *ResultObject = DataReferenceObject;
  6386. return Status;
  6387. }
  6388. //
  6389. // --------------------------------------------------------- Internal Functions
  6390. //
  6391. PACPI_OBJECT
  6392. AcpipConvertObjectTypeToInteger (
  6393. PAML_EXECUTION_CONTEXT Context,
  6394. PACPI_OBJECT Object
  6395. )
  6396. /*++
  6397. Routine Description:
  6398. This routine converts the given object into an Integer object.
  6399. Arguments:
  6400. Context - Supplies a pointer to the AML execution context.
  6401. Object - Supplies a pointer to the object to convert.
  6402. Return Value:
  6403. Returns a pointer to a new object (unlinked to the namespace) of the
  6404. requested type. The caller is responsible for this memory once its returned.
  6405. NULL on failure.
  6406. --*/
  6407. {
  6408. ULONG CopySize;
  6409. UCHAR Digit;
  6410. ULONGLONG IntegerValue;
  6411. PACPI_OBJECT NewObject;
  6412. PSTR String;
  6413. NewObject = NULL;
  6414. IntegerValue = 0;
  6415. switch (Object->Type) {
  6416. case AcpiObjectInteger:
  6417. NewObject = AcpipCreateNamespaceObject(NULL,
  6418. AcpiObjectInteger,
  6419. NULL,
  6420. &(Object->U.Integer.Value),
  6421. sizeof(ULONGLONG));
  6422. break;
  6423. //
  6424. // Convert from a buffer to an integer by basically just casting.
  6425. //
  6426. case AcpiObjectBuffer:
  6427. CopySize = Object->U.Buffer.Length;
  6428. if (CopySize > sizeof(ULONGLONG)) {
  6429. CopySize = sizeof(ULONGLONG);
  6430. }
  6431. RtlCopyMemory(&IntegerValue, Object->U.Buffer.Buffer, CopySize);
  6432. NewObject = AcpipCreateNamespaceObject(NULL,
  6433. AcpiObjectInteger,
  6434. NULL,
  6435. &IntegerValue,
  6436. sizeof(ULONGLONG));
  6437. break;
  6438. //
  6439. // To convert from a string to an integer, parse hex digits 0-9, A-F
  6440. // (and a-f) until a non-digit is found. A leading 0x is not allowed.
  6441. //
  6442. case AcpiObjectString:
  6443. String = Object->U.String.String;
  6444. if (String == NULL) {
  6445. break;
  6446. }
  6447. while (((*String >= '0') && (*String <= '9')) ||
  6448. ((*String >= 'a') && (*String <= 'f')) ||
  6449. ((*String >= 'A') && (*String <= 'F'))) {
  6450. if ((*String >= '0') && (*String <= '9')) {
  6451. Digit = *String - '0';
  6452. } else if (((*String >= 'a') && (*String <= 'f'))) {
  6453. Digit = *String - 'a' + 10;
  6454. } else {
  6455. ASSERT((*String >= 'A') && (*String <= 'F'));
  6456. Digit = *String - 'A' + 10;
  6457. }
  6458. IntegerValue = (IntegerValue << 4) | Digit;
  6459. String += 1;
  6460. }
  6461. NewObject = AcpipCreateNamespaceObject(NULL,
  6462. AcpiObjectInteger,
  6463. NULL,
  6464. &IntegerValue,
  6465. sizeof(ULONGLONG));
  6466. break;
  6467. default:
  6468. ASSERT(FALSE);
  6469. break;
  6470. }
  6471. return NewObject;
  6472. }
  6473. PACPI_OBJECT
  6474. AcpipConvertObjectTypeToString (
  6475. PAML_EXECUTION_CONTEXT Context,
  6476. PACPI_OBJECT Object
  6477. )
  6478. /*++
  6479. Routine Description:
  6480. This routine converts the given object into a String object.
  6481. Arguments:
  6482. Context - Supplies a pointer to the current AML execution context.
  6483. Object - Supplies a pointer to the object to convert.
  6484. Return Value:
  6485. Returns a pointer to a new object (unlinked to the namespace) of the
  6486. requested type. The caller is responsible for this memory once its returned.
  6487. NULL on failure.
  6488. --*/
  6489. {
  6490. ULONG BufferLength;
  6491. ULONG ByteIndex;
  6492. PUCHAR CurrentBufferPosition;
  6493. PSTR CurrentPosition;
  6494. PACPI_OBJECT NewObject;
  6495. ULONG NewStringLength;
  6496. switch (Object->Type) {
  6497. //
  6498. // To convert an integer to a string, create an 8 or 16 byte string buffer
  6499. // depending on whether integers are 32 or 64 bits, and then write the hex
  6500. // value in.
  6501. //
  6502. case AcpiObjectInteger:
  6503. NewStringLength = 16;
  6504. if ((Context->CurrentMethod != NULL) &&
  6505. (Context->CurrentMethod->IntegerWidthIs32 != FALSE)) {
  6506. NewStringLength = 8;
  6507. }
  6508. NewObject = AcpipCreateNamespaceObject(NULL,
  6509. AcpiObjectString,
  6510. NULL,
  6511. NULL,
  6512. NewStringLength);
  6513. if (NewObject == NULL) {
  6514. return NULL;
  6515. }
  6516. RtlPrintToString(NewObject->U.String.String,
  6517. NewStringLength,
  6518. CharacterEncodingAscii,
  6519. "%I64x",
  6520. Object->U.Integer.Value);
  6521. break;
  6522. case AcpiObjectString:
  6523. NewStringLength = RtlStringLength(Object->U.String.String) + 1;
  6524. NewObject = AcpipCreateNamespaceObject(NULL,
  6525. AcpiObjectString,
  6526. NULL,
  6527. Object->U.String.String,
  6528. NewStringLength);
  6529. break;
  6530. //
  6531. // To convert from a buffer to a string, print out all characters as two
  6532. // digit hex values, separated by spaces.
  6533. //
  6534. case AcpiObjectBuffer:
  6535. //
  6536. // The new string length is 3 times the number of bytes there are (two
  6537. // digits plus one space for each character), minus one since the last
  6538. // character doesn't get a space, plus one for the null terminator.
  6539. //
  6540. NewStringLength = (Object->U.Buffer.Length * 3);
  6541. NewObject = AcpipCreateNamespaceObject(NULL,
  6542. AcpiObjectString,
  6543. NULL,
  6544. NULL,
  6545. NewStringLength);
  6546. if (NewObject == NULL) {
  6547. return NULL;
  6548. }
  6549. BufferLength = Object->U.Buffer.Length;
  6550. if (BufferLength == 0) {
  6551. NewObject->U.String.String[0] = '\0';
  6552. } else {
  6553. CurrentPosition = NewObject->U.String.String;
  6554. CurrentBufferPosition = Object->U.Buffer.Buffer;
  6555. //
  6556. // Print out all except the last one.
  6557. //
  6558. for (ByteIndex = 0; ByteIndex < BufferLength - 1; ByteIndex += 1) {
  6559. RtlPrintToString(CurrentPosition,
  6560. NewStringLength,
  6561. CharacterEncodingAscii,
  6562. "%02x ",
  6563. *CurrentBufferPosition);
  6564. CurrentPosition += 3;
  6565. NewStringLength -= 3;
  6566. CurrentBufferPosition += 1;
  6567. }
  6568. //
  6569. // Do the last one without a space.
  6570. //
  6571. RtlPrintToString(CurrentPosition,
  6572. NewStringLength,
  6573. CharacterEncodingAscii,
  6574. "%02x",
  6575. *CurrentBufferPosition);
  6576. }
  6577. break;
  6578. default:
  6579. ASSERT(FALSE);
  6580. return NULL;
  6581. }
  6582. return NewObject;
  6583. }
  6584. PACPI_OBJECT
  6585. AcpipConvertObjectTypeToBuffer (
  6586. PAML_EXECUTION_CONTEXT Context,
  6587. PACPI_OBJECT Object
  6588. )
  6589. /*++
  6590. Routine Description:
  6591. This routine converts the given object into a Buffer object.
  6592. Arguments:
  6593. Context - Supplies a pointer to the current AML execution context.
  6594. Object - Supplies a pointer to the object to convert.
  6595. Return Value:
  6596. Returns a pointer to a new object (unlinked to the namespace) of the
  6597. requested type. The caller is responsible for this memory once its returned.
  6598. NULL on failure.
  6599. --*/
  6600. {
  6601. ULONG BufferSize;
  6602. PACPI_OBJECT NewObject;
  6603. switch (Object->Type) {
  6604. //
  6605. // Converting from an integer to a buffer is basically a matter of casting.
  6606. //
  6607. case AcpiObjectInteger:
  6608. BufferSize = sizeof(ULONGLONG);
  6609. if ((Context->CurrentMethod != NULL) &&
  6610. (Context->CurrentMethod->IntegerWidthIs32 != FALSE)) {
  6611. BufferSize = sizeof(ULONG);
  6612. }
  6613. NewObject = AcpipCreateNamespaceObject(Context,
  6614. AcpiObjectBuffer,
  6615. NULL,
  6616. &(Object->U.Integer.Value),
  6617. BufferSize);
  6618. break;
  6619. case AcpiObjectString:
  6620. BufferSize = RtlStringLength(Object->U.String.String);
  6621. if (BufferSize != 0) {
  6622. BufferSize += 1;
  6623. }
  6624. NewObject = AcpipCreateNamespaceObject(Context,
  6625. AcpiObjectBuffer,
  6626. NULL,
  6627. Object->U.String.String,
  6628. BufferSize);
  6629. break;
  6630. case AcpiObjectBuffer:
  6631. BufferSize = Object->U.Buffer.Length;
  6632. NewObject = AcpipCreateNamespaceObject(Context,
  6633. AcpiObjectBuffer,
  6634. NULL,
  6635. Object->U.Buffer.Buffer,
  6636. BufferSize);
  6637. break;
  6638. default:
  6639. ASSERT(FALSE);
  6640. return NULL;
  6641. }
  6642. return NewObject;
  6643. }
  6644. BOOL
  6645. AcpipEvaluateMatchComparison (
  6646. PAML_EXECUTION_CONTEXT Context,
  6647. PACPI_OBJECT PackageElement,
  6648. PACPI_OBJECT Operand1,
  6649. ACPI_MATCH_OPERATOR Operator1,
  6650. PACPI_OBJECT Operand2,
  6651. ACPI_MATCH_OPERATOR Operator2
  6652. )
  6653. /*++
  6654. Routine Description:
  6655. This routine performs a comparison of two or more objects as defined in the
  6656. rules for a Match statement.
  6657. Arguments:
  6658. Context - Supplies a pointer to the execution context.
  6659. PackageElement - Supplies a pointer to the element indexed from the
  6660. Match package being iterated over.
  6661. Operand1 - Supplies a pointer to the first value to compare against. This
  6662. must be an integer.
  6663. Operator1 - Supplies the operator to use to compare the package element to
  6664. Operand1.
  6665. Operand2 - Supplies a pointer to the second value to compare against. This
  6666. must be an integer.
  6667. Operator2 - Supplies the operator to use to compare the package element to
  6668. Operand2.
  6669. Return Value:
  6670. TRUE if the condition matches the given operators against the given
  6671. operands.
  6672. FALSE if the comparison does not match.
  6673. --*/
  6674. {
  6675. ULONGLONG Operand;
  6676. ULONGLONG PackageValue;
  6677. BOOL Result;
  6678. ASSERT((Operator1 < MatchOperatorCount) &&
  6679. (Operator2 < MatchOperatorCount));
  6680. ASSERT((Operator1 == MatchOperatorTrue) ||
  6681. (Operand1->Type == AcpiObjectInteger));
  6682. ASSERT((Operator2 == MatchOperatorTrue) ||
  6683. (Operand2->Type == AcpiObjectInteger));
  6684. //
  6685. // The ACPI spec says to skip uninitialized elements.
  6686. //
  6687. if ((PackageElement == NULL) ||
  6688. (PackageElement->Type == AcpiObjectUninitialized)) {
  6689. return FALSE;
  6690. }
  6691. //
  6692. // Get an object that can be evaluated as an integer. If the conversion
  6693. // fails, the ACPI spec says to quietly skip this value.
  6694. //
  6695. if (PackageElement->Type == AcpiObjectInteger) {
  6696. PackageValue = PackageElement->U.Integer.Value;
  6697. } else {
  6698. PackageElement = AcpipConvertObjectType(Context,
  6699. PackageElement,
  6700. AcpiObjectInteger);
  6701. if (PackageElement == NULL) {
  6702. return FALSE;
  6703. }
  6704. PackageValue = PackageElement->U.Integer.Value;
  6705. AcpipObjectReleaseReference(PackageElement);
  6706. }
  6707. //
  6708. // Perform the comparison on object 1.
  6709. //
  6710. Result = FALSE;
  6711. Operand = 0;
  6712. if (Operator1 != MatchOperatorTrue) {
  6713. Operand = Operand1->U.Integer.Value;
  6714. }
  6715. switch (Operator1) {
  6716. case MatchOperatorTrue:
  6717. Result = TRUE;
  6718. break;
  6719. case MatchOperatorEqual:
  6720. if (PackageValue == Operand) {
  6721. Result = TRUE;
  6722. }
  6723. break;
  6724. case MatchOperatorLessThanOrEqualTo:
  6725. if (PackageValue <= Operand) {
  6726. Result = TRUE;
  6727. }
  6728. break;
  6729. case MatchOperatorLessThan:
  6730. if (PackageValue < Operand) {
  6731. Result = TRUE;
  6732. }
  6733. break;
  6734. case MatchOperatorGreaterThanOrEqualTo:
  6735. if (PackageValue >= Operand) {
  6736. Result = TRUE;
  6737. }
  6738. break;
  6739. case MatchOperatorGreaterThan:
  6740. if (PackageValue > Operand) {
  6741. Result = TRUE;
  6742. }
  6743. break;
  6744. default:
  6745. ASSERT(FALSE);
  6746. break;
  6747. }
  6748. //
  6749. // The function is only a match if both return TRUE. If this returned FALSE,
  6750. // don't bother evaluating the other side.
  6751. //
  6752. if (Result == FALSE) {
  6753. return Result;
  6754. }
  6755. //
  6756. // Evalute operand 2.
  6757. //
  6758. Result = FALSE;
  6759. if (Operator2 != MatchOperatorTrue) {
  6760. Operand = Operand2->U.Integer.Value;
  6761. }
  6762. switch (Operator2) {
  6763. case MatchOperatorTrue:
  6764. Result = TRUE;
  6765. break;
  6766. case MatchOperatorEqual:
  6767. if (PackageValue == Operand) {
  6768. Result = TRUE;
  6769. }
  6770. break;
  6771. case MatchOperatorLessThanOrEqualTo:
  6772. if (PackageValue <= Operand) {
  6773. Result = TRUE;
  6774. }
  6775. break;
  6776. case MatchOperatorLessThan:
  6777. if (PackageValue < Operand) {
  6778. Result = TRUE;
  6779. }
  6780. break;
  6781. case MatchOperatorGreaterThanOrEqualTo:
  6782. if (PackageValue >= Operand) {
  6783. Result = TRUE;
  6784. }
  6785. break;
  6786. case MatchOperatorGreaterThan:
  6787. if (PackageValue > Operand) {
  6788. Result = TRUE;
  6789. }
  6790. break;
  6791. default:
  6792. ASSERT(FALSE);
  6793. break;
  6794. }
  6795. return Result;
  6796. }