amlopex.c 237 KB

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