1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- amlopex.c
- Abstract:
- This module implements ACPI AML low level opcode support for executing
- AML statements.
- Author:
- Evan Green 13-Nov-2012
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include "acpip.h"
- #include "amlos.h"
- #include "amlops.h"
- #include "namespce.h"
- #include "oprgn.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define ACPI_RESOURCE_END_TAG 0x79
- //
- // Define the longest string that can be created from converting a decimal
- // integer to a string.
- //
- #define MAX_DECIMAL_STRING_LENGTH 22
- //
- // Define the portion of the mutex sync flags that represent the sync level.
- //
- #define MUTEX_FLAG_SYNC_LEVEL_MASK 0xF
- //
- // Define the bitfields of the method flags byte.
- //
- #define METHOD_ARGUMENT_COUNT_MASK 0x7
- #define METHOD_SERIALIZED_FLAG 0x08
- #define METHOD_SYNC_LEVEL_SHIFT 4
- #define METHOD_SYNC_LEVEL_MASK (0xF << METHOD_SYNC_LEVEL_SHIFT)
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef enum _ACPI_MATCH_OPERATOR {
- MatchOperatorTrue = 0,
- MatchOperatorEqual = 1,
- MatchOperatorLessThanOrEqualTo = 2,
- MatchOperatorLessThan = 3,
- MatchOperatorGreaterThanOrEqualTo = 4,
- MatchOperatorGreaterThan = 5,
- MatchOperatorCount
- } ACPI_MATCH_OPERATOR, *PACPI_MATCH_OPERATOR;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- PACPI_OBJECT
- AcpipConvertObjectTypeToInteger (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- );
- PACPI_OBJECT
- AcpipConvertObjectTypeToString (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- );
- PACPI_OBJECT
- AcpipConvertObjectTypeToBuffer (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- );
- BOOL
- AcpipEvaluateMatchComparison (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT PackageElement,
- PACPI_OBJECT Operand1,
- ACPI_MATCH_OPERATOR Operator1,
- PACPI_OBJECT Operand2,
- ACPI_MATCH_OPERATOR Operator2
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- PSTR AcpiMatchOpcodeString[MatchOperatorCount] = {
- "MTR", // Always TRUE.
- "MEQ", // Equal to.
- "MLE", // Less than or Equal to.
- "MLT", // Less than.
- "MGE", // Greater than or equal to.
- "MGT" // Greater than.
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- AcpipEvaluateAcquireStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Acquire (mutex) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR InstructionPointer;
- PACPI_OBJECT NewArgument;
- ULONGLONG ResultValue;
- USHORT TimeoutValue;
- //
- // Gather arguments if needed.
- //
- TimeoutValue = 0;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Acquire (");
- }
- }
- //
- // An argument is required.
- //
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[0] = NULL;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- Statement->Argument[0] = NewArgument;
- AcpipObjectAddReference(NewArgument);
- }
- Statement->ArgumentsAcquired += 1;
- //
- // The first argument should be acquired now, and the second argument
- // is a constant word representing the timeout value.
- //
- InstructionPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
- if (Context->CurrentOffset + sizeof(USHORT) >= Context->AmlCodeSize) {
- return STATUS_MALFORMED_DATA_STREAM;
- }
- TimeoutValue = *((PUSHORT)InstructionPointer);
- Context->CurrentOffset += sizeof(USHORT);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(", %d)", TimeoutValue);
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectMutex);
- ResultValue = AcpipAcquireMutex(Context,
- Statement->Argument[0]->U.Mutex.OsMutex,
- TimeoutValue);
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateAliasStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates the alias statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Destination;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Alias (%s, %s)\n",
- Statement->Argument[0]->U.String.String,
- Statement->Argument[1]->U.String.String);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Get the destination object that the alias points to.
- //
- Destination = AcpipGetNamespaceObject(
- Statement->Argument[0]->U.String.String,
- Context->CurrentScope);
- if (Destination == NULL) {
- return STATUS_NOT_FOUND;
- }
- //
- // Create the alias.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectAlias,
- Statement->Argument[1]->U.String.String,
- &Destination,
- sizeof(PVOID));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateArgumentStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates the ArgX opcodes.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- ULONG ArgumentNumber;
- PACPI_OBJECT ArgumentObject;
- ArgumentNumber = (ULONG)Statement->AdditionalData;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Arg%d", ArgumentNumber);
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- ArgumentObject = Context->CurrentMethod->Argument[ArgumentNumber];
- if (ArgumentObject != NULL) {
- Statement->Reduction = ArgumentObject;
- AcpipObjectAddReference(ArgumentObject);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateBankFieldStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a BankField (in an Operation Region) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- UCHAR AccessFlags;
- PUCHAR InstructionPointer;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT OperationRegion;
- KSTATUS Status;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("BankField (%s, ",
- Statement->Argument[0]->U.String.String);
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- ASSERT(Statement->ArgumentsAcquired == 2);
- //
- // Perform a conversion if needed.
- //
- NewArgument = Context->PreviousStatement->Reduction;
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
- //
- // Parse the starting flags and store them in additional data 2.
- //
- InstructionPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
- AccessFlags = *InstructionPointer;
- Context->CurrentOffset += 1;
- //
- // Get the operation region this Field refers to.
- //
- OperationRegion =
- AcpipGetNamespaceObject(Statement->Argument[0]->U.String.String,
- Context->CurrentScope);
- if (OperationRegion == NULL) {
- return STATUS_NOT_FOUND;
- }
- //
- // Parse the field list.
- //
- Status = AcpipParseFieldList(Context,
- Statement->Type,
- OperationRegion,
- Statement->Argument[1],
- Statement->Argument[2],
- NULL,
- NULL,
- Statement->AdditionalData,
- AccessFlags);
- return Status;
- }
- KSTATUS
- AcpipEvaluateBreakPointStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates the BreakPoint statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("BreakPoint");
- }
- if (Context->ExecuteStatements != FALSE) {
- RtlDebugBreak();
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateBufferStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a buffer declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Argument;
- PACPI_OBJECT BufferObject;
- ULONG BufferSize;
- ULONG ByteIndex;
- ULONG ByteListLength;
- PUCHAR ByteListPointer;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PreviousStatement == NULL) {
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Buffer (");
- }
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Convert the buffer size object to an integer if needed.
- //
- Argument = Context->PreviousStatement->Reduction;
- if (Argument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- if (Argument->Type != AcpiObjectInteger) {
- Argument = AcpipConvertObjectType(Context,
- Argument,
- AcpiObjectInteger);
- } else {
- AcpipObjectAddReference(Argument);
- }
- Statement->Argument[0] = Argument;
- //
- // Just pretend the argument would have been there.
- //
- } else {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- }
- Statement->ArgumentsAcquired += 1;
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- //
- // Collect the byte list following the buffer size argument just acquired.
- //
- ByteListLength = Statement->AdditionalData - Context->CurrentOffset;
- ByteListPointer = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(") {");
- for (ByteIndex = 0; ByteIndex < ByteListLength; ByteIndex += 1) {
- RtlDebugPrint("%02x ", ByteListPointer[ByteIndex]);
- }
- RtlDebugPrint("}");
- }
- if (Context->ExecuteStatements != FALSE) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- //
- // The buffer size comes from evaluating the argument. If the
- // initializer is bigger than the buffer size, then expand it to fit
- // the initializer.
- //
- BufferSize = Statement->Argument[0]->U.Integer.Value;
- if (BufferSize < ByteListLength) {
- BufferSize = ByteListLength;
- }
- //
- // If the buffer size is greater than the initializer, allocate and
- // initialize in two steps. Otherwise, pass the data directly.
- //
- if (BufferSize > ByteListLength) {
- BufferObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- BufferSize);
- if (BufferObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- RtlCopyMemory(BufferObject->U.Buffer.Buffer,
- ByteListPointer,
- ByteListLength);
- } else {
- BufferObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- ByteListPointer,
- ByteListLength);
- if (BufferObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- Statement->Reduction = BufferObject;
- }
- //
- // Move the instruction pointer over the byte list.
- //
- Context->CurrentOffset = (ULONG)Statement->AdditionalData;
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateConcatenateResourceTemplatesStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a "Concatenate Resource Templates" statement, which
- concatenates two buffers that are resources templates. It automatically
- strips the end tags off the two, adds it to the concatenation, and calcuates
- the checksum.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Argument0;
- ULONG Argument0Length;
- PACPI_OBJECT Argument1;
- ULONG Argument1Length;
- PUCHAR BytePointer;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT Result;
- UCHAR SumOfTemplate;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("ConcatResTemplate (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Only buffers are supported.
- //
- if (NewArgument->Type != AcpiObjectBuffer) {
- return STATUS_INVALID_PARAMETER;
- }
- }
- AcpipObjectAddReference(NewArgument);
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Argument0 = Statement->Argument[0];
- Argument1 = Statement->Argument[1];
- ASSERT(Argument0->Type == AcpiObjectBuffer);
- ASSERT(Argument1->Type == AcpiObjectBuffer);
- //
- // Strip off the end tag of argument 0, if there is one.
- //
- Argument0Length = Argument0->U.Buffer.Length;
- if (Argument0Length < 2) {
- Argument0Length = 0;
- } else {
- BytePointer = (PUCHAR)Argument0->U.Buffer.Buffer +
- Argument0->U.Buffer.Length - 2;
- if (*BytePointer == ACPI_RESOURCE_END_TAG) {
- Argument0Length -= 2;
- }
- }
- //
- // Strip off argument 1's end tag.
- //
- Argument1Length = Argument1->U.Buffer.Length;
- if (Argument1Length < 2) {
- Argument1Length = 0;
- } else {
- BytePointer = (PUCHAR)Argument1->U.Buffer.Buffer +
- Argument1->U.Buffer.Length - 2;
- if (*BytePointer == ACPI_RESOURCE_END_TAG) {
- Argument1Length -= 2;
- }
- }
- //
- // Create the new buffer object with space for an end tag.
- //
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- Argument0Length + Argument1Length + 2);
- if (Result == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Copy the templates over, back to back
- //
- RtlCopyMemory(Result->U.Buffer.Buffer,
- Argument0->U.Buffer.Buffer,
- Argument0Length);
- RtlCopyMemory(Result->U.Buffer.Buffer + Argument0Length,
- Argument1->U.Buffer.Buffer,
- Argument1Length);
- //
- // Slap a new end tag and checksum on that puppy.
- //
- BytePointer = (PUCHAR)(Result->U.Buffer.Buffer) +
- Argument0Length + Argument1Length;
- *BytePointer = ACPI_RESOURCE_END_TAG;
- BytePointer += 1;
- SumOfTemplate = AcpipChecksumData(Result->U.Buffer.Buffer,
- Argument0Length + Argument1Length + 1);
- *BytePointer = -SumOfTemplate;
- Statement->Reduction = Result;
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateConcatenateStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a concatenate statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Argument0;
- PACPI_OBJECT Argument1;
- PACPI_OBJECT NewArgument;
- ULONG NewLength;
- PACPI_OBJECT Result;
- ULONG String0Length;
- ULONG String1Length;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Concat (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Only integers, strings, and buffers are supported.
- //
- if ((NewArgument->Type != AcpiObjectInteger) &&
- (NewArgument->Type != AcpiObjectString) &&
- (NewArgument->Type != AcpiObjectBuffer)) {
- return STATUS_INVALID_PARAMETER;
- }
- //
- // Perform an implicit conversion on the second argument (to the
- // type of the first argument) if needed.
- //
- if (Statement->ArgumentsAcquired == 0) {
- AcpipObjectAddReference(Statement->Argument[0]);
- } else if (Statement->ArgumentsAcquired == 1) {
- if (Statement->Argument[0]->Type != NewArgument->Type) {
- NewArgument = AcpipConvertObjectType(
- Context,
- NewArgument,
- Statement->Argument[0]->Type);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // No conversion is needed, just add to the reference count.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT(Statement->ArgumentsAcquired == 2);
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- Argument0 = Statement->Argument[0];
- Argument1 = Statement->Argument[1];
- switch (Argument0->Type) {
- //
- // Two integers get put together and make a buffer.
- //
- case AcpiObjectInteger:
- NewLength = 2 * sizeof(ULONGLONG);
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- NewLength = 2 * sizeof(ULONG);
- }
- //
- // Create a new buffer.
- //
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- NewLength);
- if (Result == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Copy the integers in like buffers.
- //
- RtlCopyMemory(Result->U.Buffer.Buffer,
- &(Argument0->U.Integer.Value),
- NewLength / 2);
- RtlCopyMemory(Result->U.Buffer.Buffer + NewLength / 2,
- &(Argument1->U.Integer.Value),
- NewLength / 2);
- break;
- //
- // Two buffers simply get glommed together.
- //
- case AcpiObjectBuffer:
- NewLength = Argument0->U.Buffer.Length + Argument1->U.Buffer.Length;
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- NULL,
- NewLength);
- if (Result == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- RtlCopyMemory(Result->U.Buffer.Buffer,
- Argument0->U.Buffer.Buffer,
- Argument0->U.Buffer.Length);
- RtlCopyMemory(Result->U.Buffer.Buffer + Argument0->U.Buffer.Length,
- Argument1->U.Buffer.Buffer,
- Argument1->U.Buffer.Length);
- break;
- //
- // Two strings get concatenated into another string.
- //
- case AcpiObjectString:
- String0Length = RtlStringLength(Argument0->U.String.String);
- String1Length = RtlStringLength(Argument1->U.String.String);
- NewLength = String0Length + String1Length + 1;
- Result = AcpipCreateNamespaceObject(Context,
- AcpiObjectString,
- NULL,
- NULL,
- NewLength);
- if (Result == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- RtlCopyMemory(Result->U.String.String,
- Argument0->U.String.String,
- String0Length);
- RtlCopyMemory(Result->U.String.String + String0Length,
- Argument1->U.String.String,
- String1Length);
- Result->U.String.String[NewLength - 1] = '\0';
- break;
- default:
- ASSERT(FALSE);
- return STATUS_CONVERSION_FAILED;
- }
- Statement->Reduction = Result;
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateConditionalReferenceOfStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an "Reference Of" statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NameString;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT Reference;
- ULONGLONG ResultValue;
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("CondRefOf (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- //
- // The argument for RefOf is a "SuperName", which is a SimpleName,
- // DebugOp, or Type6Opcode. If this is the first time through, try to
- // parse a name string.
- //
- if (Context->PreviousStatement == NULL) {
- NameString = AcpipParseNameString(Context);
- if (NameString == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- if (Context->ExecuteStatements != FALSE) {
- Statement->Argument[0] =
- AcpipGetNamespaceObject(NameString->U.String.String,
- Context->CurrentScope);
- } else {
- Statement->Argument[0] = NULL;
- }
- if (Statement->Argument[0] != NULL) {
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- Statement->ArgumentsAcquired += 1;
- AcpipObjectReleaseReference(NameString);
- //
- // Increment the reference count on the object.
- //
- } else {
- if (Context->ExecuteStatements != FALSE) {
- NewArgument = Context->PreviousStatement->Reduction;
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- }
- Statement->ArgumentsAcquired += 1;
- }
- if (Statement->ArgumentsAcquired != Statement->ArgumentsNeeded) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements != FALSE) {
- //
- // The reduction of this statement is a boolean indicating whether the
- // object actually exists or not.
- //
- ResultValue = FALSE;
- if ((Statement->Argument[0] != NULL) &&
- (Statement->Argument[0]->Type != AcpiObjectUninitialized)) {
- ResultValue = TRUE;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if ((Statement->Argument[0] != NULL) &&
- (Statement->Argument[1] != NULL)) {
- Reference = AcpipCreateNamespaceObject(Context,
- AcpiObjectAlias,
- NULL,
- &(Statement->Argument[0]),
- sizeof(PACPI_OBJECT));
- if (Reference == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- AcpipPerformStoreOperation(Context,
- Reference,
- Statement->Argument[1]);
- AcpipObjectReleaseReference(Reference);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateCopyObjectStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a "Copy Object" statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Destination;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT Source;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("CopyObject (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- ASSERT(Statement->ArgumentsAcquired == 0);
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipObjectAddReference(NewArgument);
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- Source = Statement->Argument[0];
- Statement->Reduction = AcpipCopyObject(Source);
- //
- // If the target is supplied, replace it with the copy.
- //
- Destination = Statement->Argument[1];
- if (Destination != NULL) {
- return AcpipReplaceObjectContents(Context, Source, Destination);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateCreateBufferFieldStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a CreateField (from a buffer) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ACPI_BUFFER_FIELD_OBJECT BufferField;
- PSTR Name;
- PACPI_OBJECT NewArgument;
- ACPI_OBJECT_TYPE ObjectType;
- NewArgument = NULL;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("CreateField (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- RtlDebugPrint(", ");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if ((Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) &&
- (Statement->ArgumentsAcquired != 3)) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first required argument is a buffer, the second is the
- // bit index (Integer), and the third is the bit length (Integer).
- //
- ObjectType = AcpiObjectBuffer;
- if ((Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- ObjectType = AcpiObjectInteger;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != ObjectType) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- ObjectType);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsAcquired != 3) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- //
- // The fourth argument is a name string, which can be parsed now.
- //
- ASSERT(Statement->ArgumentsAcquired == 3);
- Statement->Argument[3] = AcpipParseNameString(Context);
- if (Statement->Argument[3] == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Statement->ArgumentsAcquired += 1;
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[3]->Type == AcpiObjectString);
- Name = Statement->Argument[3]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("%s)", Name);
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectBuffer);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
- //
- // Create the buffer field object. Remember that additional data holds the
- // bit field length.
- //
- RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
- BufferField.DestinationObject = Statement->Argument[0];
- BufferField.BitOffset = Statement->Argument[1]->U.Integer.Value;
- BufferField.BitLength = Statement->Argument[2]->U.Integer.Value;
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectBufferField,
- Name,
- &BufferField,
- sizeof(ACPI_BUFFER_FIELD_OBJECT));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateCreateFixedBufferFieldStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a CreateBitField, CreateByteField, CreateWordField,
- CreateDWordField, or CreateQWordField statement, which creates a Buffer
- Field object pointing at a buffer.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ACPI_BUFFER_FIELD_OBJECT BufferField;
- PSTR Name;
- PACPI_OBJECT NewArgument;
- ACPI_OBJECT_TYPE ObjectType;
- NewArgument = NULL;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- switch (Statement->AdditionalData) {
- case 1:
- RtlDebugPrint("CreateBitField (");
- break;
- case BITS_PER_BYTE:
- RtlDebugPrint("CreateByteField (");
- break;
- case sizeof(USHORT) * BITS_PER_BYTE:
- RtlDebugPrint("CreateWordField (");
- break;
- case sizeof(ULONG) * BITS_PER_BYTE:
- RtlDebugPrint("CreateDWordField (");
- break;
- case sizeof(ULONGLONG) * BITS_PER_BYTE:
- RtlDebugPrint("CreateQWordField (");
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- RtlDebugPrint(", ");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- ASSERT(Statement->ArgumentsAcquired != 2);
- //
- // If not executing, then assume the argument would be there but
- // don't try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- //
- // Grab the first or second argument.
- //
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first required argument is a buffer, and the second is the
- // bit index (Integer).
- //
- ObjectType = AcpiObjectBuffer;
- if (Statement->ArgumentsAcquired == 1) {
- ObjectType = AcpiObjectInteger;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != ObjectType) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- ObjectType);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- //
- // If only the first argument has been parsed, then another one is
- // needed. If two have, then continue to parse the third.
- //
- if (Statement->ArgumentsAcquired == 1) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // The third argument is a name string, which can be parsed now.
- //
- if (Statement->ArgumentsAcquired == 2) {
- ASSERT(Statement->ArgumentsAcquired == 2);
- Statement->Argument[2] = AcpipParseNameString(Context);
- if (Statement->Argument[2] == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[2]->Type == AcpiObjectString);
- Name = Statement->Argument[2]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("%s)", Name);
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectBuffer);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- //
- // Create the buffer field object. Remember that additional data holds the
- // bit field length.
- //
- RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
- BufferField.DestinationObject = Statement->Argument[0];
- BufferField.BitLength = Statement->AdditionalData;
- BufferField.BitOffset = Statement->Argument[1]->U.Integer.Value;
- //
- // Bitfields are specified in bits, but all other sized fields are
- // specified in bytes.
- //
- if (BufferField.BitLength > 1) {
- BufferField.BitOffset *= BITS_PER_BYTE;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectBufferField,
- Name,
- &BufferField,
- sizeof(ACPI_BUFFER_FIELD_OBJECT));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDataStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates constant data coming from ByteData, WordData,
- DWordData, QWordData, and StringData.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR DataPointer;
- DataPointer = (PUCHAR)Context->AmlCode + Statement->AdditionalData;
- //
- // For string data, just create the string from the buffer pointer. A copy
- // will be made.
- //
- if (Statement->AdditionalData2 == 0) {
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectString,
- NULL,
- DataPointer,
- RtlStringLength((PSTR)DataPointer) + 1);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("\"");
- RtlDebugPrint(Statement->Reduction->U.String.String);
- RtlDebugPrint("\"");
- }
- //
- // The other types are integers.
- //
- } else {
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- NULL,
- 0);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Statement->Reduction->U.Integer.Value = 0;
- RtlCopyMemory(&(Statement->Reduction->U.Integer.Value),
- DataPointer,
- Statement->AdditionalData2);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("0x%I64x", Statement->Reduction->U.Integer.Value);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDelayStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates both the Sleep and Stall statements.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- ULONG Operand;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- if (Statement->Type == AmlStatementSleep) {
- RtlDebugPrint("Sleep (");
- } else {
- ASSERT(Statement->Type == AmlStatementStall);
- RtlDebugPrint("Stall (");
- }
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- //
- // For sleep statements, use the scheduler and relinquish the processor.
- //
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- Operand = (ULONG)Statement->Argument[0]->U.Integer.Value;
- if (Statement->Type == AmlStatementSleep) {
- AcpipSleep(Operand);
- //
- // For stall statements, perform a busy spin.
- //
- } else {
- ASSERT(Statement->Type == AmlStatementStall);
- AcpipBusySpin(Operand);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDebugStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Debug statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Debug");
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Create a debug object. Simple as that.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectDebug,
- NULL,
- NULL,
- 0);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDereferenceOfStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a "Dereference Of" statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Source;
- KSTATUS Status;
- //
- // Gather arguments.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("DerefOf (");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- } else {
- Statement->Argument[0] = NULL;
- if (Context->ExecuteStatements != FALSE) {
- Statement->Argument[0] = Context->PreviousStatement->Reduction;
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(")");
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- Source = Statement->Argument[0];
- switch (Source->Type) {
- case AcpiObjectAlias:
- Statement->Reduction = Source->U.Alias.DestinationObject;
- AcpipObjectAddReference(Statement->Reduction);
- break;
- case AcpiObjectString:
- Statement->Reduction =
- AcpipGetNamespaceObject(Source->U.String.String,
- Context->CurrentScope);
- if (Statement->Reduction == NULL) {
- return STATUS_NOT_FOUND;
- }
- AcpipObjectAddReference(Statement->Reduction);
- break;
- case AcpiObjectBufferField:
- Status = AcpipReadFromBufferField(Context,
- Source,
- &(Statement->Reduction));
- if (!KSUCCESS(Status)) {
- return Status;
- }
- break;
- default:
- ASSERT(FALSE);
- return STATUS_UNEXPECTED_TYPE;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDeviceStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Device declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR DeviceName;
- PACPI_OBJECT DeviceObject;
- if (Context->PreviousStatement == NULL) {
- Statement->SavedScope = NULL;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- DeviceName = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Device (%s) {", DeviceName);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Create the device object.
- //
- DeviceObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectDevice,
- DeviceName,
- NULL,
- 0);
- if (DeviceObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Make this device the current scope.
- //
- Statement->SavedScope = Context->CurrentScope;
- Context->CurrentScope = DeviceObject;
- Statement->Reduction = DeviceObject;
- }
- Context->IndentationLevel += 1;
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Pop this puppy off the stack.
- //
- Context->CurrentScope = Statement->SavedScope;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- AcpipPrintIndentedNewLine(Context);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateDivideStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a divide statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ULONGLONG Dividend;
- ULONGLONG Divisor;
- PACPI_OBJECT NewArgument;
- ULONGLONG Quotient;
- ULONGLONG Remainder;
- PACPI_OBJECT RemainderObject;
- KSTATUS Status;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Divide (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT((Statement->ArgumentsAcquired == 2) ||
- (Statement->ArgumentsAcquired == 3));
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- Dividend = Statement->Argument[0]->U.Integer.Value;
- Divisor = Statement->Argument[1]->U.Integer.Value;
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- Dividend &= 0xFFFFFFFF;
- Dividend &= 0xFFFFFFFF;
- }
- //
- // Fail to divide by 0, otherwise do the divide.
- //
- if (Divisor == 0) {
- return STATUS_DIVIDE_BY_ZERO;
- }
- Quotient = Dividend / Divisor;
- Remainder = Dividend % Divisor;
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- Quotient &= 0xFFFFFFFF;
- Remainder &= 0xFFFFFFFF;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Quotient,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the remainder if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- RemainderObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Remainder,
- sizeof(ULONGLONG));
- if (RemainderObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Status = AcpipPerformStoreOperation(Context,
- RemainderObject,
- Statement->Argument[2]);
- AcpipObjectReleaseReference(RemainderObject);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- }
- //
- // Store the quotient in the target if supplied.
- //
- if (Statement->Argument[3] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[3]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateElseStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Else statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- //
- // If this is the first time through, up the indentation level.
- //
- if (Context->PreviousStatement == NULL) {
- Context->IndentationLevel += 1;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Else {");
- }
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Check the result of the last If statement. Skip over the Else if the
- // IF succeeded.
- //
- if (Context->LastIfStatementResult != FALSE) {
- Context->CurrentOffset = Statement->AdditionalData;
- }
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateEventStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Event (creation) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR Name;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- Name = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Event (%s)", Name);
- }
- if (Context->ExecuteStatements != FALSE) {
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectEvent,
- Name,
- NULL,
- 0);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateExecutingMethodStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Executing Method statement. This does not
- translate to a real ACPI opcode, but is a dummy object placed on the
- currently-executing statement stack so that return statements know how
- far to pop back up.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Method;
- PAML_STATEMENT PreviousStatement;
- KSTATUS Status;
- ULONGLONG Zero;
- ASSERT(Context->ExecuteStatements != FALSE);
- //
- // If the method context to wait for is set, wait until the method context
- // comes back to the original routine.
- //
- if (Statement->AdditionalData2 != (UINTN)NULL) {
- if ((UINTN)Context->CurrentMethod == Statement->AdditionalData2) {
- Statement->Reduction = Context->ReturnValue;
- AcpipObjectAddReference(Statement->Reduction);
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- return STATUS_SUCCESS;
- }
- //
- // While not in the spec, folklore has it that an old version of the
- // Windows AML interpreter allowed for AML methods without return
- // statements (even though ACPI said it was required). The behavior
- // instead was that the function returned a constant zero integer.
- // Many BIOSes took advantage of that, so now it basically is part
- // of the spec. If the current function seems to have just finished,
- // then pop its context.
- //
- if (Context->CurrentOffset == Context->AmlCodeSize) {
- if (Context->ReturnValue == NULL) {
- Zero = 0;
- Context->ReturnValue =
- AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Zero,
- sizeof(ULONGLONG));
- }
- AcpipPopExecutingStatements(Context, FALSE, FALSE);
- AcpipPopCurrentMethodContext(Context);
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- return STATUS_SUCCESS;
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- PreviousStatement = Context->PreviousStatement;
- //
- // The evaluate executing method statement is special in that it will not
- // get called once with a previous statement of NULL. Since it is a side
- // effect of another statement spitting out a reduction of type method, this
- // statement always gets passed a previous statement. The first time it's
- // called, the previous statement should have a pointer to the method
- // object. Use that to determine the argument count. Additional data was
- // initialized to 0 to indicate the first time this statement is being
- // evaluated.
- //
- if (Statement->AdditionalData == (UINTN)NULL) {
- ASSERT((PreviousStatement != NULL) &&
- (PreviousStatement->Reduction != NULL) &&
- (PreviousStatement->Reduction->Type == AcpiObjectMethod));
- Method = PreviousStatement->Reduction;
- Statement->AdditionalData = (UINTN)Method;
- Statement->ArgumentsNeeded = Method->U.Method.ArgumentCount;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(" (");
- }
- if (Statement->ArgumentsNeeded != 0) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- //
- // If not all arguments are acquired, wait for them to come in, and collect
- // 'em.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if ((PreviousStatement == NULL) ||
- (PreviousStatement->Reduction == NULL)) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- Statement->Argument[Statement->ArgumentsAcquired] =
- PreviousStatement->Reduction;
- Statement->ArgumentsAcquired += 1;
- AcpipObjectAddReference(PreviousStatement->Reduction);
- }
- //
- // If all arguments are still not acquired, wait for more.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(", ");
- }
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- Context->IndentationLevel += 1;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(") {");
- AcpipPrintIndentedNewLine(Context);
- }
- //
- // Store the current method context in Additional Data 2, and use that
- // to determine when to complete this statement (complete the statement
- // when this context comes back.
- //
- Statement->AdditionalData2 = (UINTN)Context->CurrentMethod;
- //
- // Push the method execution context on as the current context.
- //
- Method = (PVOID)(UINTN)Statement->AdditionalData;
- Status = AcpipPushMethodOnExecutionContext(
- Context,
- Method,
- Method->U.Method.OsMutex,
- Method->U.Method.IntegerWidthIs32,
- Method->U.Method.AmlCode,
- Method->U.Method.AmlCodeSize,
- Statement->ArgumentsNeeded,
- Statement->Argument);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- KSTATUS
- AcpipEvaluateFatalStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a fatal execution statement. This will stop the
- operating system.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR DataPointer;
- ULONGLONG FatalArgument;
- ULONG FatalCode;
- UCHAR FatalType;
- PACPI_OBJECT NewArgument;
- DataPointer = (PUCHAR)Context->AmlCode + Statement->AdditionalData;
- FatalType = *DataPointer;
- FatalCode = *(PULONG)(DataPointer + 1);
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Fatal (%x, %x, ", FatalType, FatalCode);
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- ASSERT(Statement->ArgumentsAcquired == 0);
- //
- // Convert the argument if it is there. The argument is
- // technically required, but since this is a fatal error, be a
- // bit more forgiving.
- //
- if (Context->PreviousStatement->Reduction != NULL) {
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- //
- // Die... so sad.
- //
- FatalArgument = 0;
- if ((Statement->Argument[0] != NULL) &&
- (Statement->Argument[0]->Type == AcpiObjectInteger)) {
- FatalArgument = Statement->Argument[0]->U.Integer.Value;
- }
- RtlDebugPrint("\n\n*** ACPI Fatal Error ***\n"
- "Type: 0x%x, Code: 0x%x, Argument: 0x%I64x\n"
- "Execution Context: %x\n",
- FatalType,
- FatalCode,
- FatalArgument,
- Context);
- AcpipFatalError(ACPI_CRASH_FATAL_INSTRUCTION,
- FatalType,
- FatalCode,
- FatalArgument);
- //
- // Execution will never get here, but the compiler will get sassy if there's
- // just nothing.
- //
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateFieldStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Field (in an Operation Region) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- PACPI_OBJECT OperationRegion;
- KSTATUS Status;
- OperationRegion = NULL;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- if (Context->ExecuteStatements != FALSE) {
- //
- // Get the operation region this Field refers to.
- //
- OperationRegion = AcpipGetNamespaceObject(
- Statement->Argument[0]->U.String.String,
- Context->CurrentScope);
- if (OperationRegion == NULL) {
- return STATUS_NOT_FOUND;
- }
- }
- //
- // Parse the field list.
- //
- Status = AcpipParseFieldList(Context,
- Statement->Type,
- OperationRegion,
- NULL,
- NULL,
- NULL,
- NULL,
- Statement->AdditionalData,
- (UCHAR)Statement->AdditionalData2);
- return Status;
- }
- KSTATUS
- AcpipEvaluateFindSetBitStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a find set left bit or find set right bit statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ULONGLONG Mask;
- PACPI_OBJECT NewArgument;
- ULONGLONG Result;
- ULONGLONG Value;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- switch (Statement->Type) {
- case AmlStatementFindSetLeftBit:
- RtlDebugPrint("FindSetLeftBit (");
- break;
- case AmlStatementFindSetRightBit:
- RtlDebugPrint("FindSetRightBit (");
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (Statement->ArgumentsAcquired == 0) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT(Statement->ArgumentsAcquired == 1);
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- Value = Statement->Argument[0]->U.Integer.Value;
- if (Value != 0) {
- if (Statement->Type == AmlStatementFindSetLeftBit) {
- Result = 64;
- Mask = 0x8000000000000000ULL;
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- Result = 32;
- Mask = 0x80000000;
- ASSERT(Value <= MAX_ULONG);
- }
- while ((Value & Mask) == 0) {
- Value = Value << 1;
- Result -= 1;
- }
- } else {
- ASSERT(Statement->Type == AmlStatementFindSetRightBit);
- Mask = 1;
- Result = 1;
- while ((Value & Mask) == 0) {
- Value = Value >> 1;
- Result += 1;
- }
- }
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Result,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[1] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[1]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateIfStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an If statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("If (");
- } else {
- ASSERT(Statement->ArgumentsAcquired == 0);
- RtlDebugPrint(") {");
- }
- }
- if (Context->PreviousStatement == NULL) {
- Context->IndentationLevel += 1;
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- }
- Statement->ArgumentsAcquired += 1;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements != FALSE) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- //
- // Evaluate the if statement by skipping the package length if it's
- // zero.
- //
- Statement->AdditionalData2 = TRUE;
- if (Statement->Argument[0]->U.Integer.Value == 0) {
- Statement->AdditionalData2 = FALSE;
- Context->CurrentOffset = Statement->AdditionalData;
- }
- }
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- //
- // Save the result of the If statement into the context so that an Else
- // can be properly evaluated if it's coming up next.
- //
- if (Statement->AdditionalData2 != FALSE) {
- Context->LastIfStatementResult = TRUE;
- } else {
- Context->LastIfStatementResult = FALSE;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateIncrementOrDecrementStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Increment or Decrement statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT IntegerObject;
- PACPI_OBJECT NewArgument;
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- if (Statement->Type == AmlStatementIncrement) {
- RtlDebugPrint("Increment (");
- } else {
- ASSERT(Statement->Type == AmlStatementDecrement);
- RtlDebugPrint("Decrement (");
- }
- } else {
- RtlDebugPrint(")");
- }
- }
- //
- // If there is no previous statement, wait for the argument to come in.
- //
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, assume the argument would be there, and move on.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- //
- // Increment the reference count on the object (assuming it's there).
- //
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipObjectAddReference(NewArgument);
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements != FALSE) {
- //
- // Perform an implicit conversion if necessary.
- //
- if (Statement->Argument[0]->Type != AcpiObjectInteger) {
- IntegerObject = AcpipConvertObjectType(Context,
- Statement->Argument[0],
- AcpiObjectInteger);
- if (IntegerObject == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- } else {
- IntegerObject = Statement->Argument[0];
- AcpipObjectAddReference(IntegerObject);
- }
- //
- // Do the increment or decrement.
- //
- if (Statement->Type == AmlStatementIncrement) {
- IntegerObject->U.Integer.Value += 1;
- } else {
- IntegerObject->U.Integer.Value -= 1;
- }
- //
- // Store the result back if this is not the argument. This also implies
- // a conversion back to the original type is necessary.
- //
- Statement->Reduction = IntegerObject;
- if (IntegerObject != Statement->Argument[0]) {
- AcpipPerformStoreOperation(Context,
- IntegerObject,
- Statement->Argument[0]);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateIndexFieldStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an IndexField (in an Operation Region) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- PACPI_OBJECT DataRegister;
- PACPI_OBJECT IndexRegister;
- KSTATUS Status;
- IndexRegister = NULL;
- DataRegister = NULL;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectString);
- if (Context->ExecuteStatements != FALSE) {
- //
- // Get the Index field object.
- //
- IndexRegister = AcpipGetNamespaceObject(
- Statement->Argument[0]->U.String.String,
- Context->CurrentScope);
- if (IndexRegister == NULL) {
- return STATUS_NOT_FOUND;
- }
- //
- // Get the Data field object.
- //
- DataRegister = AcpipGetNamespaceObject(
- Statement->Argument[1]->U.String.String,
- Context->CurrentScope);
- if (DataRegister == NULL) {
- return STATUS_NOT_FOUND;
- }
- }
- //
- // Parse the field list.
- //
- Status = AcpipParseFieldList(Context,
- Statement->Type,
- NULL,
- NULL,
- NULL,
- IndexRegister,
- DataRegister,
- Statement->AdditionalData,
- (UCHAR)Statement->AdditionalData2);
- return Status;
- }
- KSTATUS
- AcpipEvaluateIndexStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Index statement, which creates a reference to the
- nth object in a buffer, string, or package.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ACPI_ALIAS_OBJECT Alias;
- ACPI_OBJECT_TYPE ArgumentType;
- ACPI_BUFFER_FIELD_OBJECT BufferField;
- PACPI_OBJECT NewArgument;
- ULONG PackageIndex;
- KSTATUS Status;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Index (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first argument must be a buffer, package, or string.
- //
- ArgumentType = AcpiObjectUninitialized;
- if (Statement->ArgumentsAcquired == 0) {
- if ((NewArgument->Type != AcpiObjectBuffer) &&
- (NewArgument->Type != AcpiObjectPackage) &&
- (NewArgument->Type != AcpiObjectString)) {
- ArgumentType = AcpiObjectBuffer;
- }
- //
- // The second object must evaluate to an integer.
- //
- } else if (NewArgument->Type != AcpiObjectInteger) {
- ArgumentType = AcpiObjectInteger;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (ArgumentType != AcpiObjectUninitialized) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- ArgumentType);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT(Statement->ArgumentsAcquired == 2);
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT((Statement->Argument[0]->Type == AcpiObjectBuffer) ||
- (Statement->Argument[0]->Type == AcpiObjectString) ||
- (Statement->Argument[0]->Type == AcpiObjectPackage));
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- //
- // For strings, create a field that points into the string.
- //
- if ((Statement->Argument[0]->Type == AcpiObjectString) ||
- (Statement->Argument[0]->Type == AcpiObjectBuffer)) {
- RtlZeroMemory(&BufferField, sizeof(ACPI_BUFFER_FIELD_OBJECT));
- BufferField.DestinationObject = Statement->Argument[0];
- BufferField.BitOffset =
- Statement->Argument[1]->U.Integer.Value * BITS_PER_BYTE;
- BufferField.BitLength = BITS_PER_BYTE;
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectBufferField,
- NULL,
- &BufferField,
- sizeof(ACPI_BUFFER_FIELD_OBJECT));
- } else if (Statement->Argument[0]->Type == AcpiObjectPackage) {
- RtlZeroMemory(&Alias, sizeof(ACPI_ALIAS_OBJECT));
- PackageIndex = (ULONG)Statement->Argument[1]->U.Integer.Value;
- Alias.DestinationObject = AcpipGetPackageObject(Statement->Argument[0],
- PackageIndex);
- if (Alias.DestinationObject == NULL) {
- return STATUS_NOT_FOUND;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectAlias,
- NULL,
- &Alias,
- sizeof(ACPI_ALIAS_OBJECT));
- }
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- Status = AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- return Status;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateIntegerArithmeticStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates simple arithmetic operations that take two operands
- and a target.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- ULONGLONG Operand1;
- ULONGLONG Operand2;
- ULONGLONG ResultValue;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- switch (Statement->Type) {
- case AmlStatementAdd:
- RtlDebugPrint("Add (");
- break;
- case AmlStatementAnd:
- RtlDebugPrint("And (");
- break;
- case AmlStatementMod:
- RtlDebugPrint("Mod (");
- break;
- case AmlStatementMultiply:
- RtlDebugPrint("Multiply (");
- break;
- case AmlStatementNand:
- RtlDebugPrint("Nand (");
- break;
- case AmlStatementNor:
- RtlDebugPrint("Nor (");
- break;
- case AmlStatementOr:
- RtlDebugPrint("Or (");
- break;
- case AmlStatementSubtract:
- RtlDebugPrint("Subtract (");
- break;
- case AmlStatementShiftLeft:
- RtlDebugPrint("ShiftLeft (");
- break;
- case AmlStatementShiftRight:
- RtlDebugPrint("ShiftRight (");
- break;
- case AmlStatementXor:
- RtlDebugPrint("XOr (");
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT(Statement->ArgumentsAcquired == 2);
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- Operand1 = Statement->Argument[0]->U.Integer.Value;
- Operand2 = Statement->Argument[1]->U.Integer.Value;
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- Operand1 &= 0xFFFFFFFF;
- Operand2 &= 0xFFFFFFFF;
- }
- switch (Statement->Type) {
- case AmlStatementAdd:
- ResultValue = Operand1 + Operand2;
- break;
- case AmlStatementAnd:
- ResultValue = Operand1 & Operand2;
- break;
- case AmlStatementMod:
- if (Operand2 == 0) {
- return STATUS_DIVIDE_BY_ZERO;
- }
- ResultValue = Operand1 % Operand2;
- break;
- case AmlStatementMultiply:
- ResultValue = Operand1 * Operand2;
- break;
- case AmlStatementNand:
- ResultValue = ~(Operand1 & Operand2);
- break;
- case AmlStatementNor:
- ResultValue = ~(Operand1 | Operand2);
- break;
- case AmlStatementOr:
- ResultValue = Operand1 | Operand2;
- break;
- case AmlStatementSubtract:
- ResultValue = Operand1 - Operand2;
- break;
- case AmlStatementShiftLeft:
- ResultValue = Operand1 << Operand2;
- break;
- case AmlStatementShiftRight:
- ResultValue = Operand1 >> Operand2;
- break;
- case AmlStatementXor:
- ResultValue = Operand1 ^ Operand2;
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- ResultValue &= 0xFFFFFFFF;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateIntegerStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates statements that take no arguments and generate an
- integer output. This includes the constant statements Zero, One, and Ones,
- as well as the AML Revision and Timer statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS almost always.
- STATUS_INVALID_PARAMETER if this routine was called for the wrong statement
- type (an internal error for sure).
- STATUS_UNSUCCESSFUL if a namespace object could not be created.
- --*/
- {
- BOOL PrintParentheses;
- ULONGLONG Value;
- PrintParentheses = FALSE;
- switch (Statement->Type) {
- case AmlStatementZero:
- Value = 0;
- break;
- case AmlStatementOne:
- Value = 1;
- break;
- case AmlStatementOnes:
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- Value = 0xFFFFFFFF;
- } else {
- Value = 0xFFFFFFFFFFFFFFFFULL;
- }
- break;
- case AmlStatementRevision:
- if (Context->PrintStatements != FALSE) {
- PrintParentheses = TRUE;
- RtlDebugPrint("Revision (");
- }
- Value = AML_REVISION;
- break;
- case AmlStatementTimer:
- if (Context->PrintStatements != FALSE) {
- PrintParentheses = TRUE;
- RtlDebugPrint("Timer (");
- }
- Value = AcpipGetTimerValue();
- break;
- default:
- ASSERT(FALSE);
- return STATUS_INVALID_PARAMETER;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("0x%I64x", Value);
- if (PrintParentheses != FALSE) {
- RtlDebugPrint(")");
- }
- }
- if (Context->ExecuteStatements != FALSE) {
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Value,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateLoadStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Load statement, which adds the contents of a
- memory op-region as an SSDT to the namespace.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PDESCRIPTION_HEADER Buffer;
- PACPI_OBJECT BufferObject;
- UINTN BufferSize;
- PACPI_OBJECT DdbHandle;
- PACPI_OBJECT NewArgument;
- PACPI_OPERATION_REGION_OBJECT OperationRegion;
- PACPI_OBJECT Source;
- KSTATUS Status;
- Buffer = NULL;
- BufferObject = NULL;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Load (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- ASSERT(Statement->ArgumentsAcquired <= 1);
- if (Context->PreviousStatement->Reduction != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- //
- // The source can either be an operation region itself or a field unit.
- //
- Source = Statement->Argument[0];
- DdbHandle = Statement->Argument[1];
- //
- // If it's an operation region, read it directly. It had better be a memory
- // region.
- //
- if (Source->Type == AcpiObjectOperationRegion) {
- OperationRegion = &(Source->U.OperationRegion);
- if ((OperationRegion->Space != OperationRegionSystemMemory) ||
- (OperationRegion->Length < sizeof(DESCRIPTION_HEADER))) {
- ASSERT(FALSE);
- return STATUS_INVALID_PARAMETER;
- }
- BufferSize = OperationRegion->Length;
- ASSERT(BufferSize == OperationRegion->Length);
- Buffer = AcpipAllocateMemory(BufferSize);
- if (Buffer == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- Status = OperationRegion->FunctionTable->Read(
- OperationRegion->OsContext,
- 0,
- OperationRegion->Length * BITS_PER_BYTE,
- Buffer);
- ASSERT(KSUCCESS(Status));
- //
- // Convert the field unit into a buffer, which performs a read of the
- // op-region.
- //
- } else if (Source->Type == AcpiObjectFieldUnit) {
- BufferObject = AcpipConvertObjectType(Context,
- Source,
- AcpiObjectBuffer);
- if (BufferObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Steal the buffer from the buffer object.
- //
- Buffer = BufferObject->U.Buffer.Buffer;
- BufferSize = BufferObject->U.Buffer.Length;
- BufferObject->U.Buffer.Buffer = NULL;
- BufferObject->U.Buffer.Length = 0;
- } else {
- RtlDebugPrint("ACPI: Load source should be an op-region or field.\n");
- ASSERT(FALSE);
- return STATUS_UNEXPECTED_TYPE;
- }
- //
- // Validate the buffer a bit.
- //
- if ((BufferSize < sizeof(DESCRIPTION_HEADER)) ||
- (BufferSize < Buffer->Length)) {
- Status = STATUS_DATA_LENGTH_MISMATCH;
- goto EvaluateLoadStatementEnd;
- }
- if (AcpipChecksumData(Buffer, Buffer->Length) != 0) {
- Status = STATUS_CHECKSUM_MISMATCH;
- goto EvaluateLoadStatementEnd;
- }
- //
- // Load the definition block synchronously.
- //
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("\nLoading Definition Block...\n");
- }
- Status = AcpiLoadDefinitionBlock(Buffer, DdbHandle);
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("ACPI: Failed to execute Load: %x\n", Status);
- goto EvaluateLoadStatementEnd;
- }
- //
- // The definition block owns the buffer now.
- //
- Buffer = NULL;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("\nDone Loading Definition Block\n");
- }
- EvaluateLoadStatementEnd:
- if (BufferObject != NULL) {
- AcpipObjectReleaseReference(BufferObject);
- }
- if (Buffer != NULL) {
- AcpipFreeMemory(Buffer);
- }
- return Status;
- }
- KSTATUS
- AcpipEvaluateLocalStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates the LocalX opcodes.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ULONG LocalNumber;
- PACPI_OBJECT LocalObject;
- LocalNumber = (ULONG)Statement->AdditionalData;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Local%d", LocalNumber);
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- LocalObject = Context->CurrentMethod->LocalVariable[LocalNumber];
- //
- // Create an uninitialized object if none exists yet.
- //
- if (LocalObject == NULL) {
- LocalObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectUninitialized,
- NULL,
- NULL,
- 0);
- if (LocalObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Context->CurrentMethod->LocalVariable[LocalNumber] = LocalObject;
- }
- Statement->Reduction = LocalObject;
- AcpipObjectAddReference(LocalObject);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateLogicalExpressionStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates logical binary operators (Logical and, equal,
- greater, less, and or).
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- ULONGLONG Operand1;
- ULONGLONG Operand2;
- ULONGLONG ResultValue;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- switch (Statement->Type) {
- case AmlStatementLogicalAnd:
- RtlDebugPrint("LAnd (");
- break;
- case AmlStatementLogicalEqual:
- RtlDebugPrint("LEqual (");
- break;
- case AmlStatementLogicalGreater:
- RtlDebugPrint("LGreater (");
- break;
- case AmlStatementLogicalLess:
- RtlDebugPrint("LLess (");
- break;
- case AmlStatementLogicalOr:
- RtlDebugPrint("LOr (");
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- Operand1 = Statement->Argument[0]->U.Integer.Value;
- Operand2 = Statement->Argument[1]->U.Integer.Value;
- ResultValue = FALSE;
- switch (Statement->Type) {
- case AmlStatementLogicalAnd:
- if ((Operand1 != 0) && (Operand2 != 0)) {
- ResultValue = TRUE;
- }
- break;
- case AmlStatementLogicalEqual:
- if (Operand1 == Operand2) {
- ResultValue = TRUE;
- }
- break;
- case AmlStatementLogicalGreater:
- if (Operand1 > Operand2) {
- ResultValue = TRUE;
- }
- break;
- case AmlStatementLogicalLess:
- if (Operand1 < Operand2) {
- ResultValue = TRUE;
- }
- break;
- case AmlStatementLogicalOr:
- if ((Operand1 != 0) || (Operand2 != 0)) {
- ResultValue = TRUE;
- }
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateLogicalNotStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates logical NOT operator.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- ULONGLONG ResultValue;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("LNot (");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- ResultValue = FALSE;
- if (Statement->Argument[0]->U.Integer.Value == 0) {
- ResultValue = TRUE;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateMatchStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Match statement, which iterates over a package
- doing some simple comparisons.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR InstructionPointer;
- ULONGLONG ItemCount;
- ULONGLONG ItemIndex;
- BOOL Match;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT Operand1;
- PACPI_OBJECT Operand2;
- ACPI_MATCH_OPERATOR Operator1;
- ACPI_MATCH_OPERATOR Operator2;
- PACPI_OBJECT Package;
- PACPI_OBJECT PackageElement;
- PACPI_OBJECT StartIndex;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Match (");
- } else if (Statement->ArgumentsAcquired < 3) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // An argument is required.
- //
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first object must be a package.
- //
- if (Statement->ArgumentsAcquired == 0) {
- if (NewArgument->Type != AcpiObjectPackage) {
- return STATUS_CONVERSION_FAILED;
- }
- AcpipObjectAddReference(NewArgument);
- //
- // The second and third arguments must be an integer, buffer, or
- // string. Convert that to an integer. The fourth argument
- // (StartIndex) is also an integer.
- //
- } else if ((Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2) ||
- (Statement->ArgumentsAcquired == 3)) {
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- }
- //
- // Save the argument and return if not all arguments have been
- // collected yet.
- //
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- //
- // After the first and second arguments come match opcodes. Pull
- // those out and store them in additional data.
- //
- if ((Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- InstructionPointer =
- (PUCHAR)(Context->AmlCode) + Context->CurrentOffset;
- if (Context->CurrentOffset >= Context->AmlCodeSize) {
- return STATUS_MALFORMED_DATA_STREAM;
- }
- Statement->AdditionalData = (Statement->AdditionalData << 8) |
- *InstructionPointer;
- if (*InstructionPointer >= MatchOperatorCount) {
- return STATUS_MALFORMED_DATA_STREAM;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("%s, ",
- AcpiMatchOpcodeString[*InstructionPointer]);
- }
- Context->CurrentOffset += 1;
- }
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- //
- // Assert that all the arguments are the expected types.
- //
- Package = Statement->Argument[0];
- Operand1 = Statement->Argument[1];
- Operand2 = Statement->Argument[2];
- StartIndex = Statement->Argument[3];
- Operator1 = (Statement->AdditionalData >> 8) & 0xFF;
- Operator2 = Statement->AdditionalData & 0xFF;
- ASSERT((Package->Type == AcpiObjectPackage) &&
- (StartIndex->Type == AcpiObjectInteger));
- ASSERT((Operand1->Type == AcpiObjectInteger) &&
- (Operand2->Type == AcpiObjectInteger));
- ASSERT((Operator1 < MatchOperatorCount) &&
- (Operator2 < MatchOperatorCount));
- //
- // Perform the match operation.
- //
- ItemIndex = StartIndex->U.Integer.Value;
- ItemCount = Package->U.Package.ElementCount;
- while (ItemIndex < ItemCount) {
- PackageElement = AcpipGetPackageObject(Package, ItemIndex);
- Match = AcpipEvaluateMatchComparison(Context,
- PackageElement,
- Operand1,
- Operator1,
- Operand2,
- Operator2);
- if (Match != FALSE) {
- break;
- }
- ItemIndex += 1;
- }
- //
- // If a match was never found (as evidenced by the index being all the way
- // at the end), the ACPI says to return the constant "Ones".
- //
- if (ItemIndex == ItemCount) {
- ItemIndex = (ULONGLONG)-1;
- if (Context->CurrentMethod->IntegerWidthIs32) {
- ItemIndex = (ULONG)-1;
- }
- }
- //
- // Return the result value.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ItemIndex,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateMethodStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Method declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ACPI_METHOD_OBJECT Method;
- UCHAR MethodFlags;
- PACPI_OBJECT MethodObject;
- PSTR Name;
- //
- // If the previous statement is NULL, this is the first time through.
- //
- if (Context->PreviousStatement == NULL) {
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- //
- // Get the method flags out of additional data 2.
- //
- MethodFlags = (UCHAR)Statement->AdditionalData2;
- //
- // Initialize the method structure.
- //
- RtlZeroMemory(&Method, sizeof(ACPI_METHOD_OBJECT));
- Method.IntegerWidthIs32 = Context->CurrentMethod->IntegerWidthIs32;
- Method.ArgumentCount = MethodFlags & METHOD_ARGUMENT_COUNT_MASK;
- Method.Serialized = FALSE;
- if ((MethodFlags & METHOD_SERIALIZED_FLAG) != 0) {
- Method.Serialized = TRUE;
- }
- Method.SyncLevel = (MethodFlags & METHOD_SYNC_LEVEL_MASK) >>
- METHOD_SYNC_LEVEL_SHIFT;
- Method.AmlCode = (PUCHAR)Context->AmlCode + Context->CurrentOffset;
- //
- // Additional Data stored the end offset, so the size is the end offset
- // minus the current offset.
- //
- Method.AmlCodeSize = Statement->AdditionalData - Context->CurrentOffset;
- Name = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Method (%s, 0x%02x)", Name, MethodFlags);
- }
- //
- // Create the object if execution is enabled.
- //
- if (Context->ExecuteStatements != FALSE) {
- MethodObject = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectMethod,
- Name,
- &Method,
- sizeof(ACPI_METHOD_OBJECT));
- if (MethodObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Advance the current offset to the end of the method, as it's not
- // being executed now, and complete the statement.
- //
- Context->CurrentOffset = Statement->AdditionalData;
- return STATUS_SUCCESS;
- //
- // If the context is printing but not executing, add to the indentation
- // level and delve into the function for execution.
- //
- } else {
- Context->IndentationLevel += 1;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(" {");
- }
- }
- }
- //
- // Wait for the end of the routine.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Decrease the indentation level and print the closing curly brace if
- // needed.
- //
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateMidStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a mid statement, which splits a string up.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PVOID Buffer;
- ULONGLONG BufferLength;
- ULONGLONG MidIndex;
- ULONGLONG MidLength;
- PACPI_OBJECT NewArgument;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Mid (");
- } else if ((Statement->ArgumentsAcquired == 0) ||
- (Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (Statement->ArgumentsAcquired == 0) {
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- if ((NewArgument->Type != AcpiObjectString) &&
- (NewArgument->Type != AcpiObjectBuffer)) {
- //
- // Perform an implicit conversion if needed.
- //
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectBuffer);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else if ((Statement->ArgumentsAcquired == 1) ||
- (Statement->ArgumentsAcquired == 2)) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- //
- // Parse the target argument.
- //
- } else {
- ASSERT(Statement->ArgumentsAcquired == 3);
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT((Statement->Argument[0]->Type == AcpiObjectString) ||
- (Statement->Argument[0]->Type == AcpiObjectBuffer));
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
- //
- // The Mid statement gets a portion of a string or buffer at an offset
- // (Index) with a length. If the mid statement tries to go over, the
- // resulting buffer is clipped with the original. If the offset is beyond
- // the end of the buffer, an empty buffer is created.
- //
- MidIndex = Statement->Argument[1]->U.Integer.Value;
- MidLength = Statement->Argument[2]->U.Integer.Value;
- BufferLength = 0;
- if (Statement->Argument[0]->Type == AcpiObjectString) {
- Buffer = Statement->Argument[0]->U.String.String;
- if (Buffer != NULL) {
- BufferLength = RtlStringLength(Buffer) + 1;
- }
- } else {
- Buffer = Statement->Argument[0]->U.Buffer.Buffer;
- BufferLength = Statement->Argument[0]->U.Buffer.Length;
- }
- //
- // Cap the mid statement from going over the buffer.
- //
- if (MidIndex >= BufferLength) {
- MidIndex = 0;
- MidLength = 0;
- }
- if (MidIndex + MidLength > BufferLength) {
- MidLength = BufferLength - MidIndex;
- }
- //
- // Create the mid buffer.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- Buffer + MidIndex,
- MidLength);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[3] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateMutexStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Mutex (creation) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR NameString;
- UCHAR SyncLevel;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- NameString = Statement->Argument[0]->U.String.String;
- SyncLevel = Statement->AdditionalData & MUTEX_FLAG_SYNC_LEVEL_MASK;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Mutex (%s, %d)", NameString, SyncLevel);
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- //
- // Create the mutex object.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectMutex,
- NameString,
- NULL,
- 0);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateNameStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Name statement, which creates a new named object
- in the namespace given an existing one.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NamedObject;
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT ObjectWithContents;
- KSTATUS Status;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Name (%s,",
- Statement->Argument[0]->U.String.String);
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipObjectAddReference(NewArgument);
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- //
- // The arguments should be all gathered.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- //
- // Create the new object without the stuff in it.
- //
- ObjectWithContents = Statement->Argument[1];
- NamedObject = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectUninitialized,
- Statement->Argument[0]->U.String.String,
- NULL,
- 0);
- if (NamedObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Put the stuff from the other object in this new named object.
- //
- Status = AcpipPerformStoreOperation(Context,
- ObjectWithContents,
- NamedObject);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Statement->Reduction = NamedObject;
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateNameStringStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a NameString statement, which evaluates to an
- object that is expected to exist in the namespace.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR Name;
- ACPI_UNRESOLVED_NAME_OBJECT UnresolvedName;
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- Name = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(Name);
- }
- //
- // Get the object if the interpreter is executing statements.
- //
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- Statement->Reduction = AcpipGetNamespaceObject(Name,
- Context->CurrentScope);
- //
- // If the object could not be found, then a name is being referenced
- // before it is defined. In certain situations this is alright, such as
- // the definition of a package object during a load operation. Create
- // an unresolved name object to remember to re-evaluate this name
- // when the object is referenced.
- //
- if (Statement->Reduction == NULL) {
- RtlZeroMemory(&UnresolvedName, sizeof(ACPI_UNRESOLVED_NAME_OBJECT));
- UnresolvedName.Name = Name;
- UnresolvedName.Scope = Context->CurrentScope;
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectUnresolvedName,
- NULL,
- &UnresolvedName,
- sizeof(ACPI_UNRESOLVED_NAME_OBJECT));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(" ?");
- }
- } else {
- AcpipObjectAddReference(Statement->Reduction);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateNoOpStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a No-Op statement, which is really quite easy since
- it doesn't do anything.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- STATUS_SUCCESS always.
- --*/
- {
- //
- // Finally, an easy one!
- //
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("NoOp");
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateNotifyStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Notify (the operating system) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- KSTATUS Status;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Notify (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first argument needs to be a Thermal Zone, Processor, or
- // Device.
- //
- if (Statement->ArgumentsAcquired == 0) {
- if ((NewArgument->Type != AcpiObjectProcessor) &&
- (NewArgument->Type != AcpiObjectThermalZone) &&
- (NewArgument->Type != AcpiObjectDevice)) {
- return STATUS_INVALID_PARAMETER;
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- //
- // The second argument needs to come out as an integer.
- //
- } else {
- ASSERT(Statement->ArgumentsAcquired == 1);
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT((Statement->Argument[0]->Type == AcpiObjectProcessor) ||
- (Statement->Argument[0]->Type == AcpiObjectThermalZone) ||
- (Statement->Argument[0]->Type == AcpiObjectDevice));
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- //
- // Pass the notification on to the rest of the system.
- //
- Status = AcpipNotifyOperatingSystem(
- Statement->Argument[0],
- Statement->Argument[1]->U.Integer.Value);
- return Status;
- }
- KSTATUS
- AcpipEvaluateNotStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates bitwise NOT operator.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- ULONGLONG ResultValue;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Not (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (Statement->ArgumentsAcquired == 0) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- //
- // Seems like so much build up just for this...
- //
- ResultValue = ~(Statement->Argument[0]->U.Integer.Value);
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- if (Statement->Argument[1] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[0]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateObjectTypeStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Object Type statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- PACPI_OBJECT Object;
- ULONGLONG ObjectType;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("ObjectType (");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (Statement->ArgumentsAcquired == 0) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipObjectAddReference(NewArgument);
- } else {
- if (NewArgument != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- Object = Statement->Argument[0];
- while (Object->Type == AcpiObjectAlias) {
- Object = Object->U.Alias.DestinationObject;
- }
- ObjectType = Object->Type;
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ObjectType,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateOperationRegionStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Operation Region statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR Name;
- PACPI_OBJECT NewArgument;
- ULONGLONG RegionLength;
- ULONGLONG RegionOffset;
- ACPI_OPERATION_REGION_SPACE RegionSpace;
- KSTATUS Status;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("OpRegion (%s, %x, ",
- Statement->Argument[0]->U.String.String,
- Statement->AdditionalData);
- } else if (Statement->ArgumentsAcquired == 1) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- ASSERT(Statement->Argument[2]->Type == AcpiObjectInteger);
- Name = Statement->Argument[0]->U.String.String;
- RegionOffset = Statement->Argument[1]->U.Integer.Value;
- RegionLength = Statement->Argument[2]->U.Integer.Value;
- RegionSpace = (UCHAR)Statement->AdditionalData;
- Status = AcpipCreateOperationRegion(Context,
- Name,
- RegionSpace,
- RegionOffset,
- RegionLength);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluatePackageStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Package or Variable Package statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ULONG BufferSize;
- PACPI_OBJECT NewArgument;
- if (Context->PreviousStatement == NULL) {
- Context->IndentationLevel += 1;
- if (Context->PrintStatements != FALSE) {
- if (Statement->Type == AmlStatementPackage) {
- RtlDebugPrint("Package (%d) {", Statement->AdditionalData2);
- AcpipPrintIndentedNewLine(Context);
- } else {
- ASSERT(Statement->Type == AmlStatementVariablePackage);
- RtlDebugPrint("VarPackage (");
- }
- }
- }
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument. This only occurs in a variable package when looking
- // for the package size.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- ASSERT(Statement->ArgumentsAcquired == 0);
- //
- // Fail if there is no argument there.
- //
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- //
- // Finish printing the header for the variable package.
- //
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(") {");
- AcpipPrintIndentedNewLine(Context);
- }
- //
- // Assuming the length isn't 0, wait for the first package object.
- //
- if (Context->CurrentOffset != Statement->AdditionalData) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- //
- // If not at the end, add this to the collection.
- //
- if ((Context->PrintStatements != FALSE) &&
- (Context->CurrentOffset != Statement->AdditionalData) &&
- (Context->PreviousStatement != NULL)) {
- RtlDebugPrint(", ");
- AcpipPrintIndentedNewLine(Context);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // If the object has never been created before, create it now.
- //
- if (Statement->Reduction == NULL) {
- BufferSize = Statement->AdditionalData2 * sizeof(PACPI_OBJECT);
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectPackage,
- NULL,
- NULL,
- BufferSize);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Additional data 2 now becomes a counter of the current
- // element.
- //
- Statement->AdditionalData2 = 0;
- }
- //
- // Add the object to the package/array.
- //
- if (Context->PreviousStatement != NULL) {
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipSetPackageObject(Statement->Reduction,
- Statement->AdditionalData2,
- Context->PreviousStatement->Reduction);
- Statement->AdditionalData2 += 1;
- }
- }
- if (Context->CurrentOffset == Statement->AdditionalData) {
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("}");
- }
- Context->IndentationLevel -= 1;
- return STATUS_SUCCESS;
- }
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- KSTATUS
- AcpipEvaluatePowerResourceStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Power Resource declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR DataPointer;
- PSTR Name;
- ACPI_POWER_RESOURCE_OBJECT PowerResource;
- PACPI_OBJECT PowerResourceObject;
- if (Context->PreviousStatement == NULL) {
- Statement->SavedScope = NULL;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- Name = Statement->Argument[0]->U.String.String;
- //
- // Get the system level and resource order.
- //
- DataPointer = Context->AmlCode + Statement->AdditionalData2;
- PowerResource.SystemLevel = *DataPointer;
- PowerResource.ResourceOrder = *(PUSHORT)(DataPointer + 1);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("PowerResource (%s, %d, %d) {",
- Name,
- PowerResource.SystemLevel,
- PowerResource.ResourceOrder);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Create the power resource object.
- //
- PowerResourceObject = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectPowerResource,
- Name,
- &PowerResource,
- sizeof(ACPI_POWER_RESOURCE_OBJECT));
- if (PowerResourceObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Make this device the current scope.
- //
- Statement->SavedScope = Context->CurrentScope;
- Context->CurrentScope = PowerResourceObject;
- Statement->Reduction = PowerResourceObject;
- }
- Context->IndentationLevel += 1;
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Pop this puppy off the stack.
- //
- Context->CurrentScope = Statement->SavedScope;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateProcessorStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Power Resource declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PUCHAR DataPointer;
- PSTR DeviceName;
- ACPI_PROCESSOR_OBJECT Processor;
- PACPI_OBJECT ProcessorObject;
- if (Context->PreviousStatement == NULL) {
- Statement->SavedScope = NULL;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- DeviceName = Statement->Argument[0]->U.String.String;
- //
- // Get the processor ID and processor block register information.
- //
- RtlZeroMemory(&Processor, sizeof(ACPI_PROCESSOR_OBJECT));
- DataPointer = Context->AmlCode + Statement->AdditionalData2;
- Processor.ProcessorId = *DataPointer;
- DataPointer += sizeof(BYTE);
- Processor.ProcessorBlockAddress = *(PULONG)DataPointer;
- DataPointer += sizeof(ULONG);
- Processor.ProcessorBlockLength = *DataPointer;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Processor (%s, %d, 0x%x, %d) {",
- DeviceName,
- Processor.ProcessorId,
- Processor.ProcessorBlockAddress,
- Processor.ProcessorBlockLength);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Create the processor object.
- //
- ProcessorObject = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectProcessor,
- DeviceName,
- &Processor,
- sizeof(ACPI_PROCESSOR_OBJECT));
- if (ProcessorObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Make this device the current scope.
- //
- Statement->SavedScope = Context->CurrentScope;
- Context->CurrentScope = ProcessorObject;
- Statement->Reduction = ProcessorObject;
- }
- Context->IndentationLevel += 1;
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Pop this puppy off the stack.
- //
- Context->CurrentScope = Statement->SavedScope;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateReferenceOfStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an "Reference Of" statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("RefOf (");
- } else {
- RtlDebugPrint(")");
- }
- }
- //
- // If there is no previous statement, wait for the argument to come in.
- //
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- //
- // Increment the reference count on the object.
- //
- } else {
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[0] = NULL;
- } else {
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- Statement->Argument[0] = Context->PreviousStatement->Reduction;
- AcpipObjectAddReference(Context->PreviousStatement->Reduction);
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements != FALSE) {
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectAlias,
- NULL,
- &(Statement->Argument[0]),
- sizeof(PACPI_OBJECT));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateReturnStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Return statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Return (");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- //
- // Increment the reference count on the object.
- //
- } else {
- if (Context->ExecuteStatements != FALSE) {
- if (Context->PreviousStatement->Reduction != NULL) {
- Statement->Argument[0] =
- Context->PreviousStatement->Reduction;
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- } else {
- Statement->Argument[0] = NULL;
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(")");
- }
- //
- // Return from the function.
- //
- if (Context->ExecuteStatements != FALSE) {
- //
- // If there was an old return value there (possibly from a nested
- // function call), release it.
- //
- if (Context->ReturnValue != NULL) {
- AcpipObjectReleaseReference(Context->ReturnValue);
- }
- Context->ReturnValue = Statement->Argument[0];
- AcpipObjectAddReference(Context->ReturnValue);
- AcpipPopExecutingStatements(Context, FALSE, FALSE);
- AcpipPopCurrentMethodContext(Context);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateScopeStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Device declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Object;
- PSTR ScopeName;
- if (Context->PreviousStatement == NULL) {
- Statement->SavedScope = NULL;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- ScopeName = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("Scope (%s) {", ScopeName);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Go find the object.
- //
- Object = AcpipGetNamespaceObject(ScopeName, Context->CurrentScope);
- //
- // Make this device the current scope.
- //
- Statement->SavedScope = Context->CurrentScope;
- Context->CurrentScope = Object;
- }
- Context->IndentationLevel += 1;
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Pop this puppy off the stack.
- //
- Context->CurrentScope = Statement->SavedScope;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- Statement->Reduction = NULL;
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateSizeOfStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a "Size Of" statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Object;
- ULONGLONG Size;
- //
- // Gather arguments.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("SizeOf (");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- } else {
- Statement->Argument[0] = NULL;
- if (Context->ExecuteStatements != FALSE) {
- Statement->Argument[0] = Context->PreviousStatement->Reduction;
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(")");
- }
- Object = NULL;
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- //
- // If the object is an alias, use the destination.
- //
- Object = Statement->Argument[0];
- while (Object->Type == AcpiObjectAlias) {
- Object = Statement->Argument[0]->U.Alias.DestinationObject;
- }
- Size = 0;
- switch (Object->Type) {
- case AcpiObjectString:
- if (Object->U.String.String != NULL) {
- Size = RtlStringLength(Object->U.String.String);
- }
- break;
- case AcpiObjectBuffer:
- Size = Object->U.Buffer.Length;
- break;
- case AcpiObjectPackage:
- Size = Object->U.Package.ElementCount;
- break;
- default:
- return STATUS_NOT_SUPPORTED;
- }
- //
- // Create the integer result.
- //
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &Size,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateStoreStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Store statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- KSTATUS Status;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Store (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- AcpipObjectAddReference(NewArgument);
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // All arguments have been acquired.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- //
- // Store the first argument into the second. The reduction of the statement
- // is the second operand.
- //
- Status = AcpipPerformStoreOperation(Context,
- Statement->Argument[0],
- Statement->Argument[1]);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Statement->Reduction = Statement->Argument[1];
- AcpipObjectAddReference(Statement->Reduction);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateSyncObjectStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Release (mutex), Reset (event), or Signal (event)
- statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NameString;
- PACPI_OBJECT NewArgument;
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- if (Statement->Type == AmlStatementRelease) {
- RtlDebugPrint("Release (");
- } else if (Statement->Type == AmlStatementSignal) {
- RtlDebugPrint("Signal (");
- } else {
- ASSERT(Statement->Type == AmlStatementReset);
- RtlDebugPrint("Reset (");
- }
- }
- }
- //
- // The argument for Release, Reset, and Signal is a "SuperName", which
- // is a SimpleName, DebugOp, or Type6Opcode. If this is the first time
- // through, try to parse a name string.
- //
- if (Context->PreviousStatement == NULL) {
- NameString = AcpipParseNameString(Context);
- if (NameString == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(NameString->U.String.String);
- }
- if (Context->ExecuteStatements != FALSE) {
- Statement->Argument[0] =
- AcpipGetNamespaceObject(NameString->U.String.String,
- Context->CurrentScope);
- if (Statement->Argument[0] == NULL) {
- return STATUS_NOT_FOUND;
- }
- } else {
- Statement->Argument[0] = NULL;
- }
- if (Statement->Argument[0] != NULL) {
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- Statement->ArgumentsAcquired += 1;
- AcpipObjectReleaseReference(NameString);
- //
- // Increment the reference count on the object.
- //
- } else {
- if (Context->ExecuteStatements != FALSE) {
- NewArgument = Context->PreviousStatement->Reduction;
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- AcpipObjectAddReference(NewArgument);
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(")");
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- if (Statement->Type == AmlStatementRelease) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectMutex);
- AcpipReleaseMutex(Context,
- Statement->Argument[0]->U.Mutex.OsMutex);
- } else if (Statement->Type == AmlStatementSignal) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
- AcpipSignalEvent(Statement->Argument[0]->U.Event.OsEvent);
- } else {
- ASSERT(Statement->Type == AmlStatementReset);
- ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
- AcpipResetEvent(Statement->Argument[0]->U.Event.OsEvent);
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateThermalZoneStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a Thermal Zone declaration statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PSTR Name;
- PACPI_OBJECT ThermalZoneObject;
- if (Context->PreviousStatement == NULL) {
- Statement->SavedScope = NULL;
- ASSERT(Statement->Argument[0]->Type == AcpiObjectString);
- Name = Statement->Argument[0]->U.String.String;
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint("ThermalZone (%s) {", Name);
- }
- if (Context->ExecuteStatements != FALSE) {
- //
- // Create the thermal zone object.
- //
- ThermalZoneObject = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectPowerResource,
- Name,
- NULL,
- 0);
- if (ThermalZoneObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Make this device the current scope.
- //
- Statement->SavedScope = Context->CurrentScope;
- Context->CurrentScope = ThermalZoneObject;
- Statement->Reduction = ThermalZoneObject;
- }
- Context->IndentationLevel += 1;
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // Pop this puppy off the stack.
- //
- Context->CurrentScope = Statement->SavedScope;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateToFormatStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates the "To" something and "From" something statements,
- including ToBCD, ToBuffer, ToDecimalString, ToHexString, ToInteger,
- ToString, ToUUID, Unicode, and FromBcd.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- ULONGLONG BcdValue;
- ULONG ByteCount;
- ULONG ByteIndex;
- PUCHAR BytePointer;
- ULONG ByteStringSize;
- ULONG Digit;
- ULONGLONG IntegerValue;
- PACPI_OBJECT NewArgument;
- ULONG Nibble;
- CHAR ResultString[MAX_DECIMAL_STRING_LENGTH];
- ULONGLONG ResultValue;
- PSTR String;
- ULONG StringSize;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- switch (Statement->Type) {
- case AmlStatementFromBcd:
- RtlDebugPrint("FromBCD (");
- break;
- case AmlStatementToBcd:
- RtlDebugPrint("ToBCD (");
- break;
- case AmlStatementToBuffer:
- RtlDebugPrint("ToBuffer (");
- break;
- case AmlStatementToDecimalString:
- RtlDebugPrint("ToDecimalString (");
- break;
- case AmlStatementToHexString:
- RtlDebugPrint("ToHexString (");
- break;
- case AmlStatementToInteger:
- RtlDebugPrint("ToInteger (");
- break;
- case AmlStatementToString:
- RtlDebugPrint("ToString (");
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- } else {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- if (Statement->ArgumentsAcquired == 0) {
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // If it's not an integer, buffer, or string, fail.
- //
- if ((NewArgument->Type != AcpiObjectInteger) &&
- (NewArgument->Type != AcpiObjectBuffer) &&
- (NewArgument->Type != AcpiObjectString)) {
- return STATUS_INVALID_PARAMETER;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (((Statement->Type == AmlStatementToBcd) ||
- (Statement->Type == AmlStatementFromBcd)) &&
- (NewArgument->Type != AcpiObjectInteger)) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- } else {
- ASSERT(Statement->ArgumentsAcquired == 1);
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
- //
- // Evaluate the result.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- switch (Statement->Type) {
- case AmlStatementFromBcd:
- //
- // Convert the BCD value to an integer.
- //
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- BcdValue = Statement->Argument[0]->U.Integer.Value;
- ResultValue = 0;
- for (Nibble = 0; Nibble < sizeof(ULONGLONG) * 2; Nibble += 1) {
- Digit = (BcdValue & 0xF000000000000000ULL) >> 60;
- ResultValue = (ResultValue * 10) + Digit;
- Digit = Digit << 4;
- }
- if (Context->CurrentMethod->IntegerWidthIs32 != FALSE) {
- ResultValue &= 0xFFFFFFFF;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- break;
- case AmlStatementToBcd:
- //
- // Convert the integer to a BCD value.
- //
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- IntegerValue = Statement->Argument[0]->U.Integer.Value;
- ResultValue = 0;
- for (Nibble = 0; Nibble < sizeof(ULONGLONG) * 2; Nibble += 1) {
- if (IntegerValue == 0) {
- break;
- }
- Digit = IntegerValue % 10;
- ResultValue = (ResultValue << 4) | Digit;
- IntegerValue = IntegerValue / 10;
- }
- if (IntegerValue != 0) {
- return STATUS_CONVERSION_FAILED;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- break;
- case AmlStatementToBuffer:
- Statement->Reduction = AcpipConvertObjectType(Context,
- Statement->Argument[0],
- AcpiObjectBuffer);
- break;
- case AmlStatementToDecimalString:
- //
- // If the result is already a string, no action is performed.
- //
- if (Statement->Argument[0]->Type == AcpiObjectString) {
- Statement->Reduction = Statement->Argument[0];
- AcpipObjectAddReference(Statement->Reduction);
- //
- // Convert the integer to a string.
- //
- } else if (Statement->Argument[0]->Type == AcpiObjectInteger) {
- RtlPrintToString(ResultString,
- MAX_DECIMAL_STRING_LENGTH,
- CharacterEncodingAscii,
- "%I64d",
- Statement->Argument[0]->U.Integer.Value);
- Statement->Reduction = AcpipCreateNamespaceObject(
- Context,
- AcpiObjectString,
- NULL,
- ResultString,
- MAX_DECIMAL_STRING_LENGTH);
- //
- // Convert the buffer to a comma delimited string of decimal integers.
- //
- } else if (Statement->Argument[0]->Type == AcpiObjectBuffer) {
- //
- // Create the result string with buffer first. The size is up to
- // three decimal digits, plus one comma per byte, minus the comma
- // at the end, plus the null delimiter.
- //
- StringSize = Statement->Argument[0]->U.Buffer.Length * 4;
- if (StringSize == 0) {
- StringSize = 1;
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectString,
- NULL,
- NULL,
- StringSize);
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Print out each byte individually, except the last one.
- //
- String = Statement->Reduction->U.String.String;
- BytePointer = Statement->Argument[0]->U.Buffer.Buffer;
- ByteCount = Statement->Argument[0]->U.Buffer.Length;
- for (ByteIndex = 0; ByteIndex < ByteCount - 1; ByteIndex += 1) {
- ByteStringSize = RtlPrintToString(String,
- StringSize,
- CharacterEncodingAscii,
- "%d,",
- *BytePointer);
- if (ByteStringSize > StringSize) {
- ByteStringSize = StringSize;
- }
- BytePointer += 1;
- String += ByteStringSize;
- StringSize -= ByteStringSize;
- }
- //
- // Do the last one without a comma.
- //
- RtlPrintToString(String,
- StringSize,
- CharacterEncodingAscii,
- "%d",
- *BytePointer);
- } else {
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- break;
- case AmlStatementToHexString:
- //
- // If the result is already a string, no action is performed.
- //
- if (Statement->Argument[0]->Type == AcpiObjectString) {
- Statement->Reduction = Statement->Argument[0];
- AcpipObjectAddReference(Statement->Reduction);
- //
- // Convert the integer or buffer to a string.
- //
- } else {
- Statement->Reduction = AcpipConvertObjectType(
- Context,
- Statement->Argument[0],
- AcpiObjectString);
- }
- break;
- case AmlStatementToInteger:
- if (Statement->Argument[0]->Type == AcpiObjectInteger) {
- Statement->Reduction = Statement->Argument[0];
- AcpipObjectAddReference(Statement->Reduction);
- } else if (Statement->Argument[0]->Type == AcpiObjectBuffer) {
- Statement->Reduction = AcpipConvertObjectType(
- Context,
- Statement->Argument[0],
- AcpiObjectInteger);
- } else if (Statement->Argument[0]->Type != AcpiObjectString) {
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- String = Statement->Argument[0]->U.String.String;
- if (String == NULL) {
- break;
- }
- //
- // Parse the string as a decimal or a hex string depending on whether
- // there is an 0x prepending or not.
- //
- IntegerValue = 0;
- if ((*String == '0') && (*(String + 1) == 'x')) {
- while (((*String >= '0') && (*String <= '9')) ||
- ((*String >= 'a') && (*String <= 'f')) ||
- ((*String >= 'A') && (*String <= 'F'))) {
- if ((*String >= '0') && (*String <= '9')) {
- Digit = *String - '0';
- } else if (((*String >= 'a') && (*String <= 'f'))) {
- Digit = *String - 'a';
- } else {
- ASSERT((*String >= 'A') && (*String <= 'F'));
- Digit = *String - 'A';
- }
- IntegerValue = (IntegerValue << 4) | Digit;
- String += 1;
- }
- //
- // Parse it as a decimal string.
- //
- } else {
- while ((*String >= '0') && (*String <= '9')) {
- Digit = *String - '0';
- IntegerValue = (IntegerValue * 10) + Digit;
- String += 1;
- }
- }
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &IntegerValue,
- sizeof(ULONGLONG));
- break;
- case AmlStatementToString:
- Statement->Reduction = AcpipConvertObjectType(Context,
- Statement->Argument[0],
- AcpiObjectString);
- break;
- default:
- ASSERT(FALSE);
- return STATUS_NOT_SUPPORTED;
- }
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- //
- // Store the result in the target if supplied.
- //
- if (Statement->Argument[2] != NULL) {
- return AcpipPerformStoreOperation(Context,
- Statement->Reduction,
- Statement->Argument[2]);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateUnloadStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Unload statement, which unloads a previously
- loaded definition block.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT DdbHandle;
- PACPI_OBJECT NewArgument;
- //
- // If not all arguments are acquired, evaluate the previous statement to get
- // the next argument.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Unload (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(")");
- }
- }
- if (Context->PreviousStatement == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- ASSERT(Statement->ArgumentsAcquired <= 1);
- if (Context->PreviousStatement->Reduction != NULL) {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements == FALSE) {
- return STATUS_SUCCESS;
- }
- DdbHandle = Statement->Argument[0];
- ASSERT(DdbHandle != NULL);
- AcpiUnloadDefinitionBlock(DdbHandle);
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateWaitStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates an Wait (for Event) statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT IntegerObject;
- PACPI_OBJECT NameString;
- PACPI_OBJECT NewArgument;
- ULONGLONG ResultValue;
- ULONG TimeoutValue;
- //
- // Gather arguments if needed.
- //
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("Wait (");
- } else if (Statement->ArgumentsAcquired == 0) {
- RtlDebugPrint(", ");
- } else {
- RtlDebugPrint(")");
- }
- }
- //
- // The argument for Wait is a "SuperName", which is a SimpleName,
- // DebugOp, or Type6Opcode. If this is the first time through, try to
- // parse a name string.
- //
- if (Context->PreviousStatement == NULL) {
- NameString = AcpipParseNameString(Context);
- if (NameString == NULL) {
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- if (Context->PrintStatements != FALSE) {
- RtlDebugPrint(NameString->U.String.String);
- }
- if (Context->ExecuteStatements != FALSE) {
- Statement->Argument[0] =
- AcpipGetNamespaceObject(NameString->U.String.String,
- Context->CurrentScope);
- if (Statement->Argument[0] == NULL) {
- return STATUS_NOT_FOUND;
- }
- AcpipObjectAddReference(Statement->Argument[0]);
- }
- Statement->ArgumentsAcquired += 1;
- AcpipObjectReleaseReference(NameString);
- //
- // Get the argument from the previous statement.
- //
- } else {
- if (Context->ExecuteStatements != FALSE) {
- NewArgument = Context->PreviousStatement->Reduction;
- if (NewArgument == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // The first argument is the Event object.
- //
- if (Statement->ArgumentsAcquired == 0) {
- if (NewArgument->Type != AcpiObjectEvent) {
- return STATUS_INVALID_PARAMETER;
- }
- Statement->Argument[Statement->ArgumentsAcquired] =
- NewArgument;
- AcpipObjectAddReference(NewArgument);
- //
- // The second argument should evaluate to an integer specifying
- // the number of milliseconds to wait for the given event.
- //
- } else {
- if (NewArgument->Type == AcpiObjectInteger) {
- Statement->Argument[Statement->ArgumentsAcquired] =
- NewArgument;
- AcpipObjectAddReference(NewArgument);
- } else {
- IntegerObject = AcpipConvertObjectType(
- Context,
- NewArgument,
- AcpiObjectInteger);
- if (IntegerObject == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- Statement->Argument[Statement->ArgumentsAcquired] =
- IntegerObject;
- }
- }
- }
- Statement->ArgumentsAcquired += 1;
- }
- }
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- Statement->Reduction = NULL;
- if (Context->ExecuteStatements != FALSE) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectEvent);
- ASSERT(Statement->Argument[1]->Type == AcpiObjectInteger);
- TimeoutValue = Statement->Argument[1]->U.Integer.Value;
- ResultValue = AcpipWaitForEvent(Statement->Argument[0]->U.Event.OsEvent,
- TimeoutValue);
- Statement->Reduction = AcpipCreateNamespaceObject(Context,
- AcpiObjectInteger,
- NULL,
- &ResultValue,
- sizeof(ULONGLONG));
- if (Statement->Reduction == NULL) {
- return STATUS_UNSUCCESSFUL;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateWhileModifierStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates one of the statements that modifies a While loop,
- a Break or Continue.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- BOOL Continue;
- if (Context->PrintStatements != FALSE) {
- if (Statement->Type == AmlStatementBreak) {
- RtlDebugPrint("Break");
- } else {
- ASSERT(Statement->Type == AmlStatementContinue);
- RtlDebugPrint("Continue");
- }
- }
- if (Context->ExecuteStatements != FALSE) {
- if (Statement->Type == AmlStatementContinue) {
- Continue = TRUE;
- } else {
- Continue = FALSE;
- }
- AcpipPopExecutingStatements(Context, TRUE, Continue);
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- AcpipEvaluateWhileStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine evaluates a While statement.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT NewArgument;
- if (Statement->ArgumentsNeeded != Statement->ArgumentsAcquired) {
- //
- // Print out the piece of the statement depending on the number of
- // arguments acquired.
- //
- if (Context->PrintStatements != FALSE) {
- if (Context->PreviousStatement == NULL) {
- RtlDebugPrint("While (");
- } else {
- ASSERT(Statement->ArgumentsAcquired == 0);
- RtlDebugPrint(") {");
- }
- }
- if (Context->PreviousStatement == NULL) {
- Context->IndentationLevel += 1;
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- //
- // If not executing, then assume the argument would be there but don't
- // try to dink with it.
- //
- if (Context->ExecuteStatements == FALSE) {
- Statement->Argument[Statement->ArgumentsAcquired] = NULL;
- Statement->ArgumentsAcquired += 1;
- } else {
- NewArgument = Context->PreviousStatement->Reduction;
- //
- // Fail if there is no argument there.
- //
- if (Context->PreviousStatement->Reduction == NULL) {
- return STATUS_ARGUMENT_EXPECTED;
- }
- //
- // Perform an implicit conversion if needed.
- //
- if (NewArgument->Type != AcpiObjectInteger) {
- NewArgument = AcpipConvertObjectType(Context,
- NewArgument,
- AcpiObjectInteger);
- if (NewArgument == NULL) {
- return STATUS_CONVERSION_FAILED;
- }
- //
- // The object is fine, take ownership of it.
- //
- } else {
- AcpipObjectAddReference(NewArgument);
- }
- Statement->Argument[Statement->ArgumentsAcquired] = NewArgument;
- Statement->ArgumentsAcquired += 1;
- }
- //
- // Evaluate the predicate.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- if (Context->ExecuteStatements != FALSE) {
- ASSERT(Statement->Argument[0]->Type == AcpiObjectInteger);
- //
- // Evaluate the while statement by skipping the package length if
- // it's zero, and completing the while statement.
- //
- if (Statement->Argument[0]->U.Integer.Value == 0) {
- Context->CurrentOffset = Statement->AdditionalData;
- Context->IndentationLevel -= 1;
- if (Context->PrintStatements != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- RtlDebugPrint("}");
- }
- return STATUS_SUCCESS;
- }
- }
- }
- //
- // If execution is not done with the scope, keep this statement on the
- // stack.
- //
- if (Context->CurrentOffset < Statement->AdditionalData) {
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- ASSERT(Context->IndentationLevel != 0);
- //
- // Move the offset back to the predicate, release the argument to pretend
- // like the predicate was never seen before, and start again.
- //
- if (Context->ExecuteStatements != FALSE) {
- Context->CurrentOffset = Statement->AdditionalData2;
- AcpipObjectReleaseReference(Statement->Argument[0]);
- Statement->Argument[0] = NULL;
- Statement->ArgumentsAcquired = 0;
- AcpipPrintIndentedNewLine(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- AcpipPrintIndentedNewLine(Context);
- return STATUS_SUCCESS;
- }
- PACPI_OBJECT
- AcpipConvertObjectType (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object,
- ACPI_OBJECT_TYPE NewType
- )
- /*++
- Routine Description:
- This routine performs a conversion between supported ACPI object types.
- Arguments:
- Context - Supplies a pointer to the current execution context.
- Object - Supplies a pointer to the object to convert.
- NewType - Supplies the type to convert the given object to.
- Return Value:
- Returns a pointer to a new object (unlinked to the namespace) of the
- requested type. The caller is responsible for this memory once its returned.
- NULL on failure.
- --*/
- {
- PACPI_OBJECT NewObject;
- PACPI_OBJECT ReadResult;
- KSTATUS Status;
- NewObject = NULL;
- ReadResult = NULL;
- //
- // Get the real object being pointed to here.
- //
- while (Object->Type == AcpiObjectAlias) {
- Object = Object->U.Alias.DestinationObject;
- }
- //
- // Attempting to convert from a Field Unit to something results in a read
- // from the field.
- //
- if (Object->Type == AcpiObjectFieldUnit) {
- Status = AcpipReadFromField(Context, Object, &ReadResult);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- if (ReadResult->Type == NewType) {
- return ReadResult;
- }
- //
- // The new thing to convert is the result of the field read.
- //
- Object = ReadResult;
- } else if (Object->Type == AcpiObjectBufferField) {
- Status = AcpipReadFromBufferField(Context, Object, &ReadResult);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- if (ReadResult->Type == NewType) {
- return ReadResult;
- }
- //
- // The new thing to convert is the result of the buffer field read.
- //
- Object = ReadResult;
- }
- switch (NewType) {
- case AcpiObjectInteger:
- NewObject = AcpipConvertObjectTypeToInteger(Context, Object);
- break;
- case AcpiObjectString:
- NewObject = AcpipConvertObjectTypeToString(Context, Object);
- break;
- case AcpiObjectBuffer:
- NewObject = AcpipConvertObjectTypeToBuffer(Context, Object);
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- //
- // Release the intermediate read result object.
- //
- if (ReadResult != NULL) {
- AcpipObjectReleaseReference(ReadResult);
- }
- return NewObject;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- PACPI_OBJECT
- AcpipConvertObjectTypeToInteger (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- )
- /*++
- Routine Description:
- This routine converts the given object into an Integer object.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- Object - Supplies a pointer to the object to convert.
- Return Value:
- Returns a pointer to a new object (unlinked to the namespace) of the
- requested type. The caller is responsible for this memory once its returned.
- NULL on failure.
- --*/
- {
- ULONG CopySize;
- UCHAR Digit;
- ULONGLONG IntegerValue;
- PACPI_OBJECT NewObject;
- PSTR String;
- NewObject = NULL;
- IntegerValue = 0;
- switch (Object->Type) {
- case AcpiObjectInteger:
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectInteger,
- NULL,
- &(Object->U.Integer.Value),
- sizeof(ULONGLONG));
- break;
- //
- // Convert from a buffer to an integer by basically just casting.
- //
- case AcpiObjectBuffer:
- CopySize = Object->U.Buffer.Length;
- if (CopySize > sizeof(ULONGLONG)) {
- CopySize = sizeof(ULONGLONG);
- }
- RtlCopyMemory(&IntegerValue, Object->U.Buffer.Buffer, CopySize);
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectInteger,
- NULL,
- &IntegerValue,
- sizeof(ULONGLONG));
- break;
- //
- // To convert from a string to an integer, parse hex digits 0-9, A-F
- // (and a-f) until a non-digit is found. A leading 0x is not allowed.
- //
- case AcpiObjectString:
- String = Object->U.String.String;
- if (String == NULL) {
- break;
- }
- while (((*String >= '0') && (*String <= '9')) ||
- ((*String >= 'a') && (*String <= 'f')) ||
- ((*String >= 'A') && (*String <= 'F'))) {
- if ((*String >= '0') && (*String <= '9')) {
- Digit = *String - '0';
- } else if (((*String >= 'a') && (*String <= 'f'))) {
- Digit = *String - 'a' + 10;
- } else {
- ASSERT((*String >= 'A') && (*String <= 'F'));
- Digit = *String - 'A' + 10;
- }
- IntegerValue = (IntegerValue << 4) | Digit;
- String += 1;
- }
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectInteger,
- NULL,
- &IntegerValue,
- sizeof(ULONGLONG));
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return NewObject;
- }
- PACPI_OBJECT
- AcpipConvertObjectTypeToString (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- )
- /*++
- Routine Description:
- This routine converts the given object into a String object.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Object - Supplies a pointer to the object to convert.
- Return Value:
- Returns a pointer to a new object (unlinked to the namespace) of the
- requested type. The caller is responsible for this memory once its returned.
- NULL on failure.
- --*/
- {
- ULONG BufferLength;
- ULONG ByteIndex;
- PUCHAR CurrentBufferPosition;
- PSTR CurrentPosition;
- PACPI_OBJECT NewObject;
- ULONG NewStringLength;
- switch (Object->Type) {
- //
- // To convert an integer to a string, create an 8 or 16 byte string buffer
- // depending on whether integers are 32 or 64 bits, and then write the hex
- // value in.
- //
- case AcpiObjectInteger:
- NewStringLength = 16;
- if ((Context->CurrentMethod != NULL) &&
- (Context->CurrentMethod->IntegerWidthIs32 != FALSE)) {
- NewStringLength = 8;
- }
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectString,
- NULL,
- NULL,
- NewStringLength);
- if (NewObject == NULL) {
- return NULL;
- }
- RtlPrintToString(NewObject->U.String.String,
- NewStringLength,
- CharacterEncodingAscii,
- "%I64x",
- Object->U.Integer.Value);
- break;
- case AcpiObjectString:
- NewStringLength = RtlStringLength(Object->U.String.String) + 1;
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectString,
- NULL,
- Object->U.String.String,
- NewStringLength);
- break;
- //
- // To convert from a buffer to a string, print out all characters as two
- // digit hex values, separated by spaces.
- //
- case AcpiObjectBuffer:
- //
- // The new string length is 3 times the number of bytes there are (two
- // digits plus one space for each character), minus one since the last
- // character doesn't get a space, plus one for the null terminator.
- //
- NewStringLength = (Object->U.Buffer.Length * 3);
- NewObject = AcpipCreateNamespaceObject(NULL,
- AcpiObjectString,
- NULL,
- NULL,
- NewStringLength);
- if (NewObject == NULL) {
- return NULL;
- }
- BufferLength = Object->U.Buffer.Length;
- if (BufferLength == 0) {
- NewObject->U.String.String[0] = '\0';
- } else {
- CurrentPosition = NewObject->U.String.String;
- CurrentBufferPosition = Object->U.Buffer.Buffer;
- //
- // Print out all except the last one.
- //
- for (ByteIndex = 0; ByteIndex < BufferLength - 1; ByteIndex += 1) {
- RtlPrintToString(CurrentPosition,
- NewStringLength,
- CharacterEncodingAscii,
- "%02x ",
- *CurrentBufferPosition);
- CurrentPosition += 3;
- NewStringLength -= 3;
- CurrentBufferPosition += 1;
- }
- //
- // Do the last one without a space.
- //
- RtlPrintToString(CurrentPosition,
- NewStringLength,
- CharacterEncodingAscii,
- "%02x",
- *CurrentBufferPosition);
- }
- break;
- default:
- ASSERT(FALSE);
- return NULL;
- }
- return NewObject;
- }
- PACPI_OBJECT
- AcpipConvertObjectTypeToBuffer (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Object
- )
- /*++
- Routine Description:
- This routine converts the given object into a Buffer object.
- Arguments:
- Context - Supplies a pointer to the current AML execution context.
- Object - Supplies a pointer to the object to convert.
- Return Value:
- Returns a pointer to a new object (unlinked to the namespace) of the
- requested type. The caller is responsible for this memory once its returned.
- NULL on failure.
- --*/
- {
- ULONG BufferSize;
- PACPI_OBJECT NewObject;
- switch (Object->Type) {
- //
- // Converting from an integer to a buffer is basically a matter of casting.
- //
- case AcpiObjectInteger:
- BufferSize = sizeof(ULONGLONG);
- if ((Context->CurrentMethod != NULL) &&
- (Context->CurrentMethod->IntegerWidthIs32 != FALSE)) {
- BufferSize = sizeof(ULONG);
- }
- NewObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- &(Object->U.Integer.Value),
- BufferSize);
- break;
- case AcpiObjectString:
- BufferSize = RtlStringLength(Object->U.String.String);
- if (BufferSize != 0) {
- BufferSize += 1;
- }
- NewObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- Object->U.String.String,
- BufferSize);
- break;
- case AcpiObjectBuffer:
- BufferSize = Object->U.Buffer.Length;
- NewObject = AcpipCreateNamespaceObject(Context,
- AcpiObjectBuffer,
- NULL,
- Object->U.Buffer.Buffer,
- BufferSize);
- break;
- default:
- ASSERT(FALSE);
- return NULL;
- }
- return NewObject;
- }
- BOOL
- AcpipEvaluateMatchComparison (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT PackageElement,
- PACPI_OBJECT Operand1,
- ACPI_MATCH_OPERATOR Operator1,
- PACPI_OBJECT Operand2,
- ACPI_MATCH_OPERATOR Operator2
- )
- /*++
- Routine Description:
- This routine performs a comparison of two or more objects as defined in the
- rules for a Match statement.
- Arguments:
- Context - Supplies a pointer to the execution context.
- PackageElement - Supplies a pointer to the element indexed from the
- Match package being iterated over.
- Operand1 - Supplies a pointer to the first value to compare against. This
- must be an integer.
- Operator1 - Supplies the operator to use to compare the package element to
- Operand1.
- Operand2 - Supplies a pointer to the second value to compare against. This
- must be an integer.
- Operator2 - Supplies the operator to use to compare the package element to
- Operand2.
- Return Value:
- TRUE if the condition matches the given operators against the given
- operands.
- FALSE if the comparison does not match.
- --*/
- {
- ULONGLONG Operand;
- ULONGLONG PackageValue;
- BOOL Result;
- ASSERT((Operator1 < MatchOperatorCount) &&
- (Operator2 < MatchOperatorCount));
- ASSERT((Operator1 == MatchOperatorTrue) ||
- (Operand1->Type == AcpiObjectInteger));
- ASSERT((Operator2 == MatchOperatorTrue) ||
- (Operand2->Type == AcpiObjectInteger));
- //
- // The ACPI spec says to skip uninitialized elements.
- //
- if ((PackageElement == NULL) ||
- (PackageElement->Type == AcpiObjectUninitialized)) {
- return FALSE;
- }
- //
- // Get an object that can be evaluated as an integer. If the conversion
- // fails, the ACPI spec says to quietly skip this value.
- //
- if (PackageElement->Type == AcpiObjectInteger) {
- PackageValue = PackageElement->U.Integer.Value;
- } else {
- PackageElement = AcpipConvertObjectType(Context,
- PackageElement,
- AcpiObjectInteger);
- if (PackageElement == NULL) {
- return FALSE;
- }
- PackageValue = PackageElement->U.Integer.Value;
- AcpipObjectReleaseReference(PackageElement);
- }
- //
- // Perform the comparison on object 1.
- //
- Result = FALSE;
- Operand = 0;
- if (Operator1 != MatchOperatorTrue) {
- Operand = Operand1->U.Integer.Value;
- }
- switch (Operator1) {
- case MatchOperatorTrue:
- Result = TRUE;
- break;
- case MatchOperatorEqual:
- if (PackageValue == Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorLessThanOrEqualTo:
- if (PackageValue <= Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorLessThan:
- if (PackageValue < Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorGreaterThanOrEqualTo:
- if (PackageValue >= Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorGreaterThan:
- if (PackageValue > Operand) {
- Result = TRUE;
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- //
- // The function is only a match if both return TRUE. If this returned FALSE,
- // don't bother evaluating the other side.
- //
- if (Result == FALSE) {
- return Result;
- }
- //
- // Evalute operand 2.
- //
- Result = FALSE;
- if (Operator2 != MatchOperatorTrue) {
- Operand = Operand2->U.Integer.Value;
- }
- switch (Operator2) {
- case MatchOperatorTrue:
- Result = TRUE;
- break;
- case MatchOperatorEqual:
- if (PackageValue == Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorLessThanOrEqualTo:
- if (PackageValue <= Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorLessThan:
- if (PackageValue < Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorGreaterThanOrEqualTo:
- if (PackageValue >= Operand) {
- Result = TRUE;
- }
- break;
- case MatchOperatorGreaterThan:
- if (PackageValue > Operand) {
- Result = TRUE;
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return Result;
- }
|