From 5437485bdb98c4b00f15969e013c454426e9c862 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Thu, 16 Feb 2012 00:24:10 +0000 Subject: Import ACPICA 20120215. --- source/common/adfile.c | 333 +++ source/common/adisasm.c | 1156 ++++++++ source/common/adwalk.c | 1004 +++++++ source/common/dmextern.c | 672 +++++ source/common/dmrestag.c | 1045 ++++++++ source/common/dmtable.c | 1204 +++++++++ source/common/dmtbdump.c | 2146 +++++++++++++++ source/common/dmtbinfo.c | 2065 ++++++++++++++ source/common/getopt.c | 173 ++ source/compiler/Makefile | 329 +++ source/compiler/aslanalyze.c | 569 ++++ source/compiler/aslbtypes.c | 525 ++++ source/compiler/aslcodegen.c | 593 ++++ source/compiler/aslcompile.c | 845 ++++++ source/compiler/aslcompiler.h | 1091 ++++++++ source/compiler/aslcompiler.l | 1301 +++++++++ source/compiler/aslcompiler.y | 3571 +++++++++++++++++++++++++ source/compiler/asldefine.h | 177 ++ source/compiler/aslerror.c | 647 +++++ source/compiler/aslfiles.c | 962 +++++++ source/compiler/aslfold.c | 491 ++++ source/compiler/aslglobal.h | 226 ++ source/compiler/asllength.c | 458 ++++ source/compiler/asllisting.c | 1542 +++++++++++ source/compiler/aslload.c | 898 +++++++ source/compiler/asllookup.c | 1401 ++++++++++ source/compiler/aslmain.c | 983 +++++++ source/compiler/aslmap.c | 456 ++++ source/compiler/aslmessages.h | 391 +++ source/compiler/aslopcodes.c | 814 ++++++ source/compiler/asloperands.c | 1184 ++++++++ source/compiler/aslopt.c | 796 ++++++ source/compiler/aslpredef.c | 839 ++++++ source/compiler/aslresource.c | 1066 ++++++++ source/compiler/aslrestype1.c | 645 +++++ source/compiler/aslrestype1i.c | 672 +++++ source/compiler/aslrestype2.c | 461 ++++ source/compiler/aslrestype2d.c | 742 +++++ source/compiler/aslrestype2e.c | 573 ++++ source/compiler/aslrestype2q.c | 721 +++++ source/compiler/aslrestype2s.c | 1187 ++++++++ source/compiler/aslrestype2w.c | 702 +++++ source/compiler/aslstartup.c | 513 ++++ source/compiler/aslstubs.c | 253 ++ source/compiler/asltransform.c | 782 ++++++ source/compiler/asltree.c | 1202 +++++++++ source/compiler/asltypes.h | 236 ++ source/compiler/aslutils.c | 1068 ++++++++ source/compiler/asluuid.c | 216 ++ source/compiler/aslwalks.c | 1237 +++++++++ source/compiler/dtcompile.c | 589 ++++ source/compiler/dtcompiler.h | 513 ++++ source/compiler/dtexpress.c | 408 +++ source/compiler/dtfield.c | 561 ++++ source/compiler/dtio.c | 963 +++++++ source/compiler/dtparser.l | 133 + source/compiler/dtparser.y | 273 ++ source/compiler/dtsubtable.c | 375 +++ source/compiler/dttable.c | 2020 ++++++++++++++ source/compiler/dttemplate.c | 374 +++ source/compiler/dttemplate.h | 897 +++++++ source/compiler/dtutils.c | 882 ++++++ source/compiler/readme.txt | 85 + source/components/debugger/dbcmds.c | 1084 ++++++++ source/components/debugger/dbdisply.c | 1057 ++++++++ source/components/debugger/dbexec.c | 1105 ++++++++ source/components/debugger/dbfileio.c | 578 ++++ source/components/debugger/dbhistry.c | 220 ++ source/components/debugger/dbinput.c | 1091 ++++++++ source/components/debugger/dbmethod.c | 525 ++++ source/components/debugger/dbnames.c | 934 +++++++ source/components/debugger/dbstats.c | 549 ++++ source/components/debugger/dbutils.c | 526 ++++ source/components/debugger/dbxface.c | 536 ++++ source/components/disassembler/dmbuffer.c | 542 ++++ source/components/disassembler/dmnames.c | 453 ++++ source/components/disassembler/dmobject.c | 589 ++++ source/components/disassembler/dmopcode.c | 607 +++++ source/components/disassembler/dmresrc.c | 434 +++ source/components/disassembler/dmresrcl.c | 1052 ++++++++ source/components/disassembler/dmresrcl2.c | 700 +++++ source/components/disassembler/dmresrcs.c | 358 +++ source/components/disassembler/dmutils.c | 321 +++ source/components/disassembler/dmwalk.c | 935 +++++++ source/components/dispatcher/dsargs.c | 438 +++ source/components/dispatcher/dscontrol.c | 424 +++ source/components/dispatcher/dsfield.c | 748 ++++++ source/components/dispatcher/dsinit.c | 238 ++ source/components/dispatcher/dsmethod.c | 726 +++++ source/components/dispatcher/dsmthdat.c | 772 ++++++ source/components/dispatcher/dsobject.c | 867 ++++++ source/components/dispatcher/dsopcode.c | 809 ++++++ source/components/dispatcher/dsutils.c | 937 +++++++ source/components/dispatcher/dswexec.c | 797 ++++++ source/components/dispatcher/dswload.c | 551 ++++ source/components/dispatcher/dswload2.c | 747 ++++++ source/components/dispatcher/dswscope.c | 239 ++ source/components/dispatcher/dswstate.c | 846 ++++++ source/components/events/evevent.c | 336 +++ source/components/events/evglock.c | 377 +++ source/components/events/evgpe.c | 831 ++++++ source/components/events/evgpeblk.c | 550 ++++ source/components/events/evgpeinit.c | 462 ++++ source/components/events/evgpeutil.c | 425 +++ source/components/events/evmisc.c | 377 +++ source/components/events/evregion.c | 1366 ++++++++++ source/components/events/evrgnini.c | 732 +++++ source/components/events/evsci.c | 209 ++ source/components/events/evxface.c | 979 +++++++ source/components/events/evxfevnt.c | 381 +++ source/components/events/evxfgpe.c | 903 +++++++ source/components/events/evxfregn.c | 313 +++ source/components/executer/exconfig.c | 688 +++++ source/components/executer/exconvrt.c | 754 ++++++ source/components/executer/excreate.c | 574 ++++ source/components/executer/exdebug.c | 278 ++ source/components/executer/exdump.c | 1124 ++++++++ source/components/executer/exfield.c | 406 +++ source/components/executer/exfldio.c | 1055 ++++++++ source/components/executer/exmisc.c | 800 ++++++ source/components/executer/exmutex.c | 554 ++++ source/components/executer/exnames.c | 488 ++++ source/components/executer/exoparg1.c | 1111 ++++++++ source/components/executer/exoparg2.c | 642 +++++ source/components/executer/exoparg3.c | 304 +++ source/components/executer/exoparg6.c | 365 +++ source/components/executer/exprep.c | 648 +++++ source/components/executer/exregion.c | 565 ++++ source/components/executer/exresnte.c | 302 +++ source/components/executer/exresolv.c | 580 ++++ source/components/executer/exresop.c | 738 +++++ source/components/executer/exstore.c | 531 ++++ source/components/executer/exstoren.c | 314 +++ source/components/executer/exstorob.c | 244 ++ source/components/executer/exsystem.c | 355 +++ source/components/executer/exutils.c | 532 ++++ source/components/hardware/hwacpi.c | 209 ++ source/components/hardware/hwesleep.c | 263 ++ source/components/hardware/hwgpe.c | 543 ++++ source/components/hardware/hwpci.c | 459 ++++ source/components/hardware/hwregs.c | 741 +++++ source/components/hardware/hwsleep.c | 384 +++ source/components/hardware/hwtimer.c | 218 ++ source/components/hardware/hwvalid.c | 368 +++ source/components/hardware/hwxface.c | 617 +++++ source/components/hardware/hwxfsleep.c | 474 ++++ source/components/namespace/nsaccess.c | 700 +++++ source/components/namespace/nsalloc.c | 588 ++++ source/components/namespace/nsdump.c | 769 ++++++ source/components/namespace/nsdumpdv.c | 161 ++ source/components/namespace/nseval.c | 485 ++++ source/components/namespace/nsinit.c | 665 +++++ source/components/namespace/nsload.c | 356 +++ source/components/namespace/nsnames.c | 303 +++ source/components/namespace/nsobject.c | 505 ++++ source/components/namespace/nsparse.c | 225 ++ source/components/namespace/nspredef.c | 1243 +++++++++ source/components/namespace/nsrepair.c | 802 ++++++ source/components/namespace/nsrepair2.c | 827 ++++++ source/components/namespace/nssearch.c | 424 +++ source/components/namespace/nsutils.c | 875 ++++++ source/components/namespace/nswalk.c | 386 +++ source/components/namespace/nsxfeval.c | 960 +++++++ source/components/namespace/nsxfname.c | 702 +++++ source/components/namespace/nsxfobj.c | 285 ++ source/components/parser/psargs.c | 940 +++++++ source/components/parser/psloop.c | 1268 +++++++++ source/components/parser/psopcode.c | 522 ++++ source/components/parser/psparse.c | 711 +++++ source/components/parser/psscope.c | 302 +++ source/components/parser/pstree.c | 360 +++ source/components/parser/psutils.c | 290 ++ source/components/parser/pswalk.c | 121 + source/components/parser/psxface.c | 442 +++ source/components/resources/rsaddr.c | 407 +++ source/components/resources/rscalc.c | 730 +++++ source/components/resources/rscreate.c | 534 ++++ source/components/resources/rsdump.c | 946 +++++++ source/components/resources/rsinfo.c | 265 ++ source/components/resources/rsio.c | 304 +++ source/components/resources/rsirq.c | 308 +++ source/components/resources/rslist.c | 275 ++ source/components/resources/rsmemory.c | 251 ++ source/components/resources/rsmisc.c | 869 ++++++ source/components/resources/rsserial.c | 425 +++ source/components/resources/rsutils.c | 861 ++++++ source/components/resources/rsxface.c | 689 +++++ source/components/tables/tbfadt.c | 704 +++++ source/components/tables/tbfind.c | 143 + source/components/tables/tbinstal.c | 806 ++++++ source/components/tables/tbutils.c | 760 ++++++ source/components/tables/tbxface.c | 712 +++++ source/components/tables/tbxfroot.c | 299 +++ source/components/utilities/utaddress.c | 322 +++ source/components/utilities/utalloc.c | 416 +++ source/components/utilities/utcache.c | 361 +++ source/components/utilities/utclib.c | 889 ++++++ source/components/utilities/utcopy.c | 1078 ++++++++ source/components/utilities/utdebug.c | 741 +++++ source/components/utilities/utdecode.c | 637 +++++ source/components/utilities/utdelete.c | 766 ++++++ source/components/utilities/uteval.c | 370 +++ source/components/utilities/utglobal.c | 365 +++ source/components/utilities/utids.c | 380 +++ source/components/utilities/utinit.c | 192 ++ source/components/utilities/utlock.c | 205 ++ source/components/utilities/utmath.c | 379 +++ source/components/utilities/utmisc.c | 1299 +++++++++ source/components/utilities/utmutex.c | 397 +++ source/components/utilities/utobject.c | 787 ++++++ source/components/utilities/utosi.c | 422 +++ source/components/utilities/utresrc.c | 923 +++++++ source/components/utilities/utstate.c | 398 +++ source/components/utilities/uttrack.c | 711 +++++ source/components/utilities/utxface.c | 837 ++++++ source/components/utilities/utxferror.c | 478 ++++ source/components/utilities/utxfmutex.c | 213 ++ source/include/acapps.h | 217 ++ source/include/accommon.h | 64 + source/include/acconfig.h | 233 ++ source/include/acdebug.h | 412 +++ source/include/acdisasm.h | 864 ++++++ source/include/acdispat.h | 463 ++++ source/include/acevents.h | 347 +++ source/include/acexcep.h | 312 +++ source/include/acglobal.h | 483 ++++ source/include/achware.h | 228 ++ source/include/acinterp.h | 726 +++++ source/include/aclocal.h | 1302 +++++++++ source/include/acmacros.h | 540 ++++ source/include/acnames.h | 86 + source/include/acnamesp.h | 477 ++++ source/include/acobject.h | 586 ++++ source/include/acopcode.h | 329 +++ source/include/acoutput.h | 288 ++ source/include/acparser.h | 331 +++ source/include/acpi.h | 66 + source/include/acpiosxf.h | 416 +++ source/include/acpixf.h | 785 ++++++ source/include/acpredef.h | 564 ++++ source/include/acresrc.h | 435 +++ source/include/acrestyp.h | 692 +++++ source/include/acstruct.h | 254 ++ source/include/actables.h | 184 ++ source/include/actbl.h | 434 +++ source/include/actbl1.h | 1132 ++++++++ source/include/actbl2.h | 1207 +++++++++ source/include/actbl3.h | 650 +++++ source/include/actypes.h | 1216 +++++++++ source/include/acutils.h | 984 +++++++ source/include/amlcode.h | 512 ++++ source/include/amlresrc.h | 579 ++++ source/include/platform/accygwin.h | 92 + source/include/platform/acefi.h | 75 + source/include/platform/acenv.h | 392 +++ source/include/platform/acfreebsd.h | 105 + source/include/platform/acgcc.h | 67 + source/include/platform/acintel.h | 82 + source/include/platform/aclinux.h | 161 ++ source/include/platform/acmsvc.h | 149 ++ source/include/platform/acnetbsd.h | 116 + source/include/platform/acos2.h | 94 + source/include/platform/acwin.h | 146 + source/include/platform/acwin64.h | 83 + source/os_specific/service_layers/osunixdir.c | 251 ++ source/os_specific/service_layers/osunixxf.c | 1243 +++++++++ source/os_specific/service_layers/oswindir.c | 251 ++ source/os_specific/service_layers/oswintbl.c | 222 ++ source/os_specific/service_layers/oswinxf.c | 1481 ++++++++++ source/tools/acpibin/Makefile | 129 + source/tools/acpibin/abcompare.c | 767 ++++++ source/tools/acpibin/abmain.c | 186 ++ source/tools/acpibin/acpibin.h | 113 + source/tools/acpiexec/Makefile | 286 ++ source/tools/acpiexec/aecommon.h | 199 ++ source/tools/acpiexec/aeexec.c | 720 +++++ source/tools/acpiexec/aehandlers.c | 1251 +++++++++ source/tools/acpiexec/aemain.c | 700 +++++ source/tools/acpiexec/aetables.c | 464 ++++ source/tools/acpiexec/aetables.h | 371 +++ source/tools/acpihelp/Makefile | 121 + source/tools/acpihelp/acpihelp.h | 156 ++ source/tools/acpihelp/ahamlops.c | 325 +++ source/tools/acpihelp/ahaslkey.c | 149 ++ source/tools/acpihelp/ahaslops.c | 425 +++ source/tools/acpihelp/ahdecode.c | 855 ++++++ source/tools/acpihelp/ahmain.c | 229 ++ source/tools/acpihelp/ahpredef.c | 312 +++ source/tools/acpinames/Makefile | 189 ++ source/tools/acpinames/acpinames.h | 57 + source/tools/acpinames/anmain.c | 275 ++ source/tools/acpinames/anstubs.c | 441 +++ source/tools/acpinames/antables.c | 304 +++ source/tools/acpisrc/Makefile | 124 + source/tools/acpisrc/acpisrc.h | 405 +++ source/tools/acpisrc/ascase.c | 574 ++++ source/tools/acpisrc/asconvrt.c | 1448 ++++++++++ source/tools/acpisrc/asfile.c | 815 ++++++ source/tools/acpisrc/asmain.c | 457 ++++ source/tools/acpisrc/asremove.c | 616 +++++ source/tools/acpisrc/astable.c | 870 ++++++ source/tools/acpisrc/asutils.c | 234 ++ source/tools/acpixtract/Makefile | 116 + source/tools/acpixtract/acpixtract.c | 740 +++++ source/tools/acpixtract/axmain.c | 191 ++ source/tools/examples/examples.c | 449 ++++ 306 files changed, 180582 insertions(+) create mode 100644 source/common/adfile.c create mode 100644 source/common/adisasm.c create mode 100644 source/common/adwalk.c create mode 100644 source/common/dmextern.c create mode 100644 source/common/dmrestag.c create mode 100644 source/common/dmtable.c create mode 100644 source/common/dmtbdump.c create mode 100644 source/common/dmtbinfo.c create mode 100644 source/common/getopt.c create mode 100644 source/compiler/Makefile create mode 100644 source/compiler/aslanalyze.c create mode 100644 source/compiler/aslbtypes.c create mode 100644 source/compiler/aslcodegen.c create mode 100644 source/compiler/aslcompile.c create mode 100644 source/compiler/aslcompiler.h create mode 100644 source/compiler/aslcompiler.l create mode 100644 source/compiler/aslcompiler.y create mode 100644 source/compiler/asldefine.h create mode 100644 source/compiler/aslerror.c create mode 100644 source/compiler/aslfiles.c create mode 100644 source/compiler/aslfold.c create mode 100644 source/compiler/aslglobal.h create mode 100644 source/compiler/asllength.c create mode 100644 source/compiler/asllisting.c create mode 100644 source/compiler/aslload.c create mode 100644 source/compiler/asllookup.c create mode 100644 source/compiler/aslmain.c create mode 100644 source/compiler/aslmap.c create mode 100644 source/compiler/aslmessages.h create mode 100644 source/compiler/aslopcodes.c create mode 100644 source/compiler/asloperands.c create mode 100644 source/compiler/aslopt.c create mode 100644 source/compiler/aslpredef.c create mode 100644 source/compiler/aslresource.c create mode 100644 source/compiler/aslrestype1.c create mode 100644 source/compiler/aslrestype1i.c create mode 100644 source/compiler/aslrestype2.c create mode 100644 source/compiler/aslrestype2d.c create mode 100644 source/compiler/aslrestype2e.c create mode 100644 source/compiler/aslrestype2q.c create mode 100644 source/compiler/aslrestype2s.c create mode 100644 source/compiler/aslrestype2w.c create mode 100644 source/compiler/aslstartup.c create mode 100644 source/compiler/aslstubs.c create mode 100644 source/compiler/asltransform.c create mode 100644 source/compiler/asltree.c create mode 100644 source/compiler/asltypes.h create mode 100644 source/compiler/aslutils.c create mode 100644 source/compiler/asluuid.c create mode 100644 source/compiler/aslwalks.c create mode 100644 source/compiler/dtcompile.c create mode 100644 source/compiler/dtcompiler.h create mode 100644 source/compiler/dtexpress.c create mode 100644 source/compiler/dtfield.c create mode 100644 source/compiler/dtio.c create mode 100644 source/compiler/dtparser.l create mode 100644 source/compiler/dtparser.y create mode 100644 source/compiler/dtsubtable.c create mode 100644 source/compiler/dttable.c create mode 100644 source/compiler/dttemplate.c create mode 100644 source/compiler/dttemplate.h create mode 100644 source/compiler/dtutils.c create mode 100644 source/compiler/readme.txt create mode 100644 source/components/debugger/dbcmds.c create mode 100644 source/components/debugger/dbdisply.c create mode 100644 source/components/debugger/dbexec.c create mode 100644 source/components/debugger/dbfileio.c create mode 100644 source/components/debugger/dbhistry.c create mode 100644 source/components/debugger/dbinput.c create mode 100644 source/components/debugger/dbmethod.c create mode 100644 source/components/debugger/dbnames.c create mode 100644 source/components/debugger/dbstats.c create mode 100644 source/components/debugger/dbutils.c create mode 100644 source/components/debugger/dbxface.c create mode 100644 source/components/disassembler/dmbuffer.c create mode 100644 source/components/disassembler/dmnames.c create mode 100644 source/components/disassembler/dmobject.c create mode 100644 source/components/disassembler/dmopcode.c create mode 100644 source/components/disassembler/dmresrc.c create mode 100644 source/components/disassembler/dmresrcl.c create mode 100644 source/components/disassembler/dmresrcl2.c create mode 100644 source/components/disassembler/dmresrcs.c create mode 100644 source/components/disassembler/dmutils.c create mode 100644 source/components/disassembler/dmwalk.c create mode 100644 source/components/dispatcher/dsargs.c create mode 100644 source/components/dispatcher/dscontrol.c create mode 100644 source/components/dispatcher/dsfield.c create mode 100644 source/components/dispatcher/dsinit.c create mode 100644 source/components/dispatcher/dsmethod.c create mode 100644 source/components/dispatcher/dsmthdat.c create mode 100644 source/components/dispatcher/dsobject.c create mode 100644 source/components/dispatcher/dsopcode.c create mode 100644 source/components/dispatcher/dsutils.c create mode 100644 source/components/dispatcher/dswexec.c create mode 100644 source/components/dispatcher/dswload.c create mode 100644 source/components/dispatcher/dswload2.c create mode 100644 source/components/dispatcher/dswscope.c create mode 100644 source/components/dispatcher/dswstate.c create mode 100644 source/components/events/evevent.c create mode 100644 source/components/events/evglock.c create mode 100644 source/components/events/evgpe.c create mode 100644 source/components/events/evgpeblk.c create mode 100644 source/components/events/evgpeinit.c create mode 100644 source/components/events/evgpeutil.c create mode 100644 source/components/events/evmisc.c create mode 100644 source/components/events/evregion.c create mode 100644 source/components/events/evrgnini.c create mode 100644 source/components/events/evsci.c create mode 100644 source/components/events/evxface.c create mode 100644 source/components/events/evxfevnt.c create mode 100644 source/components/events/evxfgpe.c create mode 100644 source/components/events/evxfregn.c create mode 100644 source/components/executer/exconfig.c create mode 100644 source/components/executer/exconvrt.c create mode 100644 source/components/executer/excreate.c create mode 100644 source/components/executer/exdebug.c create mode 100644 source/components/executer/exdump.c create mode 100644 source/components/executer/exfield.c create mode 100644 source/components/executer/exfldio.c create mode 100644 source/components/executer/exmisc.c create mode 100644 source/components/executer/exmutex.c create mode 100644 source/components/executer/exnames.c create mode 100644 source/components/executer/exoparg1.c create mode 100644 source/components/executer/exoparg2.c create mode 100644 source/components/executer/exoparg3.c create mode 100644 source/components/executer/exoparg6.c create mode 100644 source/components/executer/exprep.c create mode 100644 source/components/executer/exregion.c create mode 100644 source/components/executer/exresnte.c create mode 100644 source/components/executer/exresolv.c create mode 100644 source/components/executer/exresop.c create mode 100644 source/components/executer/exstore.c create mode 100644 source/components/executer/exstoren.c create mode 100644 source/components/executer/exstorob.c create mode 100644 source/components/executer/exsystem.c create mode 100644 source/components/executer/exutils.c create mode 100644 source/components/hardware/hwacpi.c create mode 100644 source/components/hardware/hwesleep.c create mode 100644 source/components/hardware/hwgpe.c create mode 100644 source/components/hardware/hwpci.c create mode 100644 source/components/hardware/hwregs.c create mode 100644 source/components/hardware/hwsleep.c create mode 100644 source/components/hardware/hwtimer.c create mode 100644 source/components/hardware/hwvalid.c create mode 100644 source/components/hardware/hwxface.c create mode 100644 source/components/hardware/hwxfsleep.c create mode 100644 source/components/namespace/nsaccess.c create mode 100644 source/components/namespace/nsalloc.c create mode 100644 source/components/namespace/nsdump.c create mode 100644 source/components/namespace/nsdumpdv.c create mode 100644 source/components/namespace/nseval.c create mode 100644 source/components/namespace/nsinit.c create mode 100644 source/components/namespace/nsload.c create mode 100644 source/components/namespace/nsnames.c create mode 100644 source/components/namespace/nsobject.c create mode 100644 source/components/namespace/nsparse.c create mode 100644 source/components/namespace/nspredef.c create mode 100644 source/components/namespace/nsrepair.c create mode 100644 source/components/namespace/nsrepair2.c create mode 100644 source/components/namespace/nssearch.c create mode 100644 source/components/namespace/nsutils.c create mode 100644 source/components/namespace/nswalk.c create mode 100644 source/components/namespace/nsxfeval.c create mode 100644 source/components/namespace/nsxfname.c create mode 100644 source/components/namespace/nsxfobj.c create mode 100644 source/components/parser/psargs.c create mode 100644 source/components/parser/psloop.c create mode 100644 source/components/parser/psopcode.c create mode 100644 source/components/parser/psparse.c create mode 100644 source/components/parser/psscope.c create mode 100644 source/components/parser/pstree.c create mode 100644 source/components/parser/psutils.c create mode 100644 source/components/parser/pswalk.c create mode 100644 source/components/parser/psxface.c create mode 100644 source/components/resources/rsaddr.c create mode 100644 source/components/resources/rscalc.c create mode 100644 source/components/resources/rscreate.c create mode 100644 source/components/resources/rsdump.c create mode 100644 source/components/resources/rsinfo.c create mode 100644 source/components/resources/rsio.c create mode 100644 source/components/resources/rsirq.c create mode 100644 source/components/resources/rslist.c create mode 100644 source/components/resources/rsmemory.c create mode 100644 source/components/resources/rsmisc.c create mode 100644 source/components/resources/rsserial.c create mode 100644 source/components/resources/rsutils.c create mode 100644 source/components/resources/rsxface.c create mode 100644 source/components/tables/tbfadt.c create mode 100644 source/components/tables/tbfind.c create mode 100644 source/components/tables/tbinstal.c create mode 100644 source/components/tables/tbutils.c create mode 100644 source/components/tables/tbxface.c create mode 100644 source/components/tables/tbxfroot.c create mode 100644 source/components/utilities/utaddress.c create mode 100644 source/components/utilities/utalloc.c create mode 100644 source/components/utilities/utcache.c create mode 100644 source/components/utilities/utclib.c create mode 100644 source/components/utilities/utcopy.c create mode 100644 source/components/utilities/utdebug.c create mode 100644 source/components/utilities/utdecode.c create mode 100644 source/components/utilities/utdelete.c create mode 100644 source/components/utilities/uteval.c create mode 100644 source/components/utilities/utglobal.c create mode 100644 source/components/utilities/utids.c create mode 100644 source/components/utilities/utinit.c create mode 100644 source/components/utilities/utlock.c create mode 100644 source/components/utilities/utmath.c create mode 100644 source/components/utilities/utmisc.c create mode 100644 source/components/utilities/utmutex.c create mode 100644 source/components/utilities/utobject.c create mode 100644 source/components/utilities/utosi.c create mode 100644 source/components/utilities/utresrc.c create mode 100644 source/components/utilities/utstate.c create mode 100644 source/components/utilities/uttrack.c create mode 100644 source/components/utilities/utxface.c create mode 100644 source/components/utilities/utxferror.c create mode 100644 source/components/utilities/utxfmutex.c create mode 100644 source/include/acapps.h create mode 100644 source/include/accommon.h create mode 100644 source/include/acconfig.h create mode 100644 source/include/acdebug.h create mode 100644 source/include/acdisasm.h create mode 100644 source/include/acdispat.h create mode 100644 source/include/acevents.h create mode 100644 source/include/acexcep.h create mode 100644 source/include/acglobal.h create mode 100644 source/include/achware.h create mode 100644 source/include/acinterp.h create mode 100644 source/include/aclocal.h create mode 100644 source/include/acmacros.h create mode 100644 source/include/acnames.h create mode 100644 source/include/acnamesp.h create mode 100644 source/include/acobject.h create mode 100644 source/include/acopcode.h create mode 100644 source/include/acoutput.h create mode 100644 source/include/acparser.h create mode 100644 source/include/acpi.h create mode 100644 source/include/acpiosxf.h create mode 100644 source/include/acpixf.h create mode 100644 source/include/acpredef.h create mode 100644 source/include/acresrc.h create mode 100644 source/include/acrestyp.h create mode 100644 source/include/acstruct.h create mode 100644 source/include/actables.h create mode 100644 source/include/actbl.h create mode 100644 source/include/actbl1.h create mode 100644 source/include/actbl2.h create mode 100644 source/include/actbl3.h create mode 100644 source/include/actypes.h create mode 100644 source/include/acutils.h create mode 100644 source/include/amlcode.h create mode 100644 source/include/amlresrc.h create mode 100644 source/include/platform/accygwin.h create mode 100644 source/include/platform/acefi.h create mode 100644 source/include/platform/acenv.h create mode 100644 source/include/platform/acfreebsd.h create mode 100644 source/include/platform/acgcc.h create mode 100644 source/include/platform/acintel.h create mode 100644 source/include/platform/aclinux.h create mode 100644 source/include/platform/acmsvc.h create mode 100644 source/include/platform/acnetbsd.h create mode 100644 source/include/platform/acos2.h create mode 100644 source/include/platform/acwin.h create mode 100644 source/include/platform/acwin64.h create mode 100644 source/os_specific/service_layers/osunixdir.c create mode 100644 source/os_specific/service_layers/osunixxf.c create mode 100644 source/os_specific/service_layers/oswindir.c create mode 100644 source/os_specific/service_layers/oswintbl.c create mode 100644 source/os_specific/service_layers/oswinxf.c create mode 100644 source/tools/acpibin/Makefile create mode 100644 source/tools/acpibin/abcompare.c create mode 100644 source/tools/acpibin/abmain.c create mode 100644 source/tools/acpibin/acpibin.h create mode 100644 source/tools/acpiexec/Makefile create mode 100644 source/tools/acpiexec/aecommon.h create mode 100644 source/tools/acpiexec/aeexec.c create mode 100644 source/tools/acpiexec/aehandlers.c create mode 100644 source/tools/acpiexec/aemain.c create mode 100644 source/tools/acpiexec/aetables.c create mode 100644 source/tools/acpiexec/aetables.h create mode 100644 source/tools/acpihelp/Makefile create mode 100644 source/tools/acpihelp/acpihelp.h create mode 100644 source/tools/acpihelp/ahamlops.c create mode 100644 source/tools/acpihelp/ahaslkey.c create mode 100644 source/tools/acpihelp/ahaslops.c create mode 100644 source/tools/acpihelp/ahdecode.c create mode 100644 source/tools/acpihelp/ahmain.c create mode 100644 source/tools/acpihelp/ahpredef.c create mode 100644 source/tools/acpinames/Makefile create mode 100644 source/tools/acpinames/acpinames.h create mode 100644 source/tools/acpinames/anmain.c create mode 100644 source/tools/acpinames/anstubs.c create mode 100644 source/tools/acpinames/antables.c create mode 100644 source/tools/acpisrc/Makefile create mode 100644 source/tools/acpisrc/acpisrc.h create mode 100644 source/tools/acpisrc/ascase.c create mode 100644 source/tools/acpisrc/asconvrt.c create mode 100644 source/tools/acpisrc/asfile.c create mode 100644 source/tools/acpisrc/asmain.c create mode 100644 source/tools/acpisrc/asremove.c create mode 100644 source/tools/acpisrc/astable.c create mode 100644 source/tools/acpisrc/asutils.c create mode 100644 source/tools/acpixtract/Makefile create mode 100644 source/tools/acpixtract/acpixtract.c create mode 100644 source/tools/acpixtract/axmain.c create mode 100644 source/tools/examples/examples.c (limited to 'source') diff --git a/source/common/adfile.c b/source/common/adfile.c new file mode 100644 index 000000000000..d971e6895bfd --- /dev/null +++ b/source/common/adfile.c @@ -0,0 +1,333 @@ +/****************************************************************************** + * + * Module Name: adfile - Application-level disassembler file support routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" + +#include + + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("adfile") + +/* Local prototypes */ + +static INT32 +AdWriteBuffer ( + char *Filename, + char *Buffer, + UINT32 Length); + +static char FilenameBuf[20]; + + +/****************************************************************************** + * + * FUNCTION: AfGenerateFilename + * + * PARAMETERS: Prefix - prefix string + * TableId - The table ID + * + * RETURN: Pointer to the completed string + * + * DESCRIPTION: Build an output filename from an ACPI table ID string + * + ******************************************************************************/ + +char * +AdGenerateFilename ( + char *Prefix, + char *TableId) +{ + UINT32 i; + UINT32 j; + + + for (i = 0; Prefix[i]; i++) + { + FilenameBuf[i] = Prefix[i]; + } + + FilenameBuf[i] = '_'; + i++; + + for (j = 0; j < 8 && (TableId[j] != ' ') && (TableId[j] != 0); i++, j++) + { + FilenameBuf[i] = TableId[j]; + } + + FilenameBuf[i] = 0; + strcat (FilenameBuf, ACPI_TABLE_FILE_SUFFIX); + return FilenameBuf; +} + + +/****************************************************************************** + * + * FUNCTION: AfWriteBuffer + * + * PARAMETERS: Filename - name of file + * Buffer - data to write + * Length - length of data + * + * RETURN: Actual number of bytes written + * + * DESCRIPTION: Open a file and write out a single buffer + * + ******************************************************************************/ + +static INT32 +AdWriteBuffer ( + char *Filename, + char *Buffer, + UINT32 Length) +{ + FILE *fp; + ACPI_SIZE Actual; + + + fp = fopen (Filename, "wb"); + if (!fp) + { + printf ("Couldn't open %s\n", Filename); + return (-1); + } + + Actual = fwrite (Buffer, (size_t) Length, 1, fp); + fclose (fp); + return ((INT32) Actual); +} + + +/****************************************************************************** + * + * FUNCTION: AfWriteTable + * + * PARAMETERS: Table - pointer to the ACPI table + * Length - length of the table + * TableName - the table signature + * OemTableID - from the table header + * + * RETURN: None + * + * DESCRIPTION: Dump the loaded tables to a file (or files) + * + ******************************************************************************/ + +void +AdWriteTable ( + ACPI_TABLE_HEADER *Table, + UINT32 Length, + char *TableName, + char *OemTableId) +{ + char *Filename; + + + Filename = AdGenerateFilename (TableName, OemTableId); + AdWriteBuffer (Filename, (char *) Table, Length); + + AcpiOsPrintf ("Table [%s] written to \"%s\"\n", TableName, Filename); +} + + +/******************************************************************************* + * + * FUNCTION: FlGenerateFilename + * + * PARAMETERS: InputFilename - Original ASL source filename + * Suffix - New extension. + * + * RETURN: New filename containing the original base + the new suffix + * + * DESCRIPTION: Generate a new filename from the ASL source filename and a new + * extension. Used to create the *.LST, *.TXT, etc. files. + * + ******************************************************************************/ + +char * +FlGenerateFilename ( + char *InputFilename, + char *Suffix) +{ + char *Position; + char *NewFilename; + + + /* + * Copy the original filename to a new buffer. Leave room for the worst case + * where we append the suffix, an added dot and the null terminator. + */ + NewFilename = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) + strlen (InputFilename) + strlen (Suffix) + 2); + strcpy (NewFilename, InputFilename); + + /* Try to find the last dot in the filename */ + + Position = strrchr (NewFilename, '.'); + if (Position) + { + /* Tack on the new suffix */ + + Position++; + *Position = 0; + strcat (Position, Suffix); + } + else + { + /* No dot, add one and then the suffix */ + + strcat (NewFilename, "."); + strcat (NewFilename, Suffix); + } + + return NewFilename; +} + + +/******************************************************************************* + * + * FUNCTION: FlStrdup + * + * DESCRIPTION: Local strdup function + * + ******************************************************************************/ + +static char * +FlStrdup ( + char *String) +{ + char *NewString; + + + NewString = ACPI_ALLOCATE ((ACPI_SIZE) strlen (String) + 1); + if (!NewString) + { + return (NULL); + } + + strcpy (NewString, String); + return (NewString); +} + + +/******************************************************************************* + * + * FUNCTION: FlSplitInputPathname + * + * PARAMETERS: InputFilename - The user-specified ASL source file to be + * compiled + * OutDirectoryPath - Where the directory path prefix is + * returned + * OutFilename - Where the filename part is returned + * + * RETURN: Status + * + * DESCRIPTION: Split the input path into a directory and filename part + * 1) Directory part used to open include files + * 2) Filename part used to generate output filenames + * + ******************************************************************************/ + +ACPI_STATUS +FlSplitInputPathname ( + char *InputPath, + char **OutDirectoryPath, + char **OutFilename) +{ + char *Substring; + char *DirectoryPath; + char *Filename; + + + *OutDirectoryPath = NULL; + *OutFilename = NULL; + + if (!InputPath) + { + return (AE_OK); + } + + /* Get the path to the input filename's directory */ + + DirectoryPath = FlStrdup (InputPath); + if (!DirectoryPath) + { + return (AE_NO_MEMORY); + } + + Substring = strrchr (DirectoryPath, '\\'); + if (!Substring) + { + Substring = strrchr (DirectoryPath, '/'); + if (!Substring) + { + Substring = strrchr (DirectoryPath, ':'); + } + } + + if (!Substring) + { + DirectoryPath[0] = 0; + Filename = FlStrdup (InputPath); + } + else + { + Filename = FlStrdup (Substring + 1); + *(Substring+1) = 0; + } + + if (!Filename) + { + return (AE_NO_MEMORY); + } + + *OutDirectoryPath = DirectoryPath; + *OutFilename = Filename; + + return (AE_OK); +} + + diff --git a/source/common/adisasm.c b/source/common/adisasm.c new file mode 100644 index 000000000000..2509ca67e948 --- /dev/null +++ b/source/common/adisasm.c @@ -0,0 +1,1156 @@ +/****************************************************************************** + * + * Module Name: adisasm - Application-level disassembler routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdebug.h" +#include "acdisasm.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "actables.h" +#include "acapps.h" + +#include +#include + + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("adisasm") + + +extern int AslCompilerdebug; + + +ACPI_STATUS +LsDisplayNamespace ( + void); + +void +LsSetupNsList ( + void *Handle); + + +/* Local prototypes */ + +static void +AdCreateTableHeader ( + char *Filename, + ACPI_TABLE_HEADER *Table); + +static ACPI_STATUS +AdDeferredParse ( + ACPI_PARSE_OBJECT *Op, + UINT8 *Aml, + UINT32 AmlLength); + +static ACPI_STATUS +AdParseDeferredOps ( + ACPI_PARSE_OBJECT *Root); + + +/* Stubs for ASL compiler */ + +#ifndef ACPI_ASL_COMPILER +BOOLEAN +AcpiDsIsResultUsed ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + return TRUE; +} + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState) +{ + return (Status); +} +#endif + +ACPI_STATUS +AcpiNsLoadTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *Node) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsRestartControlMethod ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ReturnDesc) +{ + return (AE_OK); +} + +void +AcpiDsTerminateControlMethod ( + ACPI_OPERAND_OBJECT *MethodDesc, + ACPI_WALK_STATE *WalkState) +{ + return; +} + +ACPI_STATUS +AcpiDsCallControlMethod ( + ACPI_THREAD_STATE *Thread, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsMethodDataInitArgs ( + ACPI_OPERAND_OBJECT **Params, + UINT32 MaxParamCount, + ACPI_WALK_STATE *WalkState) +{ + return (AE_OK); +} + + +static ACPI_TABLE_DESC LocalTables[1]; +static ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot; + + +/******************************************************************************* + * + * FUNCTION: AdInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: ACPICA and local initialization + * + ******************************************************************************/ + +ACPI_STATUS +AdInitialize ( + void) +{ + ACPI_STATUS Status; + + + /* ACPI CA subsystem initialization */ + + Status = AcpiOsInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtInitGlobals (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtMutexInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiNsRootInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Setup the Table Manager (cheat - there is no RSDT) */ + + AcpiGbl_RootTableList.MaxTableCount = 1; + AcpiGbl_RootTableList.CurrentTableCount = 0; + AcpiGbl_RootTableList.Tables = LocalTables; + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AdAmlDisassemble + * + * PARAMETERS: Filename - AML input filename + * OutToFile - TRUE if output should go to a file + * Prefix - Path prefix for output + * OutFilename - where the filename is returned + * GetAllTables - TRUE if all tables are desired + * + * RETURN: Status + * + * DESCRIPTION: Disassemble an entire ACPI table + * + *****************************************************************************/ + +ACPI_STATUS +AdAmlDisassemble ( + BOOLEAN OutToFile, + char *Filename, + char *Prefix, + char **OutFilename, + BOOLEAN GetAllTables) +{ + ACPI_STATUS Status; + char *DisasmFilename = NULL; + char *ExternalFilename; + ACPI_EXTERNAL_FILE *ExternalFileList = AcpiGbl_ExternalFileList; + FILE *File = NULL; + ACPI_TABLE_HEADER *Table = NULL; + ACPI_TABLE_HEADER *ExternalTable; + ACPI_OWNER_ID OwnerId; + + + /* + * Input: AML code from either a file or via GetTables (memory or + * registry) + */ + if (Filename) + { + Status = AcpiDbGetTableFromFile (Filename, &Table); + if (ACPI_FAILURE (Status)) + { + return Status; + } + + /* + * External filenames separated by commas + * Example: iasl -e file1,file2,file3 -d xxx.aml + */ + while (ExternalFileList) + { + ExternalFilename = ExternalFileList->Path; + if (!ACPI_STRCMP (ExternalFilename, Filename)) + { + /* Next external file */ + + ExternalFileList = ExternalFileList->Next; + + continue; + } + + Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable); + if (ACPI_FAILURE (Status)) + { + return Status; + } + + /* Load external table for symbol resolution */ + + if (ExternalTable) + { + Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", + AcpiFormatException (Status)); + return Status; + } + + /* + * Load namespace from names created within control methods + * Set owner id of nodes in external table + */ + AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, + AcpiGbl_RootNode, OwnerId); + AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); + } + + /* Next external file */ + + ExternalFileList = ExternalFileList->Next; + } + + /* Clear external list generated by Scope in external tables */ + + if (AcpiGbl_ExternalFileList) + { + AcpiDmClearExternalList (); + } + } + else + { + Status = AdGetLocalTables (Filename, GetAllTables); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get ACPI tables, %s\n", + AcpiFormatException (Status)); + return Status; + } + + if (!AcpiGbl_DbOpt_disasm) + { + return AE_OK; + } + + /* Obtained the local tables, just disassemble the DSDT */ + + Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get DSDT, %s\n", + AcpiFormatException (Status)); + return Status; + } + + AcpiOsPrintf ("\nDisassembly of DSDT\n"); + Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); + } + + /* + * Output: ASL code. Redirect to a file if requested + */ + if (OutToFile) + { + /* Create/Open a disassembly output file */ + + DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); + if (!OutFilename) + { + fprintf (stderr, "Could not generate output filename\n"); + Status = AE_ERROR; + goto Cleanup; + } + + File = fopen (DisasmFilename, "w+"); + if (!File) + { + fprintf (stderr, "Could not open output file %s\n", DisasmFilename); + Status = AE_ERROR; + goto Cleanup; + } + + AcpiOsRedirectOutput (File); + } + + *OutFilename = DisasmFilename; + + if (!AcpiUtIsAmlTable (Table)) + { + AdDisassemblerHeader (Filename); + AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", + Table->Signature); + AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " + "FieldName : FieldValue\n */\n\n"); + + AcpiDmDumpDataTable (Table); + fprintf (stderr, "Acpi Data Table [%4.4s] decoded, written to \"%s\"\n", + Table->Signature, DisasmFilename); + } + else + { + /* Always parse the tables, only option is what to display */ + + Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not parse ACPI tables, %s\n", + AcpiFormatException (Status)); + goto Cleanup; + } + + if (AslCompilerdebug) + { + AcpiOsPrintf ("/**** Before second load\n"); + + LsSetupNsList (File); + LsDisplayNamespace (); + AcpiOsPrintf ("*****/\n"); + } + + /* Load namespace from names created within control methods */ + + AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, + AcpiGbl_RootNode, OwnerId); + + /* + * Cross reference the namespace here, in order to + * generate External() statements + */ + AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, + AcpiGbl_RootNode, OwnerId); + + if (AslCompilerdebug) + { + AcpiDmDumpTree (AcpiGbl_ParseOpRoot); + } + + /* Find possible calls to external control methods */ + + AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); + + /* + * If we found any external control methods, we must reparse + * the entire tree with the new information (namely, the + * number of arguments per method) + */ + if (AcpiDmGetExternalMethodCount ()) + { + fprintf (stderr, + "\nFound %u external control methods, " + "reparsing with new information\n", + AcpiDmGetExternalMethodCount ()); + + /* Reparse, rebuild namespace. no need to xref namespace */ + + AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); + AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); + + AcpiGbl_RootNode = NULL; + AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; + AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; + AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; + AcpiGbl_RootNodeStruct.Parent = NULL; + AcpiGbl_RootNodeStruct.Child = NULL; + AcpiGbl_RootNodeStruct.Peer = NULL; + AcpiGbl_RootNodeStruct.Object = NULL; + AcpiGbl_RootNodeStruct.Flags = 0; + + Status = AcpiNsRootInitialize (); + AcpiDmAddExternalsToNamespace (); + + /* Parse the table again. No need to reload it, however */ + + Status = AdParseTable (Table, NULL, FALSE, FALSE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not parse ACPI tables, %s\n", + AcpiFormatException (Status)); + goto Cleanup; + } + + if (AslCompilerdebug) + { + AcpiOsPrintf ("/**** After second load and resource conversion\n"); + LsSetupNsList (File); + LsDisplayNamespace (); + AcpiOsPrintf ("*****/\n"); + + AcpiDmDumpTree (AcpiGbl_ParseOpRoot); + } + } + + /* + * Now that the namespace is finalized, we can perform namespace + * transforms. + * + * 1) Convert fixed-offset references to resource descriptors + * to symbolic references (Note: modifies namespace) + */ + AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); + + /* Optional displays */ + + if (AcpiGbl_DbOpt_disasm) + { + AdDisplayTables (Filename, Table); + fprintf (stderr, + "Disassembly completed, written to \"%s\"\n", + DisasmFilename); + } + } + +Cleanup: + + if (Table && !AcpiUtIsAmlTable (Table)) + { + ACPI_FREE (Table); + } + + if (DisasmFilename) + { + ACPI_FREE (DisasmFilename); + } + + if (OutToFile && File) + { + if (AslCompilerdebug) /* Display final namespace, with transforms */ + { + LsSetupNsList (File); + LsDisplayNamespace (); + } + + fclose (File); + AcpiOsRedirectOutput (stdout); + } + + AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); + AcpiGbl_ParseOpRoot = NULL; + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AdDisassemblerHeader + * + * PARAMETERS: Filename - Input file for the table + * + * RETURN: None + * + * DESCRIPTION: Create the disassembler header, including ACPI CA signon with + * current time and date. + * + *****************************************************************************/ + +void +AdDisassemblerHeader ( + char *Filename) +{ + time_t Timer; + + time (&Timer); + + /* Header and input table info */ + + AcpiOsPrintf ("/*\n"); + AcpiOsPrintf (ACPI_COMMON_HEADER ("AML Disassembler", " * ")); + + AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer)); + AcpiOsPrintf (" *\n"); +} + + +/****************************************************************************** + * + * FUNCTION: AdCreateTableHeader + * + * PARAMETERS: Filename - Input file for the table + * Table - Pointer to the raw table + * + * RETURN: None + * + * DESCRIPTION: Create the ASL table header, including ACPI CA signon with + * current time and date. + * + *****************************************************************************/ + +static void +AdCreateTableHeader ( + char *Filename, + ACPI_TABLE_HEADER *Table) +{ + char *NewFilename; + UINT8 Checksum; + + + /* + * Print file header and dump original table header + */ + AdDisassemblerHeader (Filename); + + AcpiOsPrintf (" * Original Table Header:\n"); + AcpiOsPrintf (" * Signature \"%4.4s\"\n", Table->Signature); + AcpiOsPrintf (" * Length 0x%8.8X (%u)\n", Table->Length, Table->Length); + + /* Print and validate the revision */ + + AcpiOsPrintf (" * Revision 0x%2.2X", Table->Revision); + + switch (Table->Revision) + { + case 0: + AcpiOsPrintf (" **** Invalid Revision"); + break; + + case 1: + /* Revision of DSDT controls the ACPI integer width */ + + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT)) + { + AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support"); + } + break; + + default: + break; + } + AcpiOsPrintf ("\n"); + + /* Print and validate the table checksum */ + + AcpiOsPrintf (" * Checksum 0x%2.2X", Table->Checksum); + + Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length); + if (Checksum) + { + AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X", + (UINT8) (Table->Checksum - Checksum)); + } + AcpiOsPrintf ("\n"); + + AcpiOsPrintf (" * OEM ID \"%.6s\"\n", Table->OemId); + AcpiOsPrintf (" * OEM Table ID \"%.8s\"\n", Table->OemTableId); + AcpiOsPrintf (" * OEM Revision 0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision); + AcpiOsPrintf (" * Compiler ID \"%.4s\"\n", Table->AslCompilerId); + AcpiOsPrintf (" * Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision); + AcpiOsPrintf (" */\n\n"); + + /* Create AML output filename based on input filename */ + + if (Filename) + { + NewFilename = FlGenerateFilename (Filename, "aml"); + } + else + { + NewFilename = ACPI_ALLOCATE_ZEROED (9); + strncat (NewFilename, Table->Signature, 4); + strcat (NewFilename, ".aml"); + } + + /* Open the ASL definition block */ + + AcpiOsPrintf ( + "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n", + NewFilename, Table->Signature, Table->Revision, + Table->OemId, Table->OemTableId, Table->OemRevision); + + ACPI_FREE (NewFilename); +} + + +/****************************************************************************** + * + * FUNCTION: AdDisplayTables + * + * PARAMETERS: Filename - Input file for the table + * Table - Pointer to the raw table + * + * RETURN: Status + * + * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables + * + *****************************************************************************/ + +ACPI_STATUS +AdDisplayTables ( + char *Filename, + ACPI_TABLE_HEADER *Table) +{ + + + if (!AcpiGbl_ParseOpRoot) + { + return AE_NOT_EXIST; + } + + if (!AcpiGbl_DbOpt_verbose) + { + AdCreateTableHeader (Filename, Table); + } + + AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX); + + if (AcpiGbl_DbOpt_verbose) + { + AcpiOsPrintf ("\n\nTable Header:\n"); + AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER), + DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + + AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length); + AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length, + DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + } + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: AdDeferredParse + * + * PARAMETERS: Op - Root Op of the deferred opcode + * Aml - Pointer to the raw AML + * AmlLength - Length of the AML + * + * RETURN: Status + * + * DESCRIPTION: Parse one deferred opcode + * (Methods, operation regions, etc.) + * + *****************************************************************************/ + +static ACPI_STATUS +AdDeferredParse ( + ACPI_PARSE_OBJECT *Op, + UINT8 *Aml, + UINT32 AmlLength) +{ + ACPI_WALK_STATE *WalkState; + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *SearchOp; + ACPI_PARSE_OBJECT *StartOp; + UINT32 BaseAmlOffset; + ACPI_PARSE_OBJECT *ExtraOp; + + + ACPI_FUNCTION_TRACE (AdDeferredParse); + + + fprintf (stderr, "."); + + if (!Aml || !AmlLength) + { + return_ACPI_STATUS (AE_OK); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n", + Op->Common.AmlOpName, (char *) &Op->Named.Name)); + + WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); + if (!WalkState) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml, + AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Parse the method */ + + WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; + WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; + Status = AcpiPsParseAml (WalkState); + + /* + * We need to update all of the Aml offsets, since the parser thought + * that the method began at offset zero. In reality, it began somewhere + * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that + * was just created and update the AmlOffset in each Op + */ + BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1; + StartOp = (Op->Common.Value.Arg)->Common.Next; + SearchOp = StartOp; + + /* Walk the parse tree */ + + while (SearchOp) + { + SearchOp->Common.AmlOffset += BaseAmlOffset; + SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); + } + + /* + * Link the newly parsed subtree into the main parse tree + */ + switch (Op->Common.AmlOpcode) + { + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + switch (Op->Common.AmlOpcode) + { + case AML_PACKAGE_OP: + ExtraOp = Op->Common.Value.Arg; + ExtraOp = ExtraOp->Common.Next; + Op->Common.Value.Arg = ExtraOp->Common.Value.Arg; + break; + + case AML_VAR_PACKAGE_OP: + case AML_BUFFER_OP: + default: + ExtraOp = Op->Common.Value.Arg; + Op->Common.Value.Arg = ExtraOp->Common.Value.Arg; + break; + } + + /* Must point all parents to the main tree */ + + StartOp = Op; + SearchOp = StartOp; + while (SearchOp) + { + if (SearchOp->Common.Parent == ExtraOp) + { + SearchOp->Common.Parent = Op; + } + SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); + } + break; + + default: + break; + } + + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AdParseDeferredOps + * + * PARAMETERS: Root - Root of the parse tree + * + * RETURN: Status + * + * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.) + * + *****************************************************************************/ + +static ACPI_STATUS +AdParseDeferredOps ( + ACPI_PARSE_OBJECT *Root) +{ + ACPI_PARSE_OBJECT *Op = Root; + ACPI_STATUS Status = AE_OK; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_NAME (AdParseDeferredOps); + fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n"); + + while (Op) + { + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (!(OpInfo->Flags & AML_DEFER)) + { + Op = AcpiPsGetDepthNext (Root, Op); + continue; + } + + switch (Op->Common.AmlOpcode) + { + case AML_METHOD_OP: + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + break; + + case AML_REGION_OP: + case AML_DATA_REGION_OP: + case AML_CREATE_QWORD_FIELD_OP: + case AML_CREATE_DWORD_FIELD_OP: + case AML_CREATE_WORD_FIELD_OP: + case AML_CREATE_BYTE_FIELD_OP: + case AML_CREATE_BIT_FIELD_OP: + case AML_CREATE_FIELD_OP: + case AML_BANK_FIELD_OP: + + /* Nothing to do in these cases */ + + break; + + default: + ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]", + Op->Common.AmlOpName)); + break; + } + + Op = AcpiPsGetDepthNext (Root, Op); + } + + fprintf (stderr, "\n"); + return Status; +} + + +/****************************************************************************** + * + * FUNCTION: AdGetLocalTables + * + * PARAMETERS: Filename - Not used + * GetAllTables - TRUE if all tables are desired + * + * RETURN: Status + * + * DESCRIPTION: Get the ACPI tables from either memory or a file + * + *****************************************************************************/ + +ACPI_STATUS +AdGetLocalTables ( + char *Filename, + BOOLEAN GetAllTables) +{ + ACPI_STATUS Status; + ACPI_TABLE_HEADER TableHeader; + ACPI_TABLE_HEADER *NewTable; + UINT32 NumTables; + UINT32 PointerSize; + UINT32 TableIndex; + + + if (GetAllTables) + { + ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT); + AcpiOsTableOverride (&TableHeader, &NewTable); + if (!NewTable) + { + fprintf (stderr, "Could not obtain RSDT\n"); + return AE_NO_ACPI_TABLES; + } + else + { + AdWriteTable (NewTable, NewTable->Length, + ACPI_SIG_RSDT, NewTable->OemTableId); + } + + if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT)) + { + PointerSize = sizeof (UINT32); + } + else + { + PointerSize = sizeof (UINT64); + } + + /* + * Determine the number of tables pointed to by the RSDT/XSDT. + * This is defined by the ACPI Specification to be the number of + * pointers contained within the RSDT/XSDT. The size of the pointers + * is architecture-dependent. + */ + NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize; + AcpiOsPrintf ("There are %u tables defined in the %4.4s\n\n", + NumTables, NewTable->Signature); + + /* Get the FADT */ + + ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT); + AcpiOsTableOverride (&TableHeader, &NewTable); + if (NewTable) + { + AdWriteTable (NewTable, NewTable->Length, + ACPI_SIG_FADT, NewTable->OemTableId); + } + AcpiOsPrintf ("\n"); + + /* Don't bother with FACS, it is usually all zeros */ + } + + /* Always get the DSDT */ + + ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT); + AcpiOsTableOverride (&TableHeader, &NewTable); + if (NewTable) + { + AdWriteTable (NewTable, NewTable->Length, + ACPI_SIG_DSDT, NewTable->OemTableId); + + /* Store DSDT in the Table Manager */ + + Status = AcpiTbStoreTable (0, NewTable, NewTable->Length, + 0, &TableIndex); + if (ACPI_FAILURE (Status)) + { + fprintf (stderr, "Could not store DSDT\n"); + return AE_NO_ACPI_TABLES; + } + } + else + { + fprintf (stderr, "Could not obtain DSDT\n"); + return AE_NO_ACPI_TABLES; + } + +#if 0 + /* TBD: Future implementation */ + + AcpiOsPrintf ("\n"); + + /* Get all SSDTs */ + + ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT); + do + { + NewTable = NULL; + Status = AcpiOsTableOverride (&TableHeader, &NewTable); + + } while (NewTable); +#endif + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: AdParseTable + * + * PARAMETERS: Table - Pointer to the raw table + * OwnerId - Returned OwnerId of the table + * LoadTable - If add table to the global table list + * External - If this is an external table + * + * RETURN: Status + * + * DESCRIPTION: Parse the DSDT. + * + *****************************************************************************/ + +ACPI_STATUS +AdParseTable ( + ACPI_TABLE_HEADER *Table, + ACPI_OWNER_ID *OwnerId, + BOOLEAN LoadTable, + BOOLEAN External) +{ + ACPI_STATUS Status = AE_OK; + ACPI_WALK_STATE *WalkState; + UINT8 *AmlStart; + UINT32 AmlLength; + UINT32 TableIndex; + + + if (!Table) + { + return AE_NOT_EXIST; + } + + /* Pass 1: Parse everything except control method bodies */ + + fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature); + + AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); + AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)); + + /* Create the root object */ + + AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (); + if (!AcpiGbl_ParseOpRoot) + { + return AE_NO_MEMORY; + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (0, + AcpiGbl_ParseOpRoot, NULL, NULL); + if (!WalkState) + { + return (AE_NO_MEMORY); + } + + Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot, + NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; + WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; + + Status = AcpiPsParseAml (WalkState); + if (ACPI_FAILURE (Status)) + { + return Status; + } + + /* If LoadTable is FALSE, we are parsing the last loaded table */ + + TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1; + + /* Pass 2 */ + + if (LoadTable) + { + Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table, + Table->Length, ACPI_TABLE_ORIGIN_ALLOCATED, &TableIndex); + if (ACPI_FAILURE (Status)) + { + return Status; + } + Status = AcpiTbAllocateOwnerId (TableIndex); + if (ACPI_FAILURE (Status)) + { + return Status; + } + if (OwnerId) + { + Status = AcpiTbGetOwnerId (TableIndex, OwnerId); + if (ACPI_FAILURE (Status)) + { + return Status; + } + } + } + + fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature); + + Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* No need to parse control methods of external table */ + + if (External) + { + return AE_OK; + } + + /* Pass 3: Parse control methods and link their parse trees into the main parse tree */ + + Status = AdParseDeferredOps (AcpiGbl_ParseOpRoot); + + /* Process Resource Templates */ + + AcpiDmFindResources (AcpiGbl_ParseOpRoot); + + fprintf (stderr, "Parsing completed\n"); + return AE_OK; +} + + diff --git a/source/common/adwalk.c b/source/common/adwalk.c new file mode 100644 index 000000000000..efda35a8be23 --- /dev/null +++ b/source/common/adwalk.c @@ -0,0 +1,1004 @@ +/****************************************************************************** + * + * Module Name: adwalk - Application-level disassembler parse tree walk routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdisasm.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acapps.h" + + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("adwalk") + +/* + * aslmap - opcode mappings and reserved method names + */ +ACPI_OBJECT_TYPE +AslMapNamedOpcodeToDataType ( + UINT16 Opcode); + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDmFindOrphanDescending ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +AcpiDmDumpDescending ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +AcpiDmXrefDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +AcpiDmCommonAscendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +AcpiDmLoadDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static UINT32 +AcpiDmInspectPossibleArgs ( + UINT32 CurrentOpArgCount, + UINT32 TargetCount, + ACPI_PARSE_OBJECT *Op); + +static ACPI_STATUS +AcpiDmResourceDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpTree + * + * PARAMETERS: Origin - Starting object + * + * RETURN: None + * + * DESCRIPTION: Parse tree walk to format and output the nodes + * + ******************************************************************************/ + +void +AcpiDmDumpTree ( + ACPI_PARSE_OBJECT *Origin) +{ + ACPI_OP_WALK_INFO Info; + + + if (!Origin) + { + return; + } + + AcpiOsPrintf ("/*\nAML Parse Tree\n\n"); + Info.Flags = 0; + Info.Count = 0; + Info.Level = 0; + Info.WalkState = NULL; + AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info); + AcpiOsPrintf ("*/\n\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFindOrphanMethods + * + * PARAMETERS: Origin - Starting object + * + * RETURN: None + * + * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods + * that are not resolved in the namespace + * + ******************************************************************************/ + +void +AcpiDmFindOrphanMethods ( + ACPI_PARSE_OBJECT *Origin) +{ + ACPI_OP_WALK_INFO Info; + + + if (!Origin) + { + return; + } + + Info.Flags = 0; + Info.Level = 0; + Info.WalkState = NULL; + AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFinishNamespaceLoad + * + * PARAMETERS: ParseTreeRoot - Root of the parse tree + * NamespaceRoot - Root of the internal namespace + * OwnerId - OwnerId of the table to be disassembled + * + * RETURN: None + * + * DESCRIPTION: Load all namespace items that are created within control + * methods. Used before namespace cross reference + * + ******************************************************************************/ + +void +AcpiDmFinishNamespaceLoad ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot, + ACPI_OWNER_ID OwnerId) +{ + ACPI_STATUS Status; + ACPI_OP_WALK_INFO Info; + ACPI_WALK_STATE *WalkState; + + + if (!ParseTreeRoot) + { + return; + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); + if (!WalkState) + { + return; + } + + Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return; + } + + Info.Flags = 0; + Info.Level = 0; + Info.WalkState = WalkState; + AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp, + AcpiDmCommonAscendingOp, &Info); + ACPI_FREE (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCrossReferenceNamespace + * + * PARAMETERS: ParseTreeRoot - Root of the parse tree + * NamespaceRoot - Root of the internal namespace + * OwnerId - OwnerId of the table to be disassembled + * + * RETURN: None + * + * DESCRIPTION: Cross reference the namespace to create externals + * + ******************************************************************************/ + +void +AcpiDmCrossReferenceNamespace ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot, + ACPI_OWNER_ID OwnerId) +{ + ACPI_STATUS Status; + ACPI_OP_WALK_INFO Info; + ACPI_WALK_STATE *WalkState; + + + if (!ParseTreeRoot) + { + return; + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); + if (!WalkState) + { + return; + } + + Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return; + } + + Info.Flags = 0; + Info.Level = 0; + Info.WalkState = WalkState; + AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp, + AcpiDmCommonAscendingOp, &Info); + ACPI_FREE (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmConvertResourceIndexes + * + * PARAMETERS: ParseTreeRoot - Root of the parse tree + * NamespaceRoot - Root of the internal namespace + * + * RETURN: None + * + * DESCRIPTION: Convert fixed-offset references to resource descriptors to + * symbolic references. Should only be called after namespace has + * been cross referenced. + * + ******************************************************************************/ + +void +AcpiDmConvertResourceIndexes ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot) +{ + ACPI_STATUS Status; + ACPI_OP_WALK_INFO Info; + ACPI_WALK_STATE *WalkState; + + + if (!ParseTreeRoot) + { + return; + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL); + if (!WalkState) + { + return; + } + + Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return; + } + + Info.Flags = 0; + Info.Level = 0; + Info.WalkState = WalkState; + AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp, + AcpiDmCommonAscendingOp, &Info); + ACPI_FREE (WalkState); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpDescending + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Format and print contents of one parse Op. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmDumpDescending ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + char *Path; + + + if (!Op) + { + return (AE_OK); + } + + /* Most of the information (count, level, name) here */ + + Info->Count++; + AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); + AcpiDmIndent (Level); + AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); + + /* Extra info is helpful */ + + switch (Op->Common.AmlOpcode) + { + case AML_BYTE_OP: + case AML_WORD_OP: + case AML_DWORD_OP: + AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer); + break; + + case AML_QWORD_OP: + AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); + break; + + case AML_INT_NAMEPATH_OP: + if (Op->Common.Value.String) + { + AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, + NULL, &Path); + AcpiOsPrintf ("%s %p", Path, Op->Common.Node); + ACPI_FREE (Path); + } + else + { + AcpiOsPrintf ("[NULL]"); + } + break; + + case AML_NAME_OP: + case AML_METHOD_OP: + case AML_DEVICE_OP: + case AML_INT_NAMEDFIELD_OP: + AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name)); + break; + + default: + break; + } + + AcpiOsPrintf ("\n"); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFindOrphanDescending + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Check namepath Ops for orphaned method invocations + * + * Note: Experimental. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmFindOrphanDescending ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + const ACPI_OPCODE_INFO *OpInfo; + ACPI_PARSE_OBJECT *ChildOp; + ACPI_PARSE_OBJECT *NextOp; + ACPI_PARSE_OBJECT *ParentOp; + UINT32 ArgCount; + + + if (!Op) + { + return (AE_OK); + } + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + switch (Op->Common.AmlOpcode) + { +#ifdef ACPI_UNDER_DEVELOPMENT + case AML_ADD_OP: + ChildOp = Op->Common.Value.Arg; + if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + !ChildOp->Common.Node) + { + AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, + NULL, &Path); + AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", Op->Common.AmlOpName, Path); + ACPI_FREE (Path); + + NextOp = Op->Common.Next; + if (!NextOp) + { + /* This NamePath has no args, assume it is an integer */ + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); + return (AE_OK); + } + + ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); + AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op)); + + if (ArgCount < 1) + { + /* One Arg means this is just a Store(Name,Target) */ + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); + return (AE_OK); + } + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); + } + break; +#endif + + case AML_STORE_OP: + + ChildOp = Op->Common.Value.Arg; + if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + !ChildOp->Common.Node) + { + NextOp = Op->Common.Next; + if (!NextOp) + { + /* This NamePath has no args, assume it is an integer */ + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); + return (AE_OK); + } + + ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); + if (ArgCount <= 1) + { + /* One Arg means this is just a Store(Name,Target) */ + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); + return (AE_OK); + } + + AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); + } + break; + + case AML_INT_NAMEPATH_OP: + + /* Must examine parent to see if this namepath is an argument */ + + ParentOp = Op->Common.Parent; + OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); + + if ((OpInfo->Class != AML_CLASS_EXECUTE) && + (OpInfo->Class != AML_CLASS_CREATE) && + (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && + !Op->Common.Node) + { + ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); + + /* + * Check if namepath is a predicate for if/while or lone parameter to + * a return. + */ + if (ArgCount == 0) + { + if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || + (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || + (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && + + /* And namepath is the first argument */ + (ParentOp->Common.Value.Arg == Op)) + { + AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0); + break; + } + } + + /* + * This is a standalone namestring (not a parameter to another + * operator) - it *must* be a method invocation, nothing else is + * grammatically possible. + */ + AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); + + } + break; + + default: + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmLoadDescendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending handler for namespace control method object load + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmLoadDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + const ACPI_OPCODE_INFO *OpInfo; + ACPI_WALK_STATE *WalkState; + ACPI_OBJECT_TYPE ObjectType; + ACPI_STATUS Status; + char *Path = NULL; + ACPI_PARSE_OBJECT *NextOp; + ACPI_NAMESPACE_NODE *Node; + char FieldPath[5]; + BOOLEAN PreDefined = FALSE; + UINT8 PreDefineIndex = 0; + + + WalkState = Info->WalkState; + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + ObjectType = OpInfo->ObjectType; + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + + /* Only interested in operators that create new names */ + + if (!(OpInfo->Flags & AML_NAMED) && + !(OpInfo->Flags & AML_CREATE)) + { + goto Exit; + } + + /* Get the NamePath from the appropriate place */ + + if (OpInfo->Flags & AML_NAMED) + { + /* For all named operators, get the new name */ + + Path = (char *) Op->Named.Path; + + if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) + { + *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; + FieldPath[4] = 0; + Path = FieldPath; + } + } + else if (OpInfo->Flags & AML_CREATE) + { + /* New name is the last child */ + + NextOp = Op->Common.Value.Arg; + + while (NextOp->Common.Next) + { + NextOp = NextOp->Common.Next; + } + Path = NextOp->Common.Value.String; + } + + if (!Path) + { + goto Exit; + } + + /* Insert the name into the namespace */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &Node); + + Op->Common.Node = Node; + + if (ACPI_SUCCESS (Status)) + { + /* Check if it's a predefined node */ + + while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) + { + if (!ACPI_STRNCMP (Node->Name.Ascii, + AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4)) + { + PreDefined = TRUE; + break; + } + + PreDefineIndex++; + } + + /* + * Set node owner id if it satisfies all the following conditions: + * 1) Not a predefined node, _SB_ etc + * 2) Not the root node + * 3) Not a node created by Scope + */ + + if (!PreDefined && Node != AcpiGbl_RootNode && + Op->Common.AmlOpcode != AML_SCOPE_OP) + { + Node->OwnerId = WalkState->OwnerId; + } + } + + +Exit: + + if (AcpiNsOpensScope (ObjectType)) + { + if (Op->Common.Node) + { + Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmXrefDescendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending handler for namespace cross reference + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmXrefDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + const ACPI_OPCODE_INFO *OpInfo; + ACPI_WALK_STATE *WalkState; + ACPI_OBJECT_TYPE ObjectType; + ACPI_OBJECT_TYPE ObjectType2; + ACPI_STATUS Status; + char *Path = NULL; + ACPI_PARSE_OBJECT *NextOp; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *Object; + UINT32 ParamCount = 0; + + + WalkState = Info->WalkState; + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + ObjectType = OpInfo->ObjectType; + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + + if ((!(OpInfo->Flags & AML_NAMED)) && + (!(OpInfo->Flags & AML_CREATE)) && + (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) + { + goto Exit; + } + + /* Get the NamePath from the appropriate place */ + + if (OpInfo->Flags & AML_NAMED) + { + if ((Op->Common.AmlOpcode == AML_ALIAS_OP) || + (Op->Common.AmlOpcode == AML_SCOPE_OP)) + { + /* + * Only these two operators refer to an existing name, + * first argument + */ + Path = (char *) Op->Named.Path; + } + } + else if (OpInfo->Flags & AML_CREATE) + { + /* Referenced Buffer Name is the first child */ + + NextOp = Op->Common.Value.Arg; + if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) + { + Path = NextOp->Common.Value.String; + } + } + else + { + Path = Op->Common.Value.String; + } + + if (!Path) + { + goto Exit; + } + + /* + * Lookup the name in the namespace. Name must exist at this point, or it + * is an invalid reference. + * + * The namespace is also used as a lookup table for references to resource + * descriptors and the fields within them. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0); + + /* + * We could install this into the namespace, but we catch duplicate + * externals when they are added to the list. + */ +#if 0 + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &Node); +#endif + } + } + + /* + * Found the node in external table, add it to external list + * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc + */ + else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId) + { + ObjectType2 = ObjectType; + + Object = AcpiNsGetAttachedObject (Node); + if (Object) + { + ObjectType2 = Object->Common.Type; + if (ObjectType2 == ACPI_TYPE_METHOD) + { + ParamCount = Object->Method.ParamCount; + } + } + + AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount); + Op->Common.Node = Node; + } + else + { + Op->Common.Node = Node; + } + + +Exit: + /* Open new scope if necessary */ + + if (AcpiNsOpensScope (ObjectType)) + { + if (Op->Common.Node) + { + Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmResourceDescendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: None + * + * DESCRIPTION: Process one parse op during symbolic resource index conversion. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmResourceDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + const ACPI_OPCODE_INFO *OpInfo; + ACPI_WALK_STATE *WalkState; + ACPI_OBJECT_TYPE ObjectType; + ACPI_STATUS Status; + + + WalkState = Info->WalkState; + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + /* Open new scope if necessary */ + + ObjectType = OpInfo->ObjectType; + if (AcpiNsOpensScope (ObjectType)) + { + if (Op->Common.Node) + { + + Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + /* + * Check if this operator contains a reference to a resource descriptor. + * If so, convert the reference into a symbolic reference. + */ + AcpiDmCheckResourceReference (Op, WalkState); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCommonAscendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: None + * + * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes + * scope if necessary. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmCommonAscendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + const ACPI_OPCODE_INFO *OpInfo; + ACPI_OBJECT_TYPE ObjectType; + + + /* Close scope if necessary */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + ObjectType = OpInfo->ObjectType; + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + + if (AcpiNsOpensScope (ObjectType)) + { + (void) AcpiDsScopeStackPop (Info->WalkState); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmInspectPossibleArgs + * + * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the + * possible method invocation found + * TargetCount - Number of targets (0,1,2) for this op + * Op - Parse op + * + * RETURN: Status + * + * DESCRIPTION: Examine following args and next ops for possible arguments + * for an unrecognized method invocation. + * + ******************************************************************************/ + +static UINT32 +AcpiDmInspectPossibleArgs ( + UINT32 CurrentOpArgCount, + UINT32 TargetCount, + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *OpInfo; + UINT32 i; + UINT32 Last = 0; + UINT32 Lookahead; + + + Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; + + /* Lookahead for the maximum number of possible arguments */ + + for (i = 0; i < Lookahead; i++) + { + if (!Op) + { + break; + } + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + /* + * Any one of these operators is "very probably" not a method arg + */ + if ((Op->Common.AmlOpcode == AML_STORE_OP) || + (Op->Common.AmlOpcode == AML_NOTIFY_OP)) + { + break; + } + + if ((OpInfo->Class != AML_CLASS_EXECUTE) && + (OpInfo->Class != AML_CLASS_CONTROL)) + { + Last = i+1; + } + + Op = Op->Common.Next; + } + + return (Last); +} + + diff --git a/source/common/dmextern.c b/source/common/dmextern.c new file mode 100644 index 000000000000..37c34fc5dab1 --- /dev/null +++ b/source/common/dmextern.c @@ -0,0 +1,672 @@ +/****************************************************************************** + * + * Module Name: dmextern - Support for External() ASL statements + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdisasm.h" + + +/* + * This module is used for application-level code (iASL disassembler) only. + * + * It contains the code to create and emit any necessary External() ASL + * statements for the module being disassembled. + */ +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("dmextern") + + +/* + * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL + * ObjectTypeKeyword. Used to generate typed external declarations + */ +static const char *AcpiGbl_DmTypeNames[] = +{ + /* 00 */ "", /* Type ANY */ + /* 01 */ ", IntObj", + /* 02 */ ", StrObj", + /* 03 */ ", BuffObj", + /* 04 */ ", PkgObj", + /* 05 */ ", FieldUnitObj", + /* 06 */ ", DeviceObj", + /* 07 */ ", EventObj", + /* 08 */ ", MethodObj", + /* 09 */ ", MutexObj", + /* 10 */ ", OpRegionObj", + /* 11 */ ", PowerResObj", + /* 12 */ ", ProcessorObj", + /* 13 */ ", ThermalZoneObj", + /* 14 */ ", BuffFieldObj", + /* 15 */ ", DDBHandleObj", + /* 16 */ "", /* Debug object */ + /* 17 */ ", FieldUnitObj", + /* 18 */ ", FieldUnitObj", + /* 19 */ ", FieldUnitObj" +}; + + +/* Local prototypes */ + +static const char * +AcpiDmGetObjectTypeName ( + ACPI_OBJECT_TYPE Type); + +static char * +AcpiDmNormalizeParentPrefix ( + ACPI_PARSE_OBJECT *Op, + char *Path); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGetObjectTypeName + * + * PARAMETERS: Type - An ACPI_OBJECT_TYPE + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Map an object type to the ASL object type string. + * + ******************************************************************************/ + +static const char * +AcpiDmGetObjectTypeName ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type == ACPI_TYPE_LOCAL_SCOPE) + { + Type = ACPI_TYPE_DEVICE; + } + + else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD) + { + return (""); + } + + return (AcpiGbl_DmTypeNames[Type]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmNormalizeParentPrefix + * + * PARAMETERS: Op - Parse op + * Path - Path with parent prefix + * + * RETURN: The full pathname to the object (from the namespace root) + * + * DESCRIPTION: Returns the full pathname of a path with parent prefix + * The caller must free the fullpath returned. + * + ******************************************************************************/ + +static char * +AcpiDmNormalizeParentPrefix ( + ACPI_PARSE_OBJECT *Op, + char *Path) +{ + ACPI_NAMESPACE_NODE *Node; + char *Fullpath; + char *ParentPath; + ACPI_SIZE Length; + + + /* Search upwards in the parse tree until we reach a namespace node */ + + while (Op) + { + if (Op->Common.Node) + { + break; + } + + Op = Op->Common.Parent; + } + + if (!Op) + { + return (NULL); + } + + /* + * Find the actual parent node for the reference: + * Remove all carat prefixes from the input path. + * There may be multiple parent prefixes (For example, ^^^M000) + */ + Node = Op->Common.Node; + while (Node && (*Path == (UINT8) AML_PARENT_PREFIX)) + { + Node = Node->Parent; + Path++; + } + + if (!Node) + { + return (NULL); + } + + /* Get the full pathname for the parent node */ + + ParentPath = AcpiNsGetExternalPathname (Node); + if (!ParentPath) + { + return (NULL); + } + + Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1); + if (ParentPath[1]) + { + /* + * If ParentPath is not just a simple '\', increment the length + * for the required dot separator (ParentPath.Path) + */ + Length++; + } + + Fullpath = ACPI_ALLOCATE_ZEROED (Length); + if (!Fullpath) + { + goto Cleanup; + } + + /* + * Concatenate parent fullpath and path. For example, + * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" + * + * Copy the parent path + */ + ACPI_STRCAT (Fullpath, ParentPath); + + /* Add dot separator (don't need dot if parent fullpath is a single "\") */ + + if (ParentPath[1]) + { + ACPI_STRCAT (Fullpath, "."); + } + + /* Copy child path (carat parent prefix(es) were skipped above) */ + + ACPI_STRCAT (Fullpath, Path); + +Cleanup: + ACPI_FREE (ParentPath); + return (Fullpath); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddToExternalFileList + * + * PARAMETERS: PathList - Single path or list separated by comma + * + * RETURN: None + * + * DESCRIPTION: Add external files to global list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDmAddToExternalFileList ( + char *PathList) +{ + ACPI_EXTERNAL_FILE *ExternalFile; + char *Path; + char *TmpPath; + + + if (!PathList) + { + return (AE_OK); + } + + Path = strtok (PathList, ","); + + while (Path) + { + TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1); + if (!TmpPath) + { + return (AE_NO_MEMORY); + } + + ACPI_STRCPY (TmpPath, Path); + + ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); + if (!ExternalFile) + { + ACPI_FREE (TmpPath); + return (AE_NO_MEMORY); + } + + ExternalFile->Path = TmpPath; + + if (AcpiGbl_ExternalFileList) + { + ExternalFile->Next = AcpiGbl_ExternalFileList; + } + + AcpiGbl_ExternalFileList = ExternalFile; + Path = strtok (NULL, ","); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmClearExternalFileList + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Clear the external file list + * + ******************************************************************************/ + +void +AcpiDmClearExternalFileList ( + void) +{ + ACPI_EXTERNAL_FILE *NextExternal; + + + while (AcpiGbl_ExternalFileList) + { + NextExternal = AcpiGbl_ExternalFileList->Next; + ACPI_FREE (AcpiGbl_ExternalFileList->Path); + ACPI_FREE (AcpiGbl_ExternalFileList); + AcpiGbl_ExternalFileList = NextExternal; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddToExternalList + * + * PARAMETERS: Op - Current parser Op + * Path - Internal (AML) path to the object + * Type - ACPI object type to be added + * Value - Arg count if adding a Method object + * + * RETURN: None + * + * DESCRIPTION: Insert a new name into the global list of Externals which + * will in turn be later emitted as an External() declaration + * in the disassembled output. + * + ******************************************************************************/ + +void +AcpiDmAddToExternalList ( + ACPI_PARSE_OBJECT *Op, + char *Path, + UINT8 Type, + UINT32 Value) +{ + char *ExternalPath; + char *Fullpath = NULL; + ACPI_EXTERNAL_LIST *NewExternal; + ACPI_EXTERNAL_LIST *NextExternal; + ACPI_EXTERNAL_LIST *PrevExternal = NULL; + ACPI_STATUS Status; + + + if (!Path) + { + return; + } + + /* Externalize the ACPI path */ + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, + NULL, &ExternalPath); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Get the full pathname from root if "Path" has a parent prefix */ + + if (*Path == (UINT8) AML_PARENT_PREFIX) + { + Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); + if (Fullpath) + { + /* Set new external path */ + + ACPI_FREE (ExternalPath); + ExternalPath = Fullpath; + } + } + + /* Check all existing externals to ensure no duplicates */ + + NextExternal = AcpiGbl_ExternalList; + while (NextExternal) + { + if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) + { + /* Duplicate method, check that the Value (ArgCount) is the same */ + + if ((NextExternal->Type == ACPI_TYPE_METHOD) && + (NextExternal->Value != Value)) + { + ACPI_ERROR ((AE_INFO, + "Argument count mismatch for method %s %u %u", + NextExternal->Path, NextExternal->Value, Value)); + } + + /* Allow upgrade of type from ANY */ + + else if (NextExternal->Type == ACPI_TYPE_ANY) + { + NextExternal->Type = Type; + NextExternal->Value = Value; + } + + ACPI_FREE (ExternalPath); + return; + } + + NextExternal = NextExternal->Next; + } + + /* Allocate and init a new External() descriptor */ + + NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); + if (!NewExternal) + { + ACPI_FREE (ExternalPath); + return; + } + + NewExternal->Path = ExternalPath; + NewExternal->Type = Type; + NewExternal->Value = Value; + NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); + + /* Was the external path with parent prefix normalized to a fullpath? */ + + if (Fullpath == ExternalPath) + { + /* Get new internal path */ + + Status = AcpiNsInternalizeName (ExternalPath, &Path); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (ExternalPath); + ACPI_FREE (NewExternal); + return; + } + + /* Set flag to indicate External->InternalPath need to be freed */ + + NewExternal->Flags |= ACPI_IPATH_ALLOCATED; + } + + NewExternal->InternalPath = Path; + + /* Link the new descriptor into the global list, ordered by string length */ + + NextExternal = AcpiGbl_ExternalList; + while (NextExternal) + { + if (NewExternal->Length <= NextExternal->Length) + { + if (PrevExternal) + { + PrevExternal->Next = NewExternal; + } + else + { + AcpiGbl_ExternalList = NewExternal; + } + + NewExternal->Next = NextExternal; + return; + } + + PrevExternal = NextExternal; + NextExternal = NextExternal->Next; + } + + if (PrevExternal) + { + PrevExternal->Next = NewExternal; + } + else + { + AcpiGbl_ExternalList = NewExternal; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddExternalsToNamespace + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Add all externals to the namespace. Allows externals to be + * "resolved". + * + ******************************************************************************/ + +void +AcpiDmAddExternalsToNamespace ( + void) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *MethodDesc; + ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; + + + while (External) + { + /* Add the external name (object) into the namespace */ + + Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, + ACPI_IMODE_LOAD_PASS1, + ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &Node); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "while adding external to namespace [%s]", + External->Path)); + } + else if (External->Type == ACPI_TYPE_METHOD) + { + /* For methods, we need to save the argument count */ + + MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); + MethodDesc->Method.ParamCount = (UINT8) External->Value; + Node->Object = MethodDesc; + } + + External = External->Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGetExternalMethodCount + * + * PARAMETERS: None + * + * RETURN: The number of control method externals in the external list + * + * DESCRIPTION: Return the number of method externals that have been generated. + * If any control method externals have been found, we must + * re-parse the entire definition block with the new information + * (number of arguments for the methods.) This is limitation of + * AML, we don't know the number of arguments from the control + * method invocation itself. + * + ******************************************************************************/ + +UINT32 +AcpiDmGetExternalMethodCount ( + void) +{ + ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; + UINT32 Count = 0; + + + while (External) + { + if (External->Type == ACPI_TYPE_METHOD) + { + Count++; + } + + External = External->Next; + } + + return (Count); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmClearExternalList + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Free the entire External info list + * + ******************************************************************************/ + +void +AcpiDmClearExternalList ( + void) +{ + ACPI_EXTERNAL_LIST *NextExternal; + + + while (AcpiGbl_ExternalList) + { + NextExternal = AcpiGbl_ExternalList->Next; + ACPI_FREE (AcpiGbl_ExternalList->Path); + ACPI_FREE (AcpiGbl_ExternalList); + AcpiGbl_ExternalList = NextExternal; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmEmitExternals + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Emit an External() ASL statement for each of the externals in + * the global external info list. + * + ******************************************************************************/ + +void +AcpiDmEmitExternals ( + void) +{ + ACPI_EXTERNAL_LIST *NextExternal; + + + if (!AcpiGbl_ExternalList) + { + return; + } + + /* + * Walk the list of externals (unresolved references) + * found during the AML parsing + */ + while (AcpiGbl_ExternalList) + { + AcpiOsPrintf (" External (%s%s", + AcpiGbl_ExternalList->Path, + AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); + + if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) + { + AcpiOsPrintf (") // %u Arguments\n", + AcpiGbl_ExternalList->Value); + } + else + { + AcpiOsPrintf (")\n"); + } + + /* Free this external info block and move on to next external */ + + NextExternal = AcpiGbl_ExternalList->Next; + if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED) + { + ACPI_FREE (AcpiGbl_ExternalList->InternalPath); + } + + ACPI_FREE (AcpiGbl_ExternalList->Path); + ACPI_FREE (AcpiGbl_ExternalList); + AcpiGbl_ExternalList = NextExternal; + } + + AcpiOsPrintf ("\n"); +} + diff --git a/source/common/dmrestag.c b/source/common/dmrestag.c new file mode 100644 index 000000000000..13b3bbc3d46d --- /dev/null +++ b/source/common/dmrestag.c @@ -0,0 +1,1045 @@ +/****************************************************************************** + * + * Module Name: dmrestag - Add tags to resource descriptors (Application-level) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdisasm.h" +#include "acnamesp.h" +#include "amlcode.h" + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("dmrestag") + +/* Local prototypes */ + +static void +AcpiDmUpdateResourceName ( + ACPI_NAMESPACE_NODE *ResourceNode); + +static char * +AcpiDmSearchTagList ( + UINT32 BitIndex, + const ACPI_RESOURCE_TAG *TagList); + +static char * +AcpiDmGetResourceTag ( + UINT32 BitIndex, + AML_RESOURCE *Resource, + UINT8 ResourceIndex); + +static char * +AcpiGetTagPathname ( + ACPI_NAMESPACE_NODE *BufferNode, + ACPI_NAMESPACE_NODE *ResourceNode, + UINT32 BitIndex); + +static ACPI_NAMESPACE_NODE * +AcpiDmGetResourceNode ( + ACPI_NAMESPACE_NODE *BufferNode, + UINT32 BitIndex); + +static ACPI_STATUS +AcpiDmAddResourceToNamespace ( + UINT8 *Aml, + UINT32 Length, + UINT32 Offset, + UINT8 ResourceIndex, + void *Context); + +static void +AcpiDmAddResourcesToNamespace ( + ACPI_NAMESPACE_NODE *BufferNode, + ACPI_PARSE_OBJECT *Op); + + +/****************************************************************************** + * + * Resource Tag tables + * + * These are the predefined tags that refer to elements of a resource + * descriptor. Each name and offset is defined in the ACPI specification. + * + * Each table entry contains the bit offset of the field and the associated + * name. + * + ******************************************************************************/ + +static const ACPI_RESOURCE_TAG AcpiDmIrqTags[] = +{ + {( 1 * 8), ACPI_RESTAG_INTERRUPT}, + {( 3 * 8) + 0, ACPI_RESTAG_INTERRUPTTYPE}, + {( 3 * 8) + 3, ACPI_RESTAG_INTERRUPTLEVEL}, + {( 3 * 8) + 4, ACPI_RESTAG_INTERRUPTSHARE}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmDmaTags[] = +{ + {( 1 * 8), ACPI_RESTAG_DMA}, + {( 2 * 8) + 0, ACPI_RESTAG_XFERTYPE}, + {( 2 * 8) + 2, ACPI_RESTAG_BUSMASTER}, + {( 2 * 8) + 5, ACPI_RESTAG_DMATYPE}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmIoTags[] = +{ + {( 1 * 8) + 0, ACPI_RESTAG_DECODE}, + {( 2 * 8), ACPI_RESTAG_MINADDR}, + {( 4 * 8), ACPI_RESTAG_MAXADDR}, + {( 6 * 8), ACPI_RESTAG_ALIGNMENT}, + {( 7 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmFixedIoTags[] = +{ + {( 1 * 8), ACPI_RESTAG_BASEADDRESS}, + {( 3 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmFixedDmaTags[] = +{ + {( 1 * 8), ACPI_RESTAG_DMA}, + {( 3 * 8), ACPI_RESTAG_DMATYPE}, + {( 5 * 8), ACPI_RESTAG_XFERTYPE}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmMemory24Tags[] = +{ + {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, + {( 4 * 8), ACPI_RESTAG_MINADDR}, + {( 6 * 8), ACPI_RESTAG_MAXADDR}, + {( 8 * 8), ACPI_RESTAG_ALIGNMENT}, + {(10 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmRegisterTags[] = +{ + {( 3 * 8), ACPI_RESTAG_ADDRESSSPACE}, + {( 4 * 8), ACPI_RESTAG_REGISTERBITWIDTH}, + {( 5 * 8), ACPI_RESTAG_REGISTERBITOFFSET}, + {( 6 * 8), ACPI_RESTAG_ACCESSSIZE}, + {( 7 * 8), ACPI_RESTAG_ADDRESS}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmMemory32Tags[] = +{ + {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, + {( 4 * 8), ACPI_RESTAG_MINADDR}, + {( 8 * 8), ACPI_RESTAG_MAXADDR}, + {(12 * 8), ACPI_RESTAG_ALIGNMENT}, + {(16 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmFixedMemory32Tags[] = +{ + {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, + {( 4 * 8), ACPI_RESTAG_BASEADDRESS}, + {( 8 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmInterruptTags[] = +{ + {( 3 * 8) + 1, ACPI_RESTAG_INTERRUPTTYPE}, + {( 3 * 8) + 2, ACPI_RESTAG_INTERRUPTLEVEL}, + {( 3 * 8) + 3, ACPI_RESTAG_INTERRUPTSHARE}, + {( 5 * 8), ACPI_RESTAG_INTERRUPT}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmAddress16Tags[] = +{ + {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, + {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, + {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, + {( 6 * 8), ACPI_RESTAG_GRANULARITY}, + {( 8 * 8), ACPI_RESTAG_MINADDR}, + {(10 * 8), ACPI_RESTAG_MAXADDR}, + {(12 * 8), ACPI_RESTAG_TRANSLATION}, + {(14 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmAddress32Tags[] = +{ + {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, + {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, + {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, + {( 6 * 8), ACPI_RESTAG_GRANULARITY}, + {(10 * 8), ACPI_RESTAG_MINADDR}, + {(14 * 8), ACPI_RESTAG_MAXADDR}, + {(18 * 8), ACPI_RESTAG_TRANSLATION}, + {(22 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmAddress64Tags[] = +{ + {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, + {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, + {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, + {( 6 * 8), ACPI_RESTAG_GRANULARITY}, + {(14 * 8), ACPI_RESTAG_MINADDR}, + {(22 * 8), ACPI_RESTAG_MAXADDR}, + {(30 * 8), ACPI_RESTAG_TRANSLATION}, + {(38 * 8), ACPI_RESTAG_LENGTH}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmExtendedAddressTags[] = +{ + {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, + {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, + {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, + {( 8 * 8), ACPI_RESTAG_GRANULARITY}, + {(16 * 8), ACPI_RESTAG_MINADDR}, + {(24 * 8), ACPI_RESTAG_MAXADDR}, + {(32 * 8), ACPI_RESTAG_TRANSLATION}, + {(40 * 8), ACPI_RESTAG_LENGTH}, + {(48 * 8), ACPI_RESTAG_TYPESPECIFICATTRIBUTES}, + {0, NULL} +}; + +/* Subtype tables for GPIO descriptors */ + +static const ACPI_RESOURCE_TAG AcpiDmGpioIntTags[] = +{ + {( 7 * 8) + 0, ACPI_RESTAG_MODE}, + {( 7 * 8) + 1, ACPI_RESTAG_POLARITY}, + {( 7 * 8) + 3, ACPI_RESTAG_INTERRUPTSHARE}, + {( 9 * 8), ACPI_RESTAG_PINCONFIG}, + {(10 * 8), ACPI_RESTAG_DRIVESTRENGTH}, + {(12 * 8), ACPI_RESTAG_DEBOUNCETIME}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmGpioIoTags[] = +{ + {( 7 * 8) + 0, ACPI_RESTAG_IORESTRICTION}, + {( 7 * 8) + 3, ACPI_RESTAG_INTERRUPTSHARE}, + {( 9 * 8), ACPI_RESTAG_PINCONFIG}, + {(10 * 8), ACPI_RESTAG_DRIVESTRENGTH}, + {(12 * 8), ACPI_RESTAG_DEBOUNCETIME}, + {0, NULL} +}; + +/* Subtype tables for SerialBus descriptors */ + +static const ACPI_RESOURCE_TAG AcpiDmI2cSerialBusTags[] = +{ + {( 6 * 8) + 0, ACPI_RESTAG_SLAVEMODE}, + {( 7 * 8) + 0, ACPI_RESTAG_MODE}, + {(12 * 8), ACPI_RESTAG_SPEED}, + {(16 * 8), ACPI_RESTAG_ADDRESS}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmSpiSerialBusTags[] = +{ + {( 6 * 8) + 0, ACPI_RESTAG_SLAVEMODE}, + {( 7 * 8) + 0, ACPI_RESTAG_MODE}, + {( 7 * 8) + 1, ACPI_RESTAG_DEVICEPOLARITY}, + {(12 * 8), ACPI_RESTAG_SPEED}, + {(16 * 8), ACPI_RESTAG_LENGTH}, + {(17 * 8), ACPI_RESTAG_PHASE}, + {(18 * 8), ACPI_RESTAG_POLARITY}, + {(19 * 8), ACPI_RESTAG_ADDRESS}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmUartSerialBusTags[] = +{ + {( 6 * 8) + 0, ACPI_RESTAG_SLAVEMODE}, /* Note: not part of original macro */ + {( 7 * 8) + 0, ACPI_RESTAG_FLOWCONTROL}, + {( 7 * 8) + 2, ACPI_RESTAG_STOPBITS}, + {( 7 * 8) + 4, ACPI_RESTAG_LENGTH}, + {( 7 * 8) + 7, ACPI_RESTAG_ENDIANNESS}, + {(12 * 8), ACPI_RESTAG_SPEED}, + {(16 * 8), ACPI_RESTAG_LENGTH_RX}, + {(18 * 8), ACPI_RESTAG_LENGTH_TX}, + {(20 * 8), ACPI_RESTAG_PARITY}, + {(21 * 8), ACPI_RESTAG_LINE}, + {0, NULL} +}; + +/* Subtype tables for Address descriptor type-specific flags */ + +static const ACPI_RESOURCE_TAG AcpiDmMemoryFlagTags[] = +{ + {( 5 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, + {( 5 * 8) + 1, ACPI_RESTAG_MEMTYPE}, + {( 5 * 8) + 3, ACPI_RESTAG_MEMATTRIBUTES}, + {( 5 * 8) + 5, ACPI_RESTAG_TYPE}, + {0, NULL} +}; + +static const ACPI_RESOURCE_TAG AcpiDmIoFlagTags[] = +{ + {( 5 * 8) + 0, ACPI_RESTAG_RANGETYPE}, + {( 5 * 8) + 4, ACPI_RESTAG_TYPE}, + {( 5 * 8) + 5, ACPI_RESTAG_TRANSTYPE}, + {0, NULL} +}; + + +/* + * Dispatch table used to obtain the correct tag table for a descriptor. + * + * A NULL in this table means one of three things: + * 1) The descriptor ID is reserved and invalid + * 2) The descriptor has no tags associated with it + * 3) The descriptor has subtypes and a separate table will be used. + */ +static const ACPI_RESOURCE_TAG *AcpiGbl_ResourceTags[] = +{ + /* Small descriptors */ + + NULL, /* 0x00, Reserved */ + NULL, /* 0x01, Reserved */ + NULL, /* 0x02, Reserved */ + NULL, /* 0x03, Reserved */ + AcpiDmIrqTags, /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */ + AcpiDmDmaTags, /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */ + NULL, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ + NULL, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ + AcpiDmIoTags, /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */ + AcpiDmFixedIoTags, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */ + AcpiDmFixedDmaTags, /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */ + NULL, /* 0x0B, Reserved */ + NULL, /* 0x0C, Reserved */ + NULL, /* 0x0D, Reserved */ + NULL, /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */ + NULL, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */ + + /* Large descriptors */ + + NULL, /* 0x00, Reserved */ + AcpiDmMemory24Tags, /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */ + AcpiDmRegisterTags, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ + NULL, /* 0x03, Reserved */ + NULL, /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */ + AcpiDmMemory32Tags, /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */ + AcpiDmFixedMemory32Tags, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */ + AcpiDmAddress32Tags, /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */ + AcpiDmAddress16Tags, /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */ + AcpiDmInterruptTags, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */ + AcpiDmAddress64Tags, /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */ + AcpiDmExtendedAddressTags, /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */ + NULL, /* 0x0C, ACPI_RESOURCE_NAME_GPIO - Use Subtype table below */ + NULL, /* 0x0D, Reserved */ + NULL /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use Subtype table below */ +}; + +/* GPIO Subtypes */ + +static const ACPI_RESOURCE_TAG *AcpiGbl_GpioResourceTags[] = +{ + AcpiDmGpioIntTags, /* 0x00 Interrupt Connection */ + AcpiDmGpioIoTags /* 0x01 I/O Connection */ +}; + +/* Serial Bus Subtypes */ + +static const ACPI_RESOURCE_TAG *AcpiGbl_SerialResourceTags[] = +{ + NULL, /* 0x00 Reserved */ + AcpiDmI2cSerialBusTags, /* 0x01 I2C SerialBus */ + AcpiDmSpiSerialBusTags, /* 0x02 SPI SerialBus */ + AcpiDmUartSerialBusTags /* 0x03 UART SerialBus */ +}; + +/* + * Globals used to generate unique resource descriptor names. We use names that + * start with underscore and a prefix letter that is not used by other ACPI + * reserved names. To this, we append hex 0x00 through 0xFF. These 5 prefixes + * allow for 5*256 = 1280 unique names, probably sufficient for any single ASL + * file. If this becomes too small, we can use alpha+numerals for a total + * of 5*36*36 = 6480. + */ +#define ACPI_NUM_RES_PREFIX 5 + +static UINT32 AcpiGbl_NextResourceId = 0; +static UINT8 AcpiGbl_NextPrefix = 0; +static char AcpiGbl_Prefix[ACPI_NUM_RES_PREFIX] = + {'Y','Z','J','K','X'}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCheckResourceReference + * + * PARAMETERS: Op - Parse Op for the AML opcode + * WalkState - Current walk state (with valid scope) + * + * RETURN: None + * + * DESCRIPTION: Convert a reference to a resource descriptor to a symbolic + * reference if possible + * + * NOTE: Bit index is used to transparently handle both resource bit + * fields and byte fields. + * + ******************************************************************************/ + +void +AcpiDmCheckResourceReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *BufferNameOp; + ACPI_PARSE_OBJECT *IndexOp; + ACPI_NAMESPACE_NODE *BufferNode; + ACPI_NAMESPACE_NODE *ResourceNode; + const ACPI_OPCODE_INFO *OpInfo; + char *Pathname; + UINT32 BitIndex; + + + /* We are only interested in the CreateXxxxField opcodes */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (OpInfo->Type != AML_TYPE_CREATE_FIELD) + { + return; + } + + /* Get the buffer term operand */ + + BufferNameOp = AcpiPsGetDepthNext (NULL, Op); + + /* Must be a named buffer, not an arg or local or method call */ + + if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP) + { + return; + } + + /* Get the Index term, must be an integer constant to convert */ + + IndexOp = BufferNameOp->Common.Next; + OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode); + if (OpInfo->ObjectType != ACPI_TYPE_INTEGER) + { + return; + } + + /* Get the bit offset of the descriptor within the buffer */ + + if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) || + (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)) + { + /* Index operand is a bit offset */ + + BitIndex = (UINT32) IndexOp->Common.Value.Integer; + } + else + { + /* Index operand is a byte offset, convert to bits */ + + BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer); + } + + /* Lookup the buffer in the namespace */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, + BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, + &BufferNode); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Validate object type, we must have a buffer */ + + if (BufferNode->Type != ACPI_TYPE_BUFFER) + { + return; + } + + /* Find the resource descriptor node corresponding to the index */ + + ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex); + if (!ResourceNode) + { + return; + } + + /* Translate the Index to a resource tag pathname */ + + Pathname = AcpiGetTagPathname (BufferNode, ResourceNode, BitIndex); + if (Pathname) + { + /* Complete the conversion of the Index to a symbol */ + + IndexOp->Common.AmlOpcode = AML_INT_NAMEPATH_OP; + IndexOp->Common.Value.String = Pathname; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGetResourceNode + * + * PARAMETERS: BufferNode - Node for the parent buffer + * BitIndex - Index into the resource descriptor + * + * RETURN: Namespace node for the resource descriptor. NULL if not found + * + * DESCRIPTION: Find a resource descriptor that corresponds to the bit index + * + ******************************************************************************/ + +static ACPI_NAMESPACE_NODE * +AcpiDmGetResourceNode ( + ACPI_NAMESPACE_NODE *BufferNode, + UINT32 BitIndex) +{ + ACPI_NAMESPACE_NODE *Node; + UINT32 ByteIndex = ACPI_DIV_8 (BitIndex); + + + /* + * Child list contains an entry for each resource descriptor. Find + * the descriptor that corresponds to the Index. + * + * If there are no children, this is not a resource template + */ + Node = BufferNode->Child; + while (Node) + { + /* + * Check if the Index falls within this resource. + * + * Value contains the resource offset, Object contains the resource + * length (both in bytes) + */ + if ((ByteIndex >= Node->Value) && + (ByteIndex < (Node->Value + Node->Length))) + { + return (Node); + } + + Node = Node->Peer; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTagPathname + * + * PARAMETERS: BufferNode - Node for the parent buffer + * ResourceNode - Node for a resource descriptor + * BitIndex - Index into the resource descriptor + * + * RETURN: Full pathname for a resource tag. NULL if no match. + * Path is returned in AML (packed) format. + * + * DESCRIPTION: Convert a BitIndex into a symbolic resource tag (full pathname) + * + ******************************************************************************/ + +static char * +AcpiGetTagPathname ( + ACPI_NAMESPACE_NODE *BufferNode, + ACPI_NAMESPACE_NODE *ResourceNode, + UINT32 BitIndex) +{ + ACPI_STATUS Status; + UINT32 ResourceBitIndex; + UINT8 ResourceTableIndex; + ACPI_SIZE RequiredSize; + char *Pathname; + AML_RESOURCE *Aml; + ACPI_PARSE_OBJECT *Op; + char *InternalPath; + char *Tag; + + + /* Get the Op that contains the actual buffer data */ + + Op = BufferNode->Op->Common.Value.Arg; + Op = Op->Common.Next; + if (!Op) + { + return (NULL); + } + + /* Get the individual resource descriptor and validate it */ + + Aml = ACPI_CAST_PTR (AML_RESOURCE, + &Op->Named.Data[ResourceNode->Value]); + + Status = AcpiUtValidateResource (Aml, &ResourceTableIndex); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + /* Get offset into this descriptor (from offset into entire buffer) */ + + ResourceBitIndex = BitIndex - ACPI_MUL_8 (ResourceNode->Value); + + /* Get the tag associated with this resource descriptor and offset */ + + Tag = AcpiDmGetResourceTag (ResourceBitIndex, Aml, ResourceTableIndex); + if (!Tag) + { + return (NULL); + } + + /* + * Now that we know that we have a reference that can be converted to a + * symbol, change the name of the resource to a unique name. + */ + AcpiDmUpdateResourceName (ResourceNode); + + /* Get the full pathname to the parent buffer */ + + RequiredSize = AcpiNsGetPathnameLength (BufferNode); + if (!RequiredSize) + { + return (NULL); + } + + Pathname = ACPI_ALLOCATE_ZEROED (RequiredSize + ACPI_PATH_SEGMENT_LENGTH); + if (!Pathname) + { + return (NULL); + } + + Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + /* + * Create the full path to the resource and tag by: remove the buffer name, + * append the resource descriptor name, append a dot, append the tag name. + * + * TBD: Always using the full path is a bit brute force, the path can be + * often be optimized with carats (if the original buffer namepath is a + * single nameseg). This doesn't really matter, because these paths do not + * end up in the final compiled AML, it's just an appearance issue for the + * disassembled code. + */ + Pathname[ACPI_STRLEN (Pathname) - ACPI_NAME_SIZE] = 0; + ACPI_STRNCAT (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE); + ACPI_STRCAT (Pathname, "."); + ACPI_STRNCAT (Pathname, Tag, ACPI_NAME_SIZE); + + /* Internalize the namepath to AML format */ + + AcpiNsInternalizeName (Pathname, &InternalPath); + ACPI_FREE (Pathname); + return (InternalPath); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmUpdateResourceName + * + * PARAMETERS: ResourceNode - Node for a resource descriptor + * + * RETURN: Stores new name in the ResourceNode + * + * DESCRIPTION: Create a new, unique name for a resource descriptor. Used by + * both the disassembly of the descriptor itself and any symbolic + * references to the descriptor. Ignored if a unique name has + * already been assigned to the resource. + * + * NOTE: Single threaded, suitable for applications only! + * + ******************************************************************************/ + +static void +AcpiDmUpdateResourceName ( + ACPI_NAMESPACE_NODE *ResourceNode) +{ + char Name[ACPI_NAME_SIZE]; + + + /* Ignore if a unique name has already been assigned */ + + if (ResourceNode->Name.Integer != ACPI_DEFAULT_RESNAME) + { + return; + } + + /* Generate a new ACPI name for the descriptor */ + + Name[0] = '_'; + Name[1] = AcpiGbl_Prefix[AcpiGbl_NextPrefix]; + Name[2] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 4); + Name[3] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 0); + + /* Update globals for next name */ + + AcpiGbl_NextResourceId++; + if (AcpiGbl_NextResourceId >= 256) + { + AcpiGbl_NextResourceId = 0; + AcpiGbl_NextPrefix++; + if (AcpiGbl_NextPrefix > ACPI_NUM_RES_PREFIX) + { + AcpiGbl_NextPrefix = 0; + } + } + + /* Change the resource descriptor name */ + + ResourceNode->Name.Integer = *ACPI_CAST_PTR (UINT32, &Name[0]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGetResourceTag + * + * PARAMETERS: BitIndex - Index into the resource descriptor + * Resource - Pointer to the raw resource data + * ResourceIndex - Index correspoinding to the resource type + * + * RETURN: Pointer to the resource tag (ACPI_NAME). NULL if no match. + * + * DESCRIPTION: Convert a BitIndex into a symbolic resource tag. + * + * Note: ResourceIndex should be previously validated and guaranteed to ve + * valid. + * + ******************************************************************************/ + +static char * +AcpiDmGetResourceTag ( + UINT32 BitIndex, + AML_RESOURCE *Resource, + UINT8 ResourceIndex) +{ + const ACPI_RESOURCE_TAG *TagList; + char *Tag = NULL; + + + /* Get the tag list for this resource descriptor type */ + + TagList = AcpiGbl_ResourceTags[ResourceIndex]; + + /* + * Handle descriptors that have multiple subtypes + */ + switch (Resource->DescriptorType) + { + case ACPI_RESOURCE_NAME_ADDRESS16: + case ACPI_RESOURCE_NAME_ADDRESS32: + case ACPI_RESOURCE_NAME_ADDRESS64: + case ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64: + + /* + * Subtype differentiation is the flags. + * Kindof brute force, but just blindly search for an index match + */ + if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_MEMORY_RANGE) + { + Tag = AcpiDmSearchTagList (BitIndex, AcpiDmMemoryFlagTags); + } + else if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_IO_RANGE) + { + Tag = AcpiDmSearchTagList (BitIndex, AcpiDmIoFlagTags); + } + + /* If we found a match, all done. Else, drop to normal search below */ + + if (Tag) + { + return (Tag); + } + break; + + case ACPI_RESOURCE_NAME_GPIO: + + /* GPIO connection has 2 subtypes: Interrupt and I/O */ + + if (Resource->Gpio.ConnectionType > AML_RESOURCE_MAX_GPIOTYPE) + { + return (NULL); + } + + TagList = AcpiGbl_GpioResourceTags[Resource->Gpio.ConnectionType]; + break; + + case ACPI_RESOURCE_NAME_SERIAL_BUS: + + /* SerialBus has 3 subtypes: I2C, SPI, and UART */ + + if ((Resource->CommonSerialBus.Type == 0) || + (Resource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE)) + { + return (NULL); + } + + TagList = AcpiGbl_SerialResourceTags[Resource->CommonSerialBus.Type]; + break; + + default: + break; + } + + /* Search for a match against the BitIndex */ + + if (TagList) + { + Tag = AcpiDmSearchTagList (BitIndex, TagList); + } + + return (Tag); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmSearchTagList + * + * PARAMETERS: BitIndex - Index into the resource descriptor + * TagList - List to search + * + * RETURN: Pointer to a tag (ACPI_NAME). NULL if no match found. + * + * DESCRIPTION: Search a tag list for a match to the input BitIndex. Matches + * a fixed offset to a symbolic resource tag name. + * + ******************************************************************************/ + +static char * +AcpiDmSearchTagList ( + UINT32 BitIndex, + const ACPI_RESOURCE_TAG *TagList) +{ + + /* + * Walk the null-terminated tag list to find a matching bit offset. + * We are looking for an exact match. + */ + for ( ; TagList->Tag; TagList++) + { + if (BitIndex == TagList->BitIndex) + { + return (TagList->Tag); + } + } + + /* A matching offset was not found */ + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFindResources + * + * PARAMETERS: Root - Root of the parse tree + * + * RETURN: None + * + * DESCRIPTION: Add all ResourceTemplate declarations to the namespace. Each + * resource descriptor in each template is given a node -- used + * for later conversion of resource references to symbolic refs. + * + ******************************************************************************/ + +void +AcpiDmFindResources ( + ACPI_PARSE_OBJECT *Root) +{ + ACPI_PARSE_OBJECT *Op = Root; + ACPI_PARSE_OBJECT *Parent; + + + /* Walk the entire parse tree */ + + while (Op) + { + /* We are interested in Buffer() declarations */ + + if (Op->Common.AmlOpcode == AML_BUFFER_OP) + { + /* And only declarations of the form Name (XXXX, Buffer()... ) */ + + Parent = Op->Common.Parent; + if (Parent->Common.AmlOpcode == AML_NAME_OP) + { + /* + * If the buffer is a resource template, add the individual + * resource descriptors to the namespace, as children of the + * buffer node. + */ + if (ACPI_SUCCESS (AcpiDmIsResourceTemplate (Op))) + { + Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; + AcpiDmAddResourcesToNamespace (Parent->Common.Node, Op); + } + } + } + + Op = AcpiPsGetDepthNext (Root, Op); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddResourcesToNamespace + * + * PARAMETERS: BufferNode - Node for the parent buffer + * Op - Parse op for the buffer + * + * RETURN: None + * + * DESCRIPTION: Add an entire resource template to the namespace. Each + * resource descriptor is added as a namespace node. + * + ******************************************************************************/ + +static void +AcpiDmAddResourcesToNamespace ( + ACPI_NAMESPACE_NODE *BufferNode, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *NextOp; + + + /* Get to the ByteData list */ + + NextOp = Op->Common.Value.Arg; + NextOp = NextOp->Common.Next; + if (!NextOp) + { + return; + } + + /* Set Node and Op to point to each other */ + + BufferNode->Op = Op; + Op->Common.Node = BufferNode; + + /* + * Insert each resource into the namespace + * NextOp contains the Aml pointer and the Aml length + */ + AcpiUtWalkAmlResources ((UINT8 *) NextOp->Named.Data, + (ACPI_SIZE) NextOp->Common.Value.Integer, + AcpiDmAddResourceToNamespace, BufferNode); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddResourceToNamespace + * + * PARAMETERS: ACPI_WALK_AML_CALLBACK + * BufferNode - Node for the parent buffer + * + * RETURN: Status + * + * DESCRIPTION: Add one resource descriptor to the namespace as a child of the + * parent buffer. The same name is used for each descriptor. This + * is changed later to a unique name if the resource is actually + * referenced by an AML operator. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmAddResourceToNamespace ( + UINT8 *Aml, + UINT32 Length, + UINT32 Offset, + UINT8 ResourceIndex, + void *Context) +{ + ACPI_STATUS Status; + ACPI_GENERIC_STATE ScopeInfo; + ACPI_NAMESPACE_NODE *Node; + + + /* TBD: Don't need to add descriptors that have no tags defined? */ + + /* Add the resource to the namespace, as child of the buffer */ + + ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Context); + Status = AcpiNsLookup (&ScopeInfo, "_TMP", ACPI_TYPE_LOCAL_RESOURCE, + ACPI_IMODE_LOAD_PASS2, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_PREFIX_IS_SCOPE, + NULL, &Node); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + /* Set the name to the default, changed later if resource is referenced */ + + Node->Name.Integer = ACPI_DEFAULT_RESNAME; + + /* Save the offset of the descriptor (within the original buffer) */ + + Node->Value = Offset; + Node->Length = Length; + return (AE_OK); +} + diff --git a/source/common/dmtable.c b/source/common/dmtable.c new file mode 100644 index 000000000000..eceef4f51bf0 --- /dev/null +++ b/source/common/dmtable.c @@ -0,0 +1,1204 @@ +/****************************************************************************** + * + * Module Name: dmtable - Support for ACPI tables that contain no AML code + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" +#include "actables.h" +#include "aslcompiler.h" +#include "dtcompiler.h" + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("dmtable") + +/* Local Prototypes */ + +static void +AcpiDmCheckAscii ( + UINT8 *Target, + char *RepairedName, + UINT32 Count); + + +/* Common format strings for commented values */ + +#define UINT8_FORMAT "%2.2X [%s]\n" +#define UINT16_FORMAT "%4.4X [%s]\n" +#define UINT32_FORMAT "%8.8X [%s]\n" +#define STRING_FORMAT "[%s]\n" + +/* These tables map a subtable type to a description string */ + +static const char *AcpiDmAsfSubnames[] = +{ + "ASF Information", + "ASF Alerts", + "ASF Remote Control", + "ASF RMCP Boot Options", + "ASF Address", + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmDmarSubnames[] = +{ + "Hardware Unit Definition", + "Reserved Memory Region", + "Root Port ATS Capability", + "Remapping Hardware Static Affinity", + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmEinjActions[] = +{ + "Begin Operation", + "Get Trigger Table", + "Set Error Type", + "Get Error Type", + "End Operation", + "Execute Operation", + "Check Busy Status", + "Get Command Status", + "Unknown Action" +}; + +static const char *AcpiDmEinjInstructions[] = +{ + "Read Register", + "Read Register Value", + "Write Register", + "Write Register Value", + "Noop", + "Unknown Instruction" +}; + +static const char *AcpiDmErstActions[] = +{ + "Begin Write Operation", + "Begin Read Operation", + "Begin Clear Operation", + "End Operation", + "Set Record Offset", + "Execute Operation", + "Check Busy Status", + "Get Command Status", + "Get Record Identifier", + "Set Record Identifier", + "Get Record Count", + "Begin Dummy Write", + "Unused/Unknown Action", + "Get Error Address Range", + "Get Error Address Length", + "Get Error Attributes", + "Unknown Action" +}; + +static const char *AcpiDmErstInstructions[] = +{ + "Read Register", + "Read Register Value", + "Write Register", + "Write Register Value", + "Noop", + "Load Var1", + "Load Var2", + "Store Var1", + "Add", + "Subtract", + "Add Value", + "Subtract Value", + "Stall", + "Stall While True", + "Skip Next If True", + "GoTo", + "Set Source Address", + "Set Destination Address", + "Move Data", + "Unknown Instruction" +}; + +static const char *AcpiDmHestSubnames[] = +{ + "IA-32 Machine Check Exception", + "IA-32 Corrected Machine Check", + "IA-32 Non-Maskable Interrupt", + "Unknown SubTable Type", /* 3 - Reserved */ + "Unknown SubTable Type", /* 4 - Reserved */ + "Unknown SubTable Type", /* 5 - Reserved */ + "PCI Express Root Port AER", + "PCI Express AER (AER Endpoint)", + "PCI Express/PCI-X Bridge AER", + "Generic Hardware Error Source", + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmHestNotifySubnames[] = +{ + "Polled", + "External Interrupt", + "Local Interrupt", + "SCI", + "NMI", + "Unknown Notify Type" /* Reserved */ +}; + +static const char *AcpiDmMadtSubnames[] = +{ + "Processor Local APIC", /* ACPI_MADT_TYPE_LOCAL_APIC */ + "I/O APIC", /* ACPI_MADT_TYPE_IO_APIC */ + "Interrupt Source Override", /* ACPI_MADT_TYPE_INTERRUPT_OVERRIDE */ + "NMI Source", /* ACPI_MADT_TYPE_NMI_SOURCE */ + "Local APIC NMI", /* ACPI_MADT_TYPE_LOCAL_APIC_NMI */ + "Local APIC Address Override", /* ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE */ + "I/O SAPIC", /* ACPI_MADT_TYPE_IO_SAPIC */ + "Local SAPIC", /* ACPI_MADT_TYPE_LOCAL_SAPIC */ + "Platform Interrupt Sources", /* ACPI_MADT_TYPE_INTERRUPT_SOURCE */ + "Processor Local x2APIC", /* ACPI_MADT_TYPE_LOCAL_X2APIC */ + "Local x2APIC NMI", /* ACPI_MADT_TYPE_LOCAL_X2APIC_NMI */ + "Generic Interrupt Controller", /* ACPI_MADT_GENERIC_INTERRUPT */ + "Generic Interrupt Distributor",/* ACPI_MADT_GENERIC_DISTRIBUTOR */ + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmPmttSubnames[] = +{ + "Socket", /* ACPI_PMTT_TYPE_SOCKET */ + "Memory Controller", /* ACPI_PMTT_TYPE_CONTROLLER */ + "Physical Component (DIMM)", /* ACPI_PMTT_TYPE_DIMM */ + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmSlicSubnames[] = +{ + "Public Key Structure", + "Windows Marker Structure", + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmSratSubnames[] = +{ + "Processor Local APIC/SAPIC Affinity", + "Memory Affinity", + "Processor Local x2APIC Affinity", + "Unknown SubTable Type" /* Reserved */ +}; + +static const char *AcpiDmIvrsSubnames[] = +{ + "Hardware Definition Block", + "Memory Definition Block", + "Unknown SubTable Type" /* Reserved */ +}; + + +#define ACPI_FADT_PM_RESERVED 9 + +static const char *AcpiDmFadtProfiles[] = +{ + "Unspecified", + "Desktop", + "Mobile", + "Workstation", + "Enterprise Server", + "SOHO Server", + "Appliance PC", + "Performance Server", + "Tablet", + "Unknown Profile Type" +}; + +#define ACPI_GAS_WIDTH_RESERVED 5 + +static const char *AcpiDmGasAccessWidth[] = +{ + "Undefined/Legacy", + "Byte Access:8", + "Word Access:16", + "DWord Access:32", + "QWord Access:64", + "Unknown Width Encoding" +}; + + +/******************************************************************************* + * + * ACPI Table Data, indexed by signature. + * + * Each entry contains: Signature, Table Info, Handler, DtHandler, + * Template, Description + * + * Simple tables have only a TableInfo structure, complex tables have a + * handler. This table must be NULL terminated. RSDP and FACS are + * special-cased elsewhere. + * + ******************************************************************************/ + +ACPI_DMTABLE_DATA AcpiDmTableData[] = +{ + {ACPI_SIG_ASF, NULL, AcpiDmDumpAsf, DtCompileAsf, TemplateAsf, "Alert Standard Format table"}, + {ACPI_SIG_BOOT, AcpiDmTableInfoBoot, NULL, NULL, TemplateBoot, "Simple Boot Flag Table"}, + {ACPI_SIG_BERT, AcpiDmTableInfoBert, NULL, NULL, TemplateBert, "Boot Error Record Table"}, + {ACPI_SIG_BGRT, AcpiDmTableInfoBgrt, NULL, NULL, TemplateBgrt, "Boot Graphics Resource Table"}, + {ACPI_SIG_CPEP, NULL, AcpiDmDumpCpep, DtCompileCpep, TemplateCpep, "Corrected Platform Error Polling table"}, + {ACPI_SIG_DBGP, AcpiDmTableInfoDbgp, NULL, NULL, TemplateDbgp, "Debug Port table"}, + {ACPI_SIG_DMAR, NULL, AcpiDmDumpDmar, DtCompileDmar, TemplateDmar, "DMA Remapping table"}, + {ACPI_SIG_ECDT, AcpiDmTableInfoEcdt, NULL, NULL, TemplateEcdt, "Embedded Controller Boot Resources Table"}, + {ACPI_SIG_EINJ, NULL, AcpiDmDumpEinj, DtCompileEinj, TemplateEinj, "Error Injection table"}, + {ACPI_SIG_ERST, NULL, AcpiDmDumpErst, DtCompileErst, TemplateErst, "Error Record Serialization Table"}, + {ACPI_SIG_FADT, NULL, AcpiDmDumpFadt, DtCompileFadt, TemplateFadt, "Fixed ACPI Description Table"}, + {ACPI_SIG_FPDT, NULL, AcpiDmDumpFpdt, DtCompileFpdt, TemplateFpdt, "Firmware Performance Data Table"}, + {ACPI_SIG_GTDT, AcpiDmTableInfoGtdt, NULL, NULL, TemplateGtdt, "Generic Timer Description Table"}, + {ACPI_SIG_HEST, NULL, AcpiDmDumpHest, DtCompileHest, TemplateHest, "Hardware Error Source Table"}, + {ACPI_SIG_HPET, AcpiDmTableInfoHpet, NULL, NULL, TemplateHpet, "High Precision Event Timer table"}, + {ACPI_SIG_IVRS, NULL, AcpiDmDumpIvrs, DtCompileIvrs, TemplateIvrs, "I/O Virtualization Reporting Structure"}, + {ACPI_SIG_MADT, NULL, AcpiDmDumpMadt, DtCompileMadt, TemplateMadt, "Multiple APIC Description Table"}, + {ACPI_SIG_MCFG, NULL, AcpiDmDumpMcfg, DtCompileMcfg, TemplateMcfg, "Memory Mapped Configuration table"}, + {ACPI_SIG_MCHI, AcpiDmTableInfoMchi, NULL, NULL, TemplateMchi, "Management Controller Host Interface table"}, + {ACPI_SIG_MPST, AcpiDmTableInfoMpst, AcpiDmDumpMpst, DtCompileMpst, TemplateMpst, "Memory Power State Table"}, + {ACPI_SIG_MSCT, NULL, AcpiDmDumpMsct, DtCompileMsct, TemplateMsct, "Maximum System Characteristics Table"}, + {ACPI_SIG_PCCT, NULL, AcpiDmDumpPcct, NULL, NULL, "Platform Communications Channel Table"}, + {ACPI_SIG_PMTT, NULL, AcpiDmDumpPmtt, DtCompilePmtt, TemplatePmtt, "Platform Memory Topology Table"}, + {ACPI_SIG_RSDT, NULL, AcpiDmDumpRsdt, DtCompileRsdt, TemplateRsdt, "Root System Description Table"}, + {ACPI_SIG_S3PT, NULL, NULL, NULL, TemplateS3pt, "S3 Performance Table"}, + {ACPI_SIG_SBST, AcpiDmTableInfoSbst, NULL, NULL, TemplateSbst, "Smart Battery Specification Table"}, + {ACPI_SIG_SLIC, NULL, AcpiDmDumpSlic, DtCompileSlic, TemplateSlic, "Software Licensing Description Table"}, + {ACPI_SIG_SLIT, NULL, AcpiDmDumpSlit, DtCompileSlit, TemplateSlit, "System Locality Information Table"}, + {ACPI_SIG_SPCR, AcpiDmTableInfoSpcr, NULL, NULL, TemplateSpcr, "Serial Port Console Redirection table"}, + {ACPI_SIG_SPMI, AcpiDmTableInfoSpmi, NULL, NULL, TemplateSpmi, "Server Platform Management Interface table"}, + {ACPI_SIG_SRAT, NULL, AcpiDmDumpSrat, DtCompileSrat, TemplateSrat, "System Resource Affinity Table"}, + {ACPI_SIG_TCPA, AcpiDmTableInfoTcpa, NULL, NULL, TemplateTcpa, "Trusted Computing Platform Alliance table"}, + {ACPI_SIG_UEFI, AcpiDmTableInfoUefi, NULL, DtCompileUefi, TemplateUefi, "UEFI Boot Optimization Table"}, + {ACPI_SIG_WAET, AcpiDmTableInfoWaet, NULL, NULL, TemplateWaet, "Windows ACPI Emulated Devices Table"}, + {ACPI_SIG_WDAT, NULL, AcpiDmDumpWdat, DtCompileWdat, TemplateWdat, "Watchdog Action Table"}, + {ACPI_SIG_WDDT, AcpiDmTableInfoWddt, NULL, NULL, TemplateWddt, "Watchdog Description Table"}, + {ACPI_SIG_WDRT, AcpiDmTableInfoWdrt, NULL, NULL, TemplateWdrt, "Watchdog Resource Table"}, + {ACPI_SIG_XSDT, NULL, AcpiDmDumpXsdt, DtCompileXsdt, TemplateXsdt, "Extended System Description Table"}, + {NULL, NULL, NULL, NULL, NULL, NULL} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGenerateChecksum + * + * PARAMETERS: Table - Pointer to table to be checksummed + * Length - Length of the table + * OriginalChecksum - Value of the checksum field + * + * RETURN: 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the table. + * + ******************************************************************************/ + +UINT8 +AcpiDmGenerateChecksum ( + void *Table, + UINT32 Length, + UINT8 OriginalChecksum) +{ + UINT8 Checksum; + + + /* Sum the entire table as-is */ + + Checksum = AcpiTbChecksum ((UINT8 *) Table, Length); + + /* Subtract off the existing checksum value in the table */ + + Checksum = (UINT8) (Checksum - OriginalChecksum); + + /* Compute the final checksum */ + + Checksum = (UINT8) (0 - Checksum); + return (Checksum); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGetTableData + * + * PARAMETERS: Signature - ACPI signature (4 chars) to match + * + * RETURN: Pointer to a valid ACPI_DMTABLE_DATA. Null if no match found. + * + * DESCRIPTION: Find a match in the global table of supported ACPI tables + * + ******************************************************************************/ + +ACPI_DMTABLE_DATA * +AcpiDmGetTableData ( + char *Signature) +{ + ACPI_DMTABLE_DATA *TableData; + + + for (TableData = AcpiDmTableData; TableData->Signature; TableData++) + { + if (ACPI_COMPARE_NAME (Signature, TableData->Signature)) + { + return (TableData); + } + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpDataTable + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: None. + * + * DESCRIPTION: Format the contents of an ACPI data table (any table other + * than an SSDT or DSDT that does not contain executable AML code) + * + ******************************************************************************/ + +void +AcpiDmDumpDataTable ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_DMTABLE_DATA *TableData; + UINT32 Length; + + + /* Ignore tables that contain AML */ + + if (AcpiUtIsAmlTable (Table)) + { + return; + } + + /* + * Handle tables that don't use the common ACPI table header structure. + * Currently, these are the FACS, RSDP, and S3PT. + */ + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FACS)) + { + Length = Table->Length; + AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoFacs); + } + else if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_RSDP)) + { + Length = AcpiDmDumpRsdp (Table); + } + else if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_S3PT)) + { + Length = AcpiDmDumpS3pt (Table); + } + else + { + /* + * All other tables must use the common ACPI table header, dump it now + */ + Length = Table->Length; + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoHeader); + if (ACPI_FAILURE (Status)) + { + return; + } + AcpiOsPrintf ("\n"); + + /* Match signature and dispatch appropriately */ + + TableData = AcpiDmGetTableData (Table->Signature); + if (!TableData) + { + if (!ACPI_STRNCMP (Table->Signature, "OEM", 3)) + { + AcpiOsPrintf ("\n**** OEM-defined ACPI table [%4.4s], unknown contents\n\n", + Table->Signature); + } + else + { + AcpiOsPrintf ("\n**** Unknown ACPI table type [%4.4s]\n\n", + Table->Signature); + } + } + else if (TableData->TableHandler) + { + /* Complex table, has a handler */ + + TableData->TableHandler (Table); + } + else if (TableData->TableInfo) + { + /* Simple table, just walk the info table */ + + AcpiDmDumpTable (Length, 0, Table, 0, TableData->TableInfo); + } + } + + if (!Gbl_DoTemplates || Gbl_VerboseTemplates) + { + /* Dump the raw table data */ + + AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n", + ACPI_RAW_TABLE_DATA_HEADER, Length, Length); + AcpiUtDumpBuffer2 (ACPI_CAST_PTR (UINT8, Table), Length, DB_BYTE_DISPLAY); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmLineHeader + * + * PARAMETERS: Offset - Current byte offset, from table start + * ByteLength - Length of the field in bytes, 0 for flags + * Name - Name of this field + * Value - Optional value, displayed on left of ':' + * + * RETURN: None + * + * DESCRIPTION: Utility routines for formatting output lines. Displays the + * current table offset in hex and decimal, the field length, + * and the field name. + * + ******************************************************************************/ + +void +AcpiDmLineHeader ( + UINT32 Offset, + UINT32 ByteLength, + char *Name) +{ + + /* Allow a null name for fields that span multiple lines (large buffers) */ + + if (!Name) + { + Name = ""; + } + + if (Gbl_DoTemplates && !Gbl_VerboseTemplates) /* Terse template */ + { + if (ByteLength) + { + AcpiOsPrintf ("[%.4d] %34s : ", ByteLength, Name); + } + else + { + if (*Name) + { + AcpiOsPrintf ("%41s : ", Name); + } + else + { + AcpiOsPrintf ("%41s ", Name); + } + } + } + else /* Normal disassembler or verbose template */ + { + if (ByteLength) + { + AcpiOsPrintf ("[%3.3Xh %4.4d% 4d] %28s : ", + Offset, Offset, ByteLength, Name); + } + else + { + if (*Name) + { + AcpiOsPrintf ("%44s : ", Name); + } + else + { + AcpiOsPrintf ("%44s ", Name); + } + } + } +} + +void +AcpiDmLineHeader2 ( + UINT32 Offset, + UINT32 ByteLength, + char *Name, + UINT32 Value) +{ + + if (Gbl_DoTemplates && !Gbl_VerboseTemplates) /* Terse template */ + { + if (ByteLength) + { + AcpiOsPrintf ("[%.4d] %30s %3d : ", + ByteLength, Name, Value); + } + else + { + AcpiOsPrintf ("%36s % 3d : ", + Name, Value); + } + } + else /* Normal disassembler or verbose template */ + { + if (ByteLength) + { + AcpiOsPrintf ("[%3.3Xh %4.4d %3d] %24s %3d : ", + Offset, Offset, ByteLength, Name, Value); + } + else + { + AcpiOsPrintf ("[%3.3Xh %4.4d ] %24s %3d : ", + Offset, Offset, Name, Value); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpTable + * + * PARAMETERS: TableLength - Length of the entire ACPI table + * TableOffset - Starting offset within the table for this + * sub-descriptor (0 if main table) + * Table - The ACPI table + * SubtableLength - Length of this sub-descriptor + * Info - Info table for this ACPI table + * + * RETURN: None + * + * DESCRIPTION: Display ACPI table contents by walking the Info table. + * + * Note: This function must remain in sync with DtGetFieldLength. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDmDumpTable ( + UINT32 TableLength, + UINT32 TableOffset, + void *Table, + UINT32 SubtableLength, + ACPI_DMTABLE_INFO *Info) +{ + UINT8 *Target; + UINT32 CurrentOffset; + UINT32 ByteLength; + UINT8 Temp8; + UINT16 Temp16; + ACPI_DMTABLE_DATA *TableData; + const char *Name; + BOOLEAN LastOutputBlankLine = FALSE; + char RepairedName[8]; + + + if (!Info) + { + AcpiOsPrintf ("Display not implemented\n"); + return (AE_NOT_IMPLEMENTED); + } + + /* Walk entire Info table; Null name terminates */ + + for (; Info->Name; Info++) + { + /* + * Target points to the field within the ACPI Table. CurrentOffset is + * the offset of the field from the start of the main table. + */ + Target = ACPI_ADD_PTR (UINT8, Table, Info->Offset); + CurrentOffset = TableOffset + Info->Offset; + + /* Check for beyond EOT or beyond subtable end */ + + if ((CurrentOffset >= TableLength) || + (SubtableLength && (Info->Offset >= SubtableLength))) + { + AcpiOsPrintf ("**** ACPI table terminates in the middle of a data structure!\n"); + return (AE_BAD_DATA); + } + + /* Generate the byte length for this field */ + + switch (Info->Opcode) + { + case ACPI_DMT_UINT8: + case ACPI_DMT_CHKSUM: + case ACPI_DMT_SPACEID: + case ACPI_DMT_ACCWIDTH: + case ACPI_DMT_IVRS: + case ACPI_DMT_MADT: + case ACPI_DMT_PMTT: + case ACPI_DMT_SRAT: + case ACPI_DMT_ASF: + case ACPI_DMT_HESTNTYP: + case ACPI_DMT_FADTPM: + case ACPI_DMT_EINJACT: + case ACPI_DMT_EINJINST: + case ACPI_DMT_ERSTACT: + case ACPI_DMT_ERSTINST: + ByteLength = 1; + break; + case ACPI_DMT_UINT16: + case ACPI_DMT_DMAR: + case ACPI_DMT_HEST: + ByteLength = 2; + break; + case ACPI_DMT_UINT24: + ByteLength = 3; + break; + case ACPI_DMT_UINT32: + case ACPI_DMT_NAME4: + case ACPI_DMT_SIG: + case ACPI_DMT_SLIC: + ByteLength = 4; + break; + case ACPI_DMT_UINT40: + ByteLength = 5; + break; + case ACPI_DMT_UINT48: + case ACPI_DMT_NAME6: + ByteLength = 6; + break; + case ACPI_DMT_UINT56: + case ACPI_DMT_BUF7: + ByteLength = 7; + break; + case ACPI_DMT_UINT64: + case ACPI_DMT_NAME8: + ByteLength = 8; + break; + case ACPI_DMT_BUF16: + case ACPI_DMT_UUID: + ByteLength = 16; + break; + case ACPI_DMT_BUF128: + ByteLength = 128; + break; + case ACPI_DMT_STRING: + ByteLength = ACPI_STRLEN (ACPI_CAST_PTR (char, Target)) + 1; + break; + case ACPI_DMT_GAS: + if (!LastOutputBlankLine) + { + AcpiOsPrintf ("\n"); + LastOutputBlankLine = TRUE; + } + ByteLength = sizeof (ACPI_GENERIC_ADDRESS); + break; + case ACPI_DMT_HESTNTFY: + if (!LastOutputBlankLine) + { + AcpiOsPrintf ("\n"); + LastOutputBlankLine = TRUE; + } + ByteLength = sizeof (ACPI_HEST_NOTIFY); + break; + default: + ByteLength = 0; + break; + } + + if (CurrentOffset + ByteLength > TableLength) + { + AcpiOsPrintf ("**** ACPI table terminates in the middle of a data structure!\n"); + return (AE_BAD_DATA); + } + + if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) + { + AcpiOsPrintf ("%s", Info->Name); + continue; + } + + /* Start a new line and decode the opcode */ + + AcpiDmLineHeader (CurrentOffset, ByteLength, Info->Name); + + switch (Info->Opcode) + { + /* Single-bit Flag fields. Note: Opcode is the bit position */ + + case ACPI_DMT_FLAG0: + case ACPI_DMT_FLAG1: + case ACPI_DMT_FLAG2: + case ACPI_DMT_FLAG3: + case ACPI_DMT_FLAG4: + case ACPI_DMT_FLAG5: + case ACPI_DMT_FLAG6: + case ACPI_DMT_FLAG7: + + AcpiOsPrintf ("%1.1X\n", (*Target >> Info->Opcode) & 0x01); + break; + + /* 2-bit Flag fields */ + + case ACPI_DMT_FLAGS0: + + AcpiOsPrintf ("%1.1X\n", *Target & 0x03); + break; + + case ACPI_DMT_FLAGS1: + + AcpiOsPrintf ("%1.1X\n", (*Target >> 1) & 0x03); + break; + + case ACPI_DMT_FLAGS2: + + AcpiOsPrintf ("%1.1X\n", (*Target >> 2) & 0x03); + break; + + case ACPI_DMT_FLAGS4: + + AcpiOsPrintf ("%1.1X\n", (*Target >> 4) & 0x03); + break; + + /* Integer Data Types */ + + case ACPI_DMT_UINT8: + case ACPI_DMT_UINT16: + case ACPI_DMT_UINT24: + case ACPI_DMT_UINT32: + case ACPI_DMT_UINT40: + case ACPI_DMT_UINT48: + case ACPI_DMT_UINT56: + case ACPI_DMT_UINT64: + /* + * Dump bytes - high byte first, low byte last. + * Note: All ACPI tables are little-endian. + */ + for (Temp8 = (UINT8) ByteLength; Temp8 > 0; Temp8--) + { + AcpiOsPrintf ("%2.2X", Target[Temp8 - 1]); + } + AcpiOsPrintf ("\n"); + break; + + case ACPI_DMT_BUF7: + case ACPI_DMT_BUF16: + case ACPI_DMT_BUF128: + + /* + * Buffer: Size depends on the opcode and was set above. + * Each hex byte is separated with a space. + * Multiple lines are separated by line continuation char. + */ + for (Temp16 = 0; Temp16 < ByteLength; Temp16++) + { + AcpiOsPrintf ("%2.2X", Target[Temp16]); + if ((UINT32) (Temp16 + 1) < ByteLength) + { + if ((Temp16 > 0) && (!((Temp16+1) % 16))) + { + AcpiOsPrintf (" \\\n"); /* Line continuation */ + AcpiDmLineHeader (0, 0, NULL); + } + else + { + AcpiOsPrintf (" "); + } + } + } + AcpiOsPrintf ("\n"); + break; + + case ACPI_DMT_UUID: + + /* Convert 16-byte UUID buffer to 36-byte formatted UUID string */ + + (void) AuConvertUuidToString ((char *) Target, MsgBuffer); + + AcpiOsPrintf ("%s\n", MsgBuffer); + break; + + case ACPI_DMT_STRING: + + AcpiOsPrintf ("\"%s\"\n", ACPI_CAST_PTR (char, Target)); + break; + + /* Fixed length ASCII name fields */ + + case ACPI_DMT_SIG: + + AcpiDmCheckAscii (Target, RepairedName, 4); + AcpiOsPrintf ("\"%.4s\" ", RepairedName); + TableData = AcpiDmGetTableData (ACPI_CAST_PTR (char, Target)); + if (TableData) + { + AcpiOsPrintf (STRING_FORMAT, TableData->Name); + } + else + { + AcpiOsPrintf ("\n"); + } + break; + + case ACPI_DMT_NAME4: + + AcpiDmCheckAscii (Target, RepairedName, 4); + AcpiOsPrintf ("\"%.4s\"\n", RepairedName); + break; + + case ACPI_DMT_NAME6: + + AcpiDmCheckAscii (Target, RepairedName, 6); + AcpiOsPrintf ("\"%.6s\"\n", RepairedName); + break; + + case ACPI_DMT_NAME8: + + AcpiDmCheckAscii (Target, RepairedName, 8); + AcpiOsPrintf ("\"%.8s\"\n", RepairedName); + break; + + /* Special Data Types */ + + case ACPI_DMT_CHKSUM: + + /* Checksum, display and validate */ + + AcpiOsPrintf ("%2.2X", *Target); + Temp8 = AcpiDmGenerateChecksum (Table, + ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Length, + ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Checksum); + if (Temp8 != ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Checksum) + { + AcpiOsPrintf ( + " /* Incorrect checksum, should be %2.2X */", Temp8); + } + AcpiOsPrintf ("\n"); + break; + + case ACPI_DMT_SPACEID: + + /* Address Space ID */ + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiUtGetRegionName (*Target)); + break; + + case ACPI_DMT_ACCWIDTH: + + /* Encoded Access Width */ + + Temp8 = *Target; + if (Temp8 > ACPI_GAS_WIDTH_RESERVED) + { + Temp8 = ACPI_GAS_WIDTH_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, Temp8, AcpiDmGasAccessWidth[Temp8]); + break; + + case ACPI_DMT_GAS: + + /* Generic Address Structure */ + + AcpiOsPrintf (STRING_FORMAT, "Generic Address Structure"); + AcpiDmDumpTable (TableLength, CurrentOffset, Target, + sizeof (ACPI_GENERIC_ADDRESS), AcpiDmTableInfoGas); + AcpiOsPrintf ("\n"); + LastOutputBlankLine = TRUE; + break; + + case ACPI_DMT_ASF: + + /* ASF subtable types */ + + Temp16 = (UINT16) ((*Target) & 0x7F); /* Top bit can be zero or one */ + if (Temp16 > ACPI_ASF_TYPE_RESERVED) + { + Temp16 = ACPI_ASF_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmAsfSubnames[Temp16]); + break; + + case ACPI_DMT_DMAR: + + /* DMAR subtable types */ + + Temp16 = ACPI_GET16 (Target); + if (Temp16 > ACPI_DMAR_TYPE_RESERVED) + { + Temp16 = ACPI_DMAR_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT16_FORMAT, ACPI_GET16 (Target), AcpiDmDmarSubnames[Temp16]); + break; + + case ACPI_DMT_EINJACT: + + /* EINJ Action types */ + + Temp8 = *Target; + if (Temp8 > ACPI_EINJ_ACTION_RESERVED) + { + Temp8 = ACPI_EINJ_ACTION_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmEinjActions[Temp8]); + break; + + case ACPI_DMT_EINJINST: + + /* EINJ Instruction types */ + + Temp8 = *Target; + if (Temp8 > ACPI_EINJ_INSTRUCTION_RESERVED) + { + Temp8 = ACPI_EINJ_INSTRUCTION_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmEinjInstructions[Temp8]); + break; + + case ACPI_DMT_ERSTACT: + + /* ERST Action types */ + + Temp8 = *Target; + if (Temp8 > ACPI_ERST_ACTION_RESERVED) + { + Temp8 = ACPI_ERST_ACTION_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmErstActions[Temp8]); + break; + + case ACPI_DMT_ERSTINST: + + /* ERST Instruction types */ + + Temp8 = *Target; + if (Temp8 > ACPI_ERST_INSTRUCTION_RESERVED) + { + Temp8 = ACPI_ERST_INSTRUCTION_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmErstInstructions[Temp8]); + break; + + case ACPI_DMT_HEST: + + /* HEST subtable types */ + + Temp16 = ACPI_GET16 (Target); + if (Temp16 > ACPI_HEST_TYPE_RESERVED) + { + Temp16 = ACPI_HEST_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT16_FORMAT, ACPI_GET16 (Target), AcpiDmHestSubnames[Temp16]); + break; + + case ACPI_DMT_HESTNTFY: + + AcpiOsPrintf (STRING_FORMAT, "Hardware Error Notification Structure"); + AcpiDmDumpTable (TableLength, CurrentOffset, Target, + sizeof (ACPI_HEST_NOTIFY), AcpiDmTableInfoHestNotify); + AcpiOsPrintf ("\n"); + LastOutputBlankLine = TRUE; + break; + + case ACPI_DMT_HESTNTYP: + + /* HEST Notify types */ + + Temp8 = *Target; + if (Temp8 > ACPI_HEST_NOTIFY_RESERVED) + { + Temp8 = ACPI_HEST_NOTIFY_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmHestNotifySubnames[Temp8]); + break; + + case ACPI_DMT_MADT: + + /* MADT subtable types */ + + Temp8 = *Target; + if (Temp8 > ACPI_MADT_TYPE_RESERVED) + { + Temp8 = ACPI_MADT_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmMadtSubnames[Temp8]); + break; + + case ACPI_DMT_PMTT: + + /* PMTT subtable types */ + + Temp8 = *Target; + if (Temp8 > ACPI_PMTT_TYPE_RESERVED) + { + Temp8 = ACPI_PMTT_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmPmttSubnames[Temp8]); + break; + + case ACPI_DMT_SLIC: + + /* SLIC subtable types */ + + Temp8 = *Target; + if (Temp8 > ACPI_SLIC_TYPE_RESERVED) + { + Temp8 = ACPI_SLIC_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT32_FORMAT, *Target, AcpiDmSlicSubnames[Temp8]); + break; + + case ACPI_DMT_SRAT: + + /* SRAT subtable types */ + + Temp8 = *Target; + if (Temp8 > ACPI_SRAT_TYPE_RESERVED) + { + Temp8 = ACPI_SRAT_TYPE_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmSratSubnames[Temp8]); + break; + + case ACPI_DMT_FADTPM: + + /* FADT Preferred PM Profile names */ + + Temp8 = *Target; + if (Temp8 > ACPI_FADT_PM_RESERVED) + { + Temp8 = ACPI_FADT_PM_RESERVED; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmFadtProfiles[Temp8]); + break; + + case ACPI_DMT_IVRS: + + /* IVRS subtable types */ + + Temp8 = *Target; + switch (Temp8) + { + case ACPI_IVRS_TYPE_HARDWARE: + Name = AcpiDmIvrsSubnames[0]; + break; + + case ACPI_IVRS_TYPE_MEMORY1: + case ACPI_IVRS_TYPE_MEMORY2: + case ACPI_IVRS_TYPE_MEMORY3: + Name = AcpiDmIvrsSubnames[1]; + break; + + default: + Name = AcpiDmIvrsSubnames[2]; + break; + } + + AcpiOsPrintf (UINT8_FORMAT, *Target, Name); + break; + + case ACPI_DMT_EXIT: + return (AE_OK); + + default: + ACPI_ERROR ((AE_INFO, + "**** Invalid table opcode [0x%X] ****\n", Info->Opcode)); + return (AE_SUPPORT); + } + } + + if (TableOffset && !SubtableLength) + { + /* If this table is not the main table, subtable must have valid length */ + + AcpiOsPrintf ("Invalid zero length subtable\n"); + return (AE_BAD_DATA); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCheckAscii + * + * PARAMETERS: Name - Ascii string + * Count - Number of characters to check + * + * RETURN: None + * + * DESCRIPTION: Ensure that the requested number of characters are printable + * Ascii characters. Sets non-printable and null chars to . + * + ******************************************************************************/ + +static void +AcpiDmCheckAscii ( + UINT8 *Name, + char *RepairedName, + UINT32 Count) +{ + UINT32 i; + + + for (i = 0; i < Count; i++) + { + RepairedName[i] = (char) Name[i]; + + if (!Name[i]) + { + return; + } + if (!isprint (Name[i])) + { + RepairedName[i] = ' '; + } + } +} diff --git a/source/common/dmtbdump.c b/source/common/dmtbdump.c new file mode 100644 index 000000000000..5ea0ea34e6ad --- /dev/null +++ b/source/common/dmtbdump.c @@ -0,0 +1,2146 @@ +/****************************************************************************** + * + * Module Name: dmtbdump - Dump ACPI data tables that contain no AML code + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" +#include "actables.h" + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("dmtbdump") + + +static void +AcpiDmValidateFadtLength ( + UINT32 Revision, + UINT32 Length); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpRsdp + * + * PARAMETERS: Table - A RSDP + * + * RETURN: Length of the table (there is not always a length field, + * use revision or length if available (ACPI 2.0+)) + * + * DESCRIPTION: Format the contents of a RSDP + * + ******************************************************************************/ + +UINT32 +AcpiDmDumpRsdp ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_TABLE_RSDP *Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table); + UINT32 Length = sizeof (ACPI_RSDP_COMMON); + UINT8 Checksum; + + + /* Dump the common ACPI 1.0 portion */ + + AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1); + + /* Validate the first checksum */ + + Checksum = AcpiDmGenerateChecksum (Rsdp, sizeof (ACPI_RSDP_COMMON), + Rsdp->Checksum); + if (Checksum != Rsdp->Checksum) + { + AcpiOsPrintf ("/* Incorrect Checksum above, should be 0x%2.2X */\n", + Checksum); + } + + /* The RSDP for ACPI 2.0+ contains more data and has a Length field */ + + if (Rsdp->Revision > 0) + { + Length = Rsdp->Length; + AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2); + + /* Validate the extended checksum over entire RSDP */ + + Checksum = AcpiDmGenerateChecksum (Rsdp, sizeof (ACPI_TABLE_RSDP), + Rsdp->ExtendedChecksum); + if (Checksum != Rsdp->ExtendedChecksum) + { + AcpiOsPrintf ( + "/* Incorrect Extended Checksum above, should be 0x%2.2X */\n", + Checksum); + } + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpRsdt + * + * PARAMETERS: Table - A RSDT + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a RSDT + * + ******************************************************************************/ + +void +AcpiDmDumpRsdt ( + ACPI_TABLE_HEADER *Table) +{ + UINT32 *Array; + UINT32 Entries; + UINT32 Offset; + UINT32 i; + + + /* Point to start of table pointer array */ + + Array = ACPI_CAST_PTR (ACPI_TABLE_RSDT, Table)->TableOffsetEntry; + Offset = sizeof (ACPI_TABLE_HEADER); + + /* RSDT uses 32-bit pointers */ + + Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT32); + + for (i = 0; i < Entries; i++) + { + AcpiDmLineHeader2 (Offset, sizeof (UINT32), "ACPI Table Address", i); + AcpiOsPrintf ("%8.8X\n", Array[i]); + Offset += sizeof (UINT32); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpXsdt + * + * PARAMETERS: Table - A XSDT + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a XSDT + * + ******************************************************************************/ + +void +AcpiDmDumpXsdt ( + ACPI_TABLE_HEADER *Table) +{ + UINT64 *Array; + UINT32 Entries; + UINT32 Offset; + UINT32 i; + + + /* Point to start of table pointer array */ + + Array = ACPI_CAST_PTR (ACPI_TABLE_XSDT, Table)->TableOffsetEntry; + Offset = sizeof (ACPI_TABLE_HEADER); + + /* XSDT uses 64-bit pointers */ + + Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT64); + + for (i = 0; i < Entries; i++) + { + AcpiDmLineHeader2 (Offset, sizeof (UINT64), "ACPI Table Address", i); + AcpiOsPrintf ("%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Array[i])); + Offset += sizeof (UINT64); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpFadt + * + * PARAMETERS: Table - A FADT + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a FADT + * + * NOTE: We cannot depend on the FADT version to indicate the actual + * contents of the FADT because of BIOS bugs. The table length + * is the only reliable indicator. + * + ******************************************************************************/ + +void +AcpiDmDumpFadt ( + ACPI_TABLE_HEADER *Table) +{ + + /* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */ + + AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt1); + + /* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */ + + if ((Table->Length > ACPI_FADT_V1_SIZE) && + (Table->Length <= ACPI_FADT_V2_SIZE)) + { + AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt2); + } + + /* Check for FADT revision 3/4 fields and up (ACPI 2.0+ extended data) */ + + else if (Table->Length > ACPI_FADT_V2_SIZE) + { + AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt3); + + /* Check for FADT revision 5 fields and up (ACPI 5.0+) */ + + if (Table->Length > ACPI_FADT_V3_SIZE) + { + AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt5); + } + } + + /* Validate various fields in the FADT, including length */ + + AcpiTbCreateLocalFadt (Table, Table->Length); + + /* Validate FADT length against the revision */ + + AcpiDmValidateFadtLength (Table->Revision, Table->Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmValidateFadtLength + * + * PARAMETERS: Revision - FADT revision (Header->Revision) + * Length - FADT length (Header->Length + * + * RETURN: None + * + * DESCRIPTION: Check the FADT revision against the expected table length for + * that revision. Issue a warning if the length is not what was + * expected. This seems to be such a common BIOS bug that the + * FADT revision has been rendered virtually meaningless. + * + ******************************************************************************/ + +static void +AcpiDmValidateFadtLength ( + UINT32 Revision, + UINT32 Length) +{ + UINT32 ExpectedLength; + + + switch (Revision) + { + case 0: + AcpiOsPrintf ("// ACPI Warning: Invalid FADT revision: 0\n"); + return; + + case 1: + ExpectedLength = ACPI_FADT_V1_SIZE; + break; + + case 2: + ExpectedLength = ACPI_FADT_V2_SIZE; + break; + + case 3: + case 4: + ExpectedLength = ACPI_FADT_V3_SIZE; + break; + + case 5: + ExpectedLength = ACPI_FADT_V5_SIZE; + break; + + default: + return; + } + + if (Length == ExpectedLength) + { + return; + } + + AcpiOsPrintf ( + "\n// ACPI Warning: FADT revision %X does not match length: found %X expected %X\n", + Revision, Length, ExpectedLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpAsf + * + * PARAMETERS: Table - A ASF table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a ASF table + * + ******************************************************************************/ + +void +AcpiDmDumpAsf ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_HEADER); + ACPI_ASF_INFO *SubTable; + ACPI_DMTABLE_INFO *InfoTable; + ACPI_DMTABLE_INFO *DataInfoTable = NULL; + UINT8 *DataTable = NULL; + UINT32 DataCount = 0; + UINT32 DataLength = 0; + UINT32 DataOffset = 0; + UINT32 i; + UINT8 Type; + + + /* No main table, only sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_ASF_INFO, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Header.Length, AcpiDmTableInfoAsfHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* The actual type is the lower 7 bits of Type */ + + Type = (UINT8) (SubTable->Header.Type & 0x7F); + + switch (Type) + { + case ACPI_ASF_TYPE_INFO: + InfoTable = AcpiDmTableInfoAsf0; + break; + + case ACPI_ASF_TYPE_ALERT: + InfoTable = AcpiDmTableInfoAsf1; + DataInfoTable = AcpiDmTableInfoAsf1a; + DataTable = ACPI_ADD_PTR (UINT8, SubTable, sizeof (ACPI_ASF_ALERT)); + DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, SubTable)->Alerts; + DataLength = ACPI_CAST_PTR (ACPI_ASF_ALERT, SubTable)->DataLength; + DataOffset = Offset + sizeof (ACPI_ASF_ALERT); + break; + + case ACPI_ASF_TYPE_CONTROL: + InfoTable = AcpiDmTableInfoAsf2; + DataInfoTable = AcpiDmTableInfoAsf2a; + DataTable = ACPI_ADD_PTR (UINT8, SubTable, sizeof (ACPI_ASF_REMOTE)); + DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, SubTable)->Controls; + DataLength = ACPI_CAST_PTR (ACPI_ASF_REMOTE, SubTable)->DataLength; + DataOffset = Offset + sizeof (ACPI_ASF_REMOTE); + break; + + case ACPI_ASF_TYPE_BOOT: + InfoTable = AcpiDmTableInfoAsf3; + break; + + case ACPI_ASF_TYPE_ADDRESS: + InfoTable = AcpiDmTableInfoAsf4; + DataTable = ACPI_ADD_PTR (UINT8, SubTable, sizeof (ACPI_ASF_ADDRESS)); + DataLength = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, SubTable)->Devices; + DataOffset = Offset + sizeof (ACPI_ASF_ADDRESS); + break; + + default: + AcpiOsPrintf ("\n**** Unknown ASF sub-table type 0x%X\n", SubTable->Header.Type); + return; + } + + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Header.Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Dump variable-length extra data */ + + switch (Type) + { + case ACPI_ASF_TYPE_ALERT: + case ACPI_ASF_TYPE_CONTROL: + + for (i = 0; i < DataCount; i++) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, DataOffset, + DataTable, DataLength, DataInfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + + DataTable = ACPI_ADD_PTR (UINT8, DataTable, DataLength); + DataOffset += DataLength; + } + break; + + case ACPI_ASF_TYPE_ADDRESS: + + for (i = 0; i < DataLength; i++) + { + if (!(i % 16)) + { + AcpiDmLineHeader (DataOffset, 1, "Addresses"); + } + + AcpiOsPrintf ("%2.2X ", *DataTable); + DataTable++; + DataOffset++; + if (DataOffset > Table->Length) + { + AcpiOsPrintf ("**** ACPI table terminates in the middle of a data structure!\n"); + return; + } + } + + AcpiOsPrintf ("\n"); + break; + + default: + break; + } + + AcpiOsPrintf ("\n"); + + /* Point to next sub-table */ + + if (!SubTable->Header.Length) + { + AcpiOsPrintf ("Invalid zero subtable header length\n"); + return; + } + + Offset += SubTable->Header.Length; + SubTable = ACPI_ADD_PTR (ACPI_ASF_INFO, SubTable, SubTable->Header.Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpCpep + * + * PARAMETERS: Table - A CPEP table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a CPEP. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpCpep ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_CPEP_POLLING *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_CPEP); + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoCpep); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_CPEP_POLLING, Table, Offset); + while (Offset < Table->Length) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Header.Length, AcpiDmTableInfoCpep0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += SubTable->Header.Length; + SubTable = ACPI_ADD_PTR (ACPI_CPEP_POLLING, SubTable, + SubTable->Header.Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpDmar + * + * PARAMETERS: Table - A DMAR table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a DMAR. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpDmar ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_DMAR_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_DMAR); + ACPI_DMTABLE_INFO *InfoTable; + ACPI_DMAR_DEVICE_SCOPE *ScopeTable; + UINT32 ScopeOffset; + UINT8 *PciPath; + UINT32 PathOffset; + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoDmar); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_DMAR_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoDmarHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_DMAR_TYPE_HARDWARE_UNIT: + InfoTable = AcpiDmTableInfoDmar0; + ScopeOffset = sizeof (ACPI_DMAR_HARDWARE_UNIT); + break; + case ACPI_DMAR_TYPE_RESERVED_MEMORY: + InfoTable = AcpiDmTableInfoDmar1; + ScopeOffset = sizeof (ACPI_DMAR_RESERVED_MEMORY); + break; + case ACPI_DMAR_TYPE_ATSR: + InfoTable = AcpiDmTableInfoDmar2; + ScopeOffset = sizeof (ACPI_DMAR_ATSR); + break; + case ACPI_DMAR_HARDWARE_AFFINITY: + InfoTable = AcpiDmTableInfoDmar3; + ScopeOffset = sizeof (ACPI_DMAR_RHSA); + break; + default: + AcpiOsPrintf ("\n**** Unknown DMAR sub-table type 0x%X\n\n", SubTable->Type); + return; + } + + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Dump the device scope entries (if any) */ + + ScopeTable = ACPI_ADD_PTR (ACPI_DMAR_DEVICE_SCOPE, SubTable, ScopeOffset); + while (ScopeOffset < SubTable->Length) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset + ScopeOffset, ScopeTable, + ScopeTable->Length, AcpiDmTableInfoDmarScope); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Dump the PCI Path entries for this device scope */ + + PathOffset = sizeof (ACPI_DMAR_DEVICE_SCOPE); /* Path entries start at this offset */ + + PciPath = ACPI_ADD_PTR (UINT8, ScopeTable, + sizeof (ACPI_DMAR_DEVICE_SCOPE)); + + while (PathOffset < ScopeTable->Length) + { + AcpiDmLineHeader ((PathOffset + ScopeOffset + Offset), 2, "PCI Path"); + AcpiOsPrintf ("%2.2X,%2.2X\n", PciPath[0], PciPath[1]); + + /* Point to next PCI Path entry */ + + PathOffset += 2; + PciPath += 2; + } + + /* Point to next device scope entry */ + + ScopeOffset += ScopeTable->Length; + ScopeTable = ACPI_ADD_PTR (ACPI_DMAR_DEVICE_SCOPE, + ScopeTable, ScopeTable->Length); + } + + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_DMAR_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpEinj + * + * PARAMETERS: Table - A EINJ table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a EINJ. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpEinj ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_WHEA_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_EINJ); + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoEinj); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_WHEA_HEADER, Table, Offset); + while (Offset < Table->Length) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + sizeof (ACPI_WHEA_HEADER), AcpiDmTableInfoEinj0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table (each subtable is of fixed length) */ + + Offset += sizeof (ACPI_WHEA_HEADER); + SubTable = ACPI_ADD_PTR (ACPI_WHEA_HEADER, SubTable, + sizeof (ACPI_WHEA_HEADER)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpErst + * + * PARAMETERS: Table - A ERST table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a ERST. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpErst ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_WHEA_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_ERST); + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoErst); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_WHEA_HEADER, Table, Offset); + while (Offset < Table->Length) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + sizeof (ACPI_WHEA_HEADER), AcpiDmTableInfoErst0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table (each subtable is of fixed length) */ + + Offset += sizeof (ACPI_WHEA_HEADER); + SubTable = ACPI_ADD_PTR (ACPI_WHEA_HEADER, SubTable, + sizeof (ACPI_WHEA_HEADER)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpFpdt + * + * PARAMETERS: Table - A FPDT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a FPDT. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpFpdt ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_FPDT_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_FPDT); + ACPI_DMTABLE_INFO *InfoTable; + + + /* There is no main table (other than the standard ACPI header) */ + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_FPDT_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoFpdtHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_FPDT_TYPE_BOOT: + InfoTable = AcpiDmTableInfoFpdt0; + break; + case ACPI_FPDT_TYPE_S3PERF: + InfoTable = AcpiDmTableInfoFpdt1; + break; + default: + AcpiOsPrintf ("\n**** Unknown FPDT sub-table type 0x%X\n\n", SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return; + } + goto NextSubTable; + } + + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_FPDT_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpHest + * + * PARAMETERS: Table - A HEST table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a HEST. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpHest ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_HEST_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_HEST); + ACPI_DMTABLE_INFO *InfoTable; + UINT32 SubTableLength; + UINT32 BankCount; + ACPI_HEST_IA_ERROR_BANK *BankTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoHest); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_HEST_HEADER, Table, Offset); + while (Offset < Table->Length) + { + BankCount = 0; + switch (SubTable->Type) + { + case ACPI_HEST_TYPE_IA32_CHECK: + InfoTable = AcpiDmTableInfoHest0; + SubTableLength = sizeof (ACPI_HEST_IA_MACHINE_CHECK); + BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, + SubTable))->NumHardwareBanks; + break; + + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: + InfoTable = AcpiDmTableInfoHest1; + SubTableLength = sizeof (ACPI_HEST_IA_CORRECTED); + BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, + SubTable))->NumHardwareBanks; + break; + + case ACPI_HEST_TYPE_IA32_NMI: + InfoTable = AcpiDmTableInfoHest2; + SubTableLength = sizeof (ACPI_HEST_IA_NMI); + break; + + case ACPI_HEST_TYPE_AER_ROOT_PORT: + InfoTable = AcpiDmTableInfoHest6; + SubTableLength = sizeof (ACPI_HEST_AER_ROOT); + break; + + case ACPI_HEST_TYPE_AER_ENDPOINT: + InfoTable = AcpiDmTableInfoHest7; + SubTableLength = sizeof (ACPI_HEST_AER); + break; + + case ACPI_HEST_TYPE_AER_BRIDGE: + InfoTable = AcpiDmTableInfoHest8; + SubTableLength = sizeof (ACPI_HEST_AER_BRIDGE); + break; + + case ACPI_HEST_TYPE_GENERIC_ERROR: + InfoTable = AcpiDmTableInfoHest9; + SubTableLength = sizeof (ACPI_HEST_GENERIC); + break; + + default: + /* Cannot continue on unknown type - no length */ + + AcpiOsPrintf ("\n**** Unknown HEST sub-table type 0x%X\n", SubTable->Type); + return; + } + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTableLength, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to end of current subtable (each subtable above is of fixed length) */ + + Offset += SubTableLength; + + /* If there are any (fixed-length) Error Banks from above, dump them now */ + + if (BankCount) + { + BankTable = ACPI_ADD_PTR (ACPI_HEST_IA_ERROR_BANK, SubTable, SubTableLength); + SubTableLength += BankCount * sizeof (ACPI_HEST_IA_ERROR_BANK); + + while (BankCount) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, BankTable, + sizeof (ACPI_HEST_IA_ERROR_BANK), AcpiDmTableInfoHestBank); + if (ACPI_FAILURE (Status)) + { + return; + } + Offset += sizeof (ACPI_HEST_IA_ERROR_BANK); + BankTable++; + BankCount--; + } + } + + /* Point to next sub-table */ + + SubTable = ACPI_ADD_PTR (ACPI_HEST_HEADER, SubTable, SubTableLength); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpIvrs + * + * PARAMETERS: Table - A IVRS table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a IVRS + * + ******************************************************************************/ + +static UINT8 EntrySizes[] = {4,8,16,32}; + +void +AcpiDmDumpIvrs ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_IVRS); + UINT32 EntryOffset; + UINT32 EntryLength; + UINT32 EntryType; + ACPI_IVRS_DE_HEADER *DeviceEntry; + ACPI_IVRS_HEADER *SubTable; + ACPI_DMTABLE_INFO *InfoTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoIvrs); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_IVRS_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoIvrsHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_IVRS_TYPE_HARDWARE: + InfoTable = AcpiDmTableInfoIvrs0; + break; + case ACPI_IVRS_TYPE_MEMORY1: + case ACPI_IVRS_TYPE_MEMORY2: + case ACPI_IVRS_TYPE_MEMORY3: + InfoTable = AcpiDmTableInfoIvrs1; + break; + default: + AcpiOsPrintf ("\n**** Unknown IVRS sub-table type 0x%X\n", + SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return; + } + goto NextSubTable; + } + + /* Dump the subtable */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* The hardware subtable can contain multiple device entries */ + + if (SubTable->Type == ACPI_IVRS_TYPE_HARDWARE) + { + EntryOffset = Offset + sizeof (ACPI_IVRS_HARDWARE); + DeviceEntry = ACPI_ADD_PTR (ACPI_IVRS_DE_HEADER, SubTable, + sizeof (ACPI_IVRS_HARDWARE)); + + while (EntryOffset < (Offset + SubTable->Length)) + { + AcpiOsPrintf ("\n"); + /* + * Upper 2 bits of Type encode the length of the device entry + * + * 00 = 4 byte + * 01 = 8 byte + * 10 = 16 byte - currently no entries defined + * 11 = 32 byte - currently no entries defined + */ + EntryType = DeviceEntry->Type; + EntryLength = EntrySizes [EntryType >> 6]; + + switch (EntryType) + { + /* 4-byte device entries */ + + case ACPI_IVRS_TYPE_PAD4: + case ACPI_IVRS_TYPE_ALL: + case ACPI_IVRS_TYPE_SELECT: + case ACPI_IVRS_TYPE_START: + case ACPI_IVRS_TYPE_END: + + InfoTable = AcpiDmTableInfoIvrs4; + break; + + /* 8-byte entries, type A */ + + case ACPI_IVRS_TYPE_ALIAS_SELECT: + case ACPI_IVRS_TYPE_ALIAS_START: + + InfoTable = AcpiDmTableInfoIvrs8a; + break; + + /* 8-byte entries, type B */ + + case ACPI_IVRS_TYPE_PAD8: + case ACPI_IVRS_TYPE_EXT_SELECT: + case ACPI_IVRS_TYPE_EXT_START: + + InfoTable = AcpiDmTableInfoIvrs8b; + break; + + /* 8-byte entries, type C */ + + case ACPI_IVRS_TYPE_SPECIAL: + + InfoTable = AcpiDmTableInfoIvrs8c; + break; + + default: + InfoTable = AcpiDmTableInfoIvrs4; + AcpiOsPrintf ( + "\n**** Unknown IVRS device entry type/length: " + "0x%.2X/0x%X at offset 0x%.4X: (header below)\n", + EntryType, EntryLength, EntryOffset); + break; + } + + /* Dump the Device Entry */ + + Status = AcpiDmDumpTable (Table->Length, EntryOffset, + DeviceEntry, EntryLength, InfoTable); + + EntryOffset += EntryLength; + DeviceEntry = ACPI_ADD_PTR (ACPI_IVRS_DE_HEADER, DeviceEntry, + EntryLength); + } + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_IVRS_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMadt + * + * PARAMETERS: Table - A MADT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a MADT. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpMadt ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_SUBTABLE_HEADER *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_MADT); + ACPI_DMTABLE_INFO *InfoTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoMadt); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoMadtHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_MADT_TYPE_LOCAL_APIC: + InfoTable = AcpiDmTableInfoMadt0; + break; + case ACPI_MADT_TYPE_IO_APIC: + InfoTable = AcpiDmTableInfoMadt1; + break; + case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: + InfoTable = AcpiDmTableInfoMadt2; + break; + case ACPI_MADT_TYPE_NMI_SOURCE: + InfoTable = AcpiDmTableInfoMadt3; + break; + case ACPI_MADT_TYPE_LOCAL_APIC_NMI: + InfoTable = AcpiDmTableInfoMadt4; + break; + case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: + InfoTable = AcpiDmTableInfoMadt5; + break; + case ACPI_MADT_TYPE_IO_SAPIC: + InfoTable = AcpiDmTableInfoMadt6; + break; + case ACPI_MADT_TYPE_LOCAL_SAPIC: + InfoTable = AcpiDmTableInfoMadt7; + break; + case ACPI_MADT_TYPE_INTERRUPT_SOURCE: + InfoTable = AcpiDmTableInfoMadt8; + break; + case ACPI_MADT_TYPE_LOCAL_X2APIC: + InfoTable = AcpiDmTableInfoMadt9; + break; + case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: + InfoTable = AcpiDmTableInfoMadt10; + break; + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + InfoTable = AcpiDmTableInfoMadt11; + break; + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + InfoTable = AcpiDmTableInfoMadt12; + break; + default: + AcpiOsPrintf ("\n**** Unknown MADT sub-table type 0x%X\n\n", SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return; + } + goto NextSubTable; + } + + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMcfg + * + * PARAMETERS: Table - A MCFG Table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a MCFG table + * + ******************************************************************************/ + +void +AcpiDmDumpMcfg ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_MCFG); + ACPI_MCFG_ALLOCATION *SubTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoMcfg); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_MCFG_ALLOCATION, Table, Offset); + while (Offset < Table->Length) + { + if (Offset + sizeof (ACPI_MCFG_ALLOCATION) > Table->Length) + { + AcpiOsPrintf ("Warning: there are %u invalid trailing bytes\n", + sizeof (ACPI_MCFG_ALLOCATION) - (Offset - Table->Length)); + return; + } + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + sizeof (ACPI_MCFG_ALLOCATION), AcpiDmTableInfoMcfg0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table (each subtable is of fixed length) */ + + Offset += sizeof (ACPI_MCFG_ALLOCATION); + SubTable = ACPI_ADD_PTR (ACPI_MCFG_ALLOCATION, SubTable, + sizeof (ACPI_MCFG_ALLOCATION)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMpst + * + * PARAMETERS: Table - A MPST Table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a MPST table + * + ******************************************************************************/ + +void +AcpiDmDumpMpst ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_MPST); + ACPI_MPST_POWER_NODE *SubTable0; + ACPI_MPST_POWER_STATE *SubTable0A; + ACPI_MPST_COMPONENT *SubTable0B; + ACPI_MPST_DATA_HDR *SubTable1; + ACPI_MPST_POWER_DATA *SubTable2; + UINT16 SubtableCount; + UINT8 PowerStateCount; + UINT8 ComponentCount; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoMpst); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Subtable: Memory Power Node(s) */ + + SubtableCount = (ACPI_CAST_PTR (ACPI_TABLE_MPST, Table))->PowerNodeCount; + SubTable0 = ACPI_ADD_PTR (ACPI_MPST_POWER_NODE, Table, Offset); + + while ((Offset < Table->Length) && SubtableCount) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable0, + sizeof (ACPI_MPST_POWER_NODE), AcpiDmTableInfoMpst0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Extract the sub-subtable counts */ + + PowerStateCount = SubTable0->NumPowerStates; + ComponentCount = SubTable0->NumPhysicalComponents; + Offset += sizeof (ACPI_MPST_POWER_NODE); + + /* Sub-subtables - Memory Power State Structure(s) */ + + SubTable0A = ACPI_ADD_PTR (ACPI_MPST_POWER_STATE, SubTable0, + sizeof (ACPI_MPST_POWER_NODE)); + + while (PowerStateCount) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable0A, + sizeof (ACPI_MPST_POWER_STATE), AcpiDmTableInfoMpst0A); + if (ACPI_FAILURE (Status)) + { + return; + } + + SubTable0A++; + PowerStateCount--; + Offset += sizeof (ACPI_MPST_POWER_STATE); + } + + /* Sub-subtables - Physical Component ID Structure(s) */ + + SubTable0B = ACPI_CAST_PTR (ACPI_MPST_COMPONENT, SubTable0A); + + if (ComponentCount) + { + AcpiOsPrintf ("\n"); + } + + while (ComponentCount) + { + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable0B, + sizeof (ACPI_MPST_COMPONENT), AcpiDmTableInfoMpst0B); + if (ACPI_FAILURE (Status)) + { + return; + } + + SubTable0B++; + ComponentCount--; + Offset += sizeof (ACPI_MPST_COMPONENT); + } + + /* Point to next Memory Power Node subtable */ + + SubtableCount--; + SubTable0 = ACPI_ADD_PTR (ACPI_MPST_POWER_NODE, SubTable0, + sizeof (ACPI_MPST_POWER_NODE) + + (sizeof (ACPI_MPST_POWER_STATE) * SubTable0->NumPowerStates) + + (sizeof (ACPI_MPST_COMPONENT) * SubTable0->NumPhysicalComponents)); + } + + /* Subtable: Count of Memory Power State Characteristic structures */ + + AcpiOsPrintf ("\n"); + SubTable1 = ACPI_CAST_PTR (ACPI_MPST_DATA_HDR, SubTable0); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable1, + sizeof (ACPI_MPST_DATA_HDR), AcpiDmTableInfoMpst1); + if (ACPI_FAILURE (Status)) + { + return; + } + + SubtableCount = SubTable1->CharacteristicsCount; + Offset += sizeof (ACPI_MPST_DATA_HDR); + + /* Subtable: Memory Power State Characteristics structure(s) */ + + SubTable2 = ACPI_ADD_PTR (ACPI_MPST_POWER_DATA, SubTable1, sizeof (ACPI_MPST_DATA_HDR)); + + while ((Offset < Table->Length) && SubtableCount) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable2, + sizeof (ACPI_MPST_POWER_DATA), AcpiDmTableInfoMpst2); + if (ACPI_FAILURE (Status)) + { + return; + } + + SubTable2++; + SubtableCount--; + Offset += sizeof (ACPI_MPST_POWER_DATA); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMsct + * + * PARAMETERS: Table - A MSCT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a MSCT + * + ******************************************************************************/ + +void +AcpiDmDumpMsct ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_MSCT); + ACPI_MSCT_PROXIMITY *SubTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoMsct); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_MSCT_PROXIMITY, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + sizeof (ACPI_MSCT_PROXIMITY), AcpiDmTableInfoMsct0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += sizeof (ACPI_MSCT_PROXIMITY); + SubTable = ACPI_ADD_PTR (ACPI_MSCT_PROXIMITY, SubTable, sizeof (ACPI_MSCT_PROXIMITY)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpPcct + * + * PARAMETERS: Table - A PCCT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a PCCT. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpPcct ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_PCCT_SUBSPACE *SubTable; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_PCCT); + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoPcct); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_PCCT_SUBSPACE, Table, Offset); + while (Offset < Table->Length) + { + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Header.Length, AcpiDmTableInfoPcct0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += SubTable->Header.Length; + SubTable = ACPI_ADD_PTR (ACPI_PCCT_SUBSPACE, SubTable, + SubTable->Header.Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpPmtt + * + * PARAMETERS: Table - A PMTT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a PMTT. This table type consists + * of an open-ended number of subtables. + * + ******************************************************************************/ + +void +AcpiDmDumpPmtt ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + ACPI_PMTT_HEADER *SubTable; + ACPI_PMTT_HEADER *MemSubTable; + ACPI_PMTT_HEADER *DimmSubTable; + ACPI_PMTT_DOMAIN *DomainArray; + UINT32 Length = Table->Length; + UINT32 Offset = sizeof (ACPI_TABLE_PMTT); + UINT32 MemOffset; + UINT32 DimmOffset; + UINT32 DomainOffset; + UINT32 DomainCount; + + + /* Main table */ + + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoPmtt); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Subtables */ + + SubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common subtable header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoPmttHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Only Socket subtables are expected at this level */ + + if (SubTable->Type != ACPI_PMTT_TYPE_SOCKET) + { + AcpiOsPrintf ( + "\n**** Unexpected or unknown PMTT subtable type 0x%X\n\n", + SubTable->Type); + return; + } + + /* Dump the fixed-length portion of the subtable */ + + Status = AcpiDmDumpTable (Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoPmtt0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Walk the memory controller subtables */ + + MemOffset = sizeof (ACPI_PMTT_SOCKET); + MemSubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, SubTable, + sizeof (ACPI_PMTT_SOCKET)); + + while (((Offset + MemOffset) < Table->Length) && + (MemOffset < SubTable->Length)) + { + /* Common subtable header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, + Offset + MemOffset, MemSubTable, + MemSubTable->Length, AcpiDmTableInfoPmttHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Only memory controller subtables are expected at this level */ + + if (MemSubTable->Type != ACPI_PMTT_TYPE_CONTROLLER) + { + AcpiOsPrintf ( + "\n**** Unexpected or unknown PMTT subtable type 0x%X\n\n", + MemSubTable->Type); + return; + } + + /* Dump the fixed-length portion of the controller subtable */ + + Status = AcpiDmDumpTable (Length, + Offset + MemOffset, MemSubTable, + MemSubTable->Length, AcpiDmTableInfoPmtt1); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Walk the variable count of proximity domains */ + + DomainCount = ((ACPI_PMTT_CONTROLLER *) MemSubTable)->DomainCount; + DomainOffset = sizeof (ACPI_PMTT_CONTROLLER); + DomainArray = ACPI_ADD_PTR (ACPI_PMTT_DOMAIN, MemSubTable, + sizeof (ACPI_PMTT_CONTROLLER)); + + while (((Offset + MemOffset + DomainOffset) < Table->Length) && + ((MemOffset + DomainOffset) < SubTable->Length) && + DomainCount) + { + Status = AcpiDmDumpTable (Length, + Offset + MemOffset + DomainOffset, DomainArray, + sizeof (ACPI_PMTT_DOMAIN), AcpiDmTableInfoPmtt1a); + if (ACPI_FAILURE (Status)) + { + return; + } + + DomainOffset += sizeof (ACPI_PMTT_DOMAIN); + DomainArray++; + DomainCount--; + } + + if (DomainCount) + { + AcpiOsPrintf ( + "\n**** DomainCount exceeds subtable length\n\n", + MemSubTable->Type); + } + + /* Walk the physical component (DIMM) subtables */ + + DimmOffset = DomainOffset; + DimmSubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, MemSubTable, + DomainOffset); + + while (((Offset + MemOffset + DimmOffset) < Table->Length) && + (DimmOffset < MemSubTable->Length)) + { + /* Common subtable header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Length, + Offset + MemOffset + DimmOffset, DimmSubTable, + DimmSubTable->Length, AcpiDmTableInfoPmttHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Only DIMM subtables are expected at this level */ + + if (DimmSubTable->Type != ACPI_PMTT_TYPE_DIMM) + { + AcpiOsPrintf ( + "\n**** Unexpected or unknown PMTT subtable type 0x%X\n\n", + DimmSubTable->Type); + return; + } + + /* Dump the fixed-length DIMM subtable */ + + Status = AcpiDmDumpTable (Length, + Offset + MemOffset + DimmOffset, DimmSubTable, + DimmSubTable->Length, AcpiDmTableInfoPmtt2); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next DIMM subtable */ + + DimmOffset += DimmSubTable->Length; + DimmSubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, + DimmSubTable, DimmSubTable->Length); + } + + /* Point to next Controller subtable */ + + MemOffset += MemSubTable->Length; + MemSubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, + MemSubTable, MemSubTable->Length); + } + + /* Point to next Socket subtable */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_PMTT_HEADER, + SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpS3pt + * + * PARAMETERS: Table - A S3PT table + * + * RETURN: Length of the table + * + * DESCRIPTION: Format the contents of a S3PT + * + ******************************************************************************/ + +UINT32 +AcpiDmDumpS3pt ( + ACPI_TABLE_HEADER *Tables) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_S3PT); + ACPI_S3PT_HEADER *SubTable; + ACPI_DMTABLE_INFO *InfoTable; + ACPI_TABLE_S3PT *S3ptTable = ACPI_CAST_PTR (ACPI_TABLE_S3PT, Tables); + + + /* Main table */ + + Status = AcpiDmDumpTable (Offset, 0, S3ptTable, 0, AcpiDmTableInfoS3pt); + if (ACPI_FAILURE (Status)) + { + return 0; + } + + SubTable = ACPI_ADD_PTR (ACPI_S3PT_HEADER, S3ptTable, Offset); + while (Offset < S3ptTable->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (S3ptTable->Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoS3ptHdr); + if (ACPI_FAILURE (Status)) + { + return 0; + } + + switch (SubTable->Type) + { + case ACPI_S3PT_TYPE_RESUME: + InfoTable = AcpiDmTableInfoS3pt0; + break; + case ACPI_S3PT_TYPE_SUSPEND: + InfoTable = AcpiDmTableInfoS3pt1; + break; + default: + AcpiOsPrintf ("\n**** Unknown S3PT sub-table type 0x%X\n", SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return 0; + } + goto NextSubTable; + } + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (S3ptTable->Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return 0; + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_S3PT_HEADER, SubTable, SubTable->Length); + } + + return (S3ptTable->Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpSlic + * + * PARAMETERS: Table - A SLIC table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a SLIC + * + ******************************************************************************/ + +void +AcpiDmDumpSlic ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_SLIC); + ACPI_SLIC_HEADER *SubTable; + ACPI_DMTABLE_INFO *InfoTable; + + + /* There is no main SLIC table, only subtables */ + + SubTable = ACPI_ADD_PTR (ACPI_SLIC_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoSlicHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_SLIC_TYPE_PUBLIC_KEY: + InfoTable = AcpiDmTableInfoSlic0; + break; + case ACPI_SLIC_TYPE_WINDOWS_MARKER: + InfoTable = AcpiDmTableInfoSlic1; + break; + default: + AcpiOsPrintf ("\n**** Unknown SLIC sub-table type 0x%X\n", SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return; + } + goto NextSubTable; + } + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_SLIC_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpSlit + * + * PARAMETERS: Table - An SLIT + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a SLIT + * + ******************************************************************************/ + +void +AcpiDmDumpSlit ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset; + UINT8 *Row; + UINT32 Localities; + UINT32 i; + UINT32 j; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoSlit); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Display the Locality NxN Matrix */ + + Localities = (UINT32) ACPI_CAST_PTR (ACPI_TABLE_SLIT, Table)->LocalityCount; + Offset = ACPI_OFFSET (ACPI_TABLE_SLIT, Entry[0]); + Row = (UINT8 *) ACPI_CAST_PTR (ACPI_TABLE_SLIT, Table)->Entry; + + for (i = 0; i < Localities; i++) + { + /* Display one row of the matrix */ + + AcpiDmLineHeader2 (Offset, Localities, "Locality", i); + for (j = 0; j < Localities; j++) + { + /* Check for beyond EOT */ + + if (Offset >= Table->Length) + { + AcpiOsPrintf ("\n**** Not enough room in table for all localities\n"); + return; + } + + AcpiOsPrintf ("%2.2X", Row[j]); + Offset++; + + /* Display up to 16 bytes per output row */ + + if ((j+1) < Localities) + { + AcpiOsPrintf (" "); + + if (j && (((j+1) % 16) == 0)) + { + AcpiOsPrintf ("\\\n"); /* With line continuation char */ + AcpiDmLineHeader (Offset, 0, NULL); + } + } + } + + /* Point to next row */ + + AcpiOsPrintf ("\n"); + Row += Localities; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpSrat + * + * PARAMETERS: Table - A SRAT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a SRAT + * + ******************************************************************************/ + +void +AcpiDmDumpSrat ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_SRAT); + ACPI_SUBTABLE_HEADER *SubTable; + ACPI_DMTABLE_INFO *InfoTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoSrat); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, AcpiDmTableInfoSratHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + switch (SubTable->Type) + { + case ACPI_SRAT_TYPE_CPU_AFFINITY: + InfoTable = AcpiDmTableInfoSrat0; + break; + case ACPI_SRAT_TYPE_MEMORY_AFFINITY: + InfoTable = AcpiDmTableInfoSrat1; + break; + case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: + InfoTable = AcpiDmTableInfoSrat2; + break; + default: + AcpiOsPrintf ("\n**** Unknown SRAT sub-table type 0x%X\n", SubTable->Type); + + /* Attempt to continue */ + + if (!SubTable->Length) + { + AcpiOsPrintf ("Invalid zero length subtable\n"); + return; + } + goto NextSubTable; + } + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + SubTable->Length, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } + +NextSubTable: + /* Point to next sub-table */ + + Offset += SubTable->Length; + SubTable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, SubTable, SubTable->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpWdat + * + * PARAMETERS: Table - A WDAT table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a WDAT + * + ******************************************************************************/ + +void +AcpiDmDumpWdat ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_WDAT); + ACPI_WDAT_ENTRY *SubTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoWdat); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_WDAT_ENTRY, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + sizeof (ACPI_WDAT_ENTRY), AcpiDmTableInfoWdat0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += sizeof (ACPI_WDAT_ENTRY); + SubTable = ACPI_ADD_PTR (ACPI_WDAT_ENTRY, SubTable, sizeof (ACPI_WDAT_ENTRY)); + } +} diff --git a/source/common/dmtbinfo.c b/source/common/dmtbinfo.c new file mode 100644 index 000000000000..4600a0aa53d3 --- /dev/null +++ b/source/common/dmtbinfo.c @@ -0,0 +1,2065 @@ +/****************************************************************************** + * + * Module Name: dmtbinfo - Table info for non-AML tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("dmtbinfo") + +/* + * How to add a new table: + * + * - Add the C table definition to the actbl1.h or actbl2.h header. + * - Add ACPI_xxxx_OFFSET macro(s) for the table (and subtables) to list below. + * - Define the table in this file (for the disassembler). If any + * new data types are required (ACPI_DMT_*), see below. + * - Add an external declaration for the new table definition (AcpiDmTableInfo*) + * in acdisam.h + * - Add new table definition to the dispatch table in dmtable.c (AcpiDmTableData) + * If a simple table (with no subtables), no disassembly code is needed. + * Otherwise, create the AcpiDmDump* function for to disassemble the table + * and add it to the dmtbdump.c file. + * - Add an external declaration for the new AcpiDmDump* function in acdisasm.h + * - Add the new AcpiDmDump* function to the dispatch table in dmtable.c + * - Create a template for the new table + * - Add data table compiler support + * + * How to add a new data type (ACPI_DMT_*): + * + * - Add new type at the end of the ACPI_DMT list in acdisasm.h + * - Add length and implementation cases in dmtable.c (disassembler) + * - Add type and length cases in dtutils.c (DT compiler) + */ + +/* + * Macros used to generate offsets to specific table fields + */ +#define ACPI_FACS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_FACS,f) +#define ACPI_GAS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GENERIC_ADDRESS,f) +#define ACPI_HDR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_HEADER,f) +#define ACPI_RSDP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RSDP,f) +#define ACPI_BERT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_BERT,f) +#define ACPI_BGRT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_BGRT,f) +#define ACPI_BOOT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_BOOT,f) +#define ACPI_CPEP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_CPEP,f) +#define ACPI_DBGP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DBGP,f) +#define ACPI_DMAR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DMAR,f) +#define ACPI_DRTM_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DRTM,f) +#define ACPI_ECDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ECDT,f) +#define ACPI_EINJ_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_EINJ,f) +#define ACPI_ERST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ERST,f) +#define ACPI_GTDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_GTDT,f) +#define ACPI_HEST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_HEST,f) +#define ACPI_HPET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_HPET,f) +#define ACPI_IVRS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_IVRS,f) +#define ACPI_MADT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MADT,f) +#define ACPI_MCFG_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MCFG,f) +#define ACPI_MCHI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MCHI,f) +#define ACPI_MPST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MPST,f) +#define ACPI_MSCT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MSCT,f) +#define ACPI_PCCT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PCCT,f) +#define ACPI_PMTT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PMTT,f) +#define ACPI_S3PT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_S3PT,f) +#define ACPI_SBST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SBST,f) +#define ACPI_SLIT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SLIT,f) +#define ACPI_SPCR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPCR,f) +#define ACPI_SPMI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPMI,f) +#define ACPI_SRAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SRAT,f) +#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA,f) +#define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f) +#define ACPI_WAET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WAET,f) +#define ACPI_WDAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WDAT,f) +#define ACPI_WDDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WDDT,f) +#define ACPI_WDRT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WDRT,f) + +/* Subtables */ + +#define ACPI_ASF0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_INFO,f) +#define ACPI_ASF1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_ALERT,f) +#define ACPI_ASF1a_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_ALERT_DATA,f) +#define ACPI_ASF2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_REMOTE,f) +#define ACPI_ASF2a_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_CONTROL_DATA,f) +#define ACPI_ASF3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_RMCP,f) +#define ACPI_ASF4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_ADDRESS,f) +#define ACPI_CPEP0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CPEP_POLLING,f) +#define ACPI_DMARS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_DEVICE_SCOPE,f) +#define ACPI_DMAR0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_HARDWARE_UNIT,f) +#define ACPI_DMAR1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_RESERVED_MEMORY,f) +#define ACPI_DMAR2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_ATSR,f) +#define ACPI_DMAR3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_RHSA,f) +#define ACPI_EINJ0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WHEA_HEADER,f) +#define ACPI_ERST0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WHEA_HEADER,f) +#define ACPI_FPDTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_FPDT_HEADER,f) +#define ACPI_FPDT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_FPDT_BOOT,f) +#define ACPI_FPDT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_FPDT_S3PT_PTR,f) +#define ACPI_HEST0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_IA_MACHINE_CHECK,f) +#define ACPI_HEST1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_IA_CORRECTED,f) +#define ACPI_HEST2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_IA_NMI,f) +#define ACPI_HEST6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_AER_ROOT,f) +#define ACPI_HEST7_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_AER,f) +#define ACPI_HEST8_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_AER_BRIDGE,f) +#define ACPI_HEST9_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_GENERIC,f) +#define ACPI_HESTN_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_NOTIFY,f) +#define ACPI_HESTB_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_IA_ERROR_BANK,f) +#define ACPI_IVRSH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_HEADER,f) +#define ACPI_IVRS0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_HARDWARE,f) +#define ACPI_IVRS1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_MEMORY,f) +#define ACPI_IVRSD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_DE_HEADER,f) +#define ACPI_IVRS8A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_DEVICE8A,f) +#define ACPI_IVRS8B_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_DEVICE8B,f) +#define ACPI_IVRS8C_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_DEVICE8C,f) +#define ACPI_MADT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_APIC,f) +#define ACPI_MADT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_IO_APIC,f) +#define ACPI_MADT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_INTERRUPT_OVERRIDE,f) +#define ACPI_MADT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_NMI_SOURCE,f) +#define ACPI_MADT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_APIC_NMI,f) +#define ACPI_MADT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_APIC_OVERRIDE,f) +#define ACPI_MADT6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_IO_SAPIC,f) +#define ACPI_MADT7_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_SAPIC,f) +#define ACPI_MADT8_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_INTERRUPT_SOURCE,f) +#define ACPI_MADT9_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_X2APIC,f) +#define ACPI_MADT10_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LOCAL_X2APIC_NMI,f) +#define ACPI_MADT11_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GENERIC_INTERRUPT,f) +#define ACPI_MADT12_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GENERIC_DISTRIBUTOR,f) +#define ACPI_MADTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SUBTABLE_HEADER,f) +#define ACPI_MCFG0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MCFG_ALLOCATION,f) +#define ACPI_MPST0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_POWER_NODE,f) +#define ACPI_MPST0A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_POWER_STATE,f) +#define ACPI_MPST0B_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_COMPONENT,f) +#define ACPI_MPST1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_DATA_HDR,f) +#define ACPI_MPST2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_POWER_DATA,f) +#define ACPI_MSCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MSCT_PROXIMITY,f) +#define ACPI_PCCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_SUBSPACE,f) +#define ACPI_PMTT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_SOCKET,f) +#define ACPI_PMTT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_CONTROLLER,f) +#define ACPI_PMTT1A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_DOMAIN,f) +#define ACPI_PMTT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_PHYSICAL_COMPONENT,f) +#define ACPI_PMTTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_HEADER,f) +#define ACPI_S3PTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_S3PT_HEADER,f) +#define ACPI_S3PT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_S3PT_RESUME,f) +#define ACPI_S3PT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_S3PT_SUSPEND,f) +#define ACPI_SLICH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SLIC_HEADER,f) +#define ACPI_SLIC0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SLIC_KEY,f) +#define ACPI_SLIC1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SLIC_MARKER,f) +#define ACPI_SRATH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SUBTABLE_HEADER,f) +#define ACPI_SRAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_CPU_AFFINITY,f) +#define ACPI_SRAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_MEM_AFFINITY,f) +#define ACPI_SRAT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_X2APIC_CPU_AFFINITY,f) +#define ACPI_WDAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WDAT_ENTRY,f) + +/* + * Simplify access to flag fields by breaking them up into bytes + */ +#define ACPI_FLAG_OFFSET(d,f,o) (UINT16) (ACPI_OFFSET (d,f) + o) + +/* Flags */ + +#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_FADT,f,o) +#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_FACS,f,o) +#define ACPI_HPET_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_HPET,f,o) +#define ACPI_SRAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_CPU_AFFINITY,f,o) +#define ACPI_SRAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_MEM_AFFINITY,f,o) +#define ACPI_SRAT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_X2APIC_CPU_AFFINITY,f,o) +#define ACPI_GTDT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_GTDT,f,o) +#define ACPI_MADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_MADT,f,o) +#define ACPI_MADT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_LOCAL_APIC,f,o) +#define ACPI_MADT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_INTERRUPT_OVERRIDE,f,o) +#define ACPI_MADT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_NMI_SOURCE,f,o) +#define ACPI_MADT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_LOCAL_APIC_NMI,f,o) +#define ACPI_MADT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_LOCAL_SAPIC,f,o) +#define ACPI_MADT8_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_INTERRUPT_SOURCE,f,o) +#define ACPI_MADT9_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_LOCAL_X2APIC,f,o) +#define ACPI_MADT10_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_LOCAL_X2APIC_NMI,f,o) +#define ACPI_MADT11_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GENERIC_INTERRUPT,f,o) +#define ACPI_MPST0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MPST_POWER_NODE,f,o) +#define ACPI_MPST2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MPST_POWER_DATA,f,o) +#define ACPI_PCCT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_PCCT,f,o) +#define ACPI_PMTTH_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PMTT_HEADER,f,o) +#define ACPI_WDDT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_WDDT,f,o) +#define ACPI_EINJ0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_WHEA_HEADER,f,o) +#define ACPI_ERST0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_WHEA_HEADER,f,o) +#define ACPI_HEST0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HEST_IA_MACHINE_CHECK,f,o) +#define ACPI_HEST1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HEST_IA_CORRECTED,f,o) +#define ACPI_HEST6_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HEST_AER_ROOT,f,o) + +/* + * Required terminator for all tables below + */ +#define ACPI_DMT_TERMINATOR {ACPI_DMT_EXIT, 0, NULL, 0} +#define ACPI_DMT_NEW_LINE {ACPI_DMT_EXTRA_TEXT, 0, "\n", 0} + + +/* + * ACPI Table Information, used to dump formatted ACPI tables + * + * Each entry is of the form: + */ + +/******************************************************************************* + * + * Common ACPI table header + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHeader[] = +{ + {ACPI_DMT_SIG, ACPI_HDR_OFFSET (Signature[0]), "Signature", 0}, + {ACPI_DMT_UINT32, ACPI_HDR_OFFSET (Length), "Table Length", DT_LENGTH}, + {ACPI_DMT_UINT8, ACPI_HDR_OFFSET (Revision), "Revision", 0}, + {ACPI_DMT_CHKSUM, ACPI_HDR_OFFSET (Checksum), "Checksum", 0}, + {ACPI_DMT_NAME6, ACPI_HDR_OFFSET (OemId[0]), "Oem ID", 0}, + {ACPI_DMT_NAME8, ACPI_HDR_OFFSET (OemTableId[0]), "Oem Table ID", 0}, + {ACPI_DMT_UINT32, ACPI_HDR_OFFSET (OemRevision), "Oem Revision", 0}, + {ACPI_DMT_NAME4, ACPI_HDR_OFFSET (AslCompilerId[0]), "Asl Compiler ID", 0}, + {ACPI_DMT_UINT32, ACPI_HDR_OFFSET (AslCompilerRevision), "Asl Compiler Revision", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * GAS - Generic Address Structure + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoGas[] = +{ + {ACPI_DMT_SPACEID, ACPI_GAS_OFFSET (SpaceId), "Space ID", 0}, + {ACPI_DMT_UINT8, ACPI_GAS_OFFSET (BitWidth), "Bit Width", 0}, + {ACPI_DMT_UINT8, ACPI_GAS_OFFSET (BitOffset), "Bit Offset", 0}, + {ACPI_DMT_ACCWIDTH, ACPI_GAS_OFFSET (AccessWidth), "Encoded Access Width", 0}, + {ACPI_DMT_UINT64, ACPI_GAS_OFFSET (Address), "Address", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * RSDP - Root System Description Pointer (Signature is "RSD PTR ") + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoRsdp1[] = +{ + {ACPI_DMT_NAME8, ACPI_RSDP_OFFSET (Signature[0]), "Signature", 0}, + {ACPI_DMT_UINT8, ACPI_RSDP_OFFSET (Checksum), "Checksum", 0}, + {ACPI_DMT_NAME6, ACPI_RSDP_OFFSET (OemId[0]), "Oem ID", 0}, + {ACPI_DMT_UINT8, ACPI_RSDP_OFFSET (Revision), "Revision", 0}, + {ACPI_DMT_UINT32, ACPI_RSDP_OFFSET (RsdtPhysicalAddress), "RSDT Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* ACPI 2.0+ Extensions */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoRsdp2[] = +{ + {ACPI_DMT_UINT32, ACPI_RSDP_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT64, ACPI_RSDP_OFFSET (XsdtPhysicalAddress), "XSDT Address", 0}, + {ACPI_DMT_UINT8, ACPI_RSDP_OFFSET (ExtendedChecksum), "Extended Checksum", 0}, + {ACPI_DMT_UINT24, ACPI_RSDP_OFFSET (Reserved[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * FACS - Firmware ACPI Control Structure + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFacs[] = +{ + {ACPI_DMT_NAME4, ACPI_FACS_OFFSET (Signature[0]), "Signature", 0}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (HardwareSignature), "Hardware Signature", 0}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (FirmwareWakingVector), "32 Firmware Waking Vector", 0}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (GlobalLock), "Global Lock", 0}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_FACS_FLAG_OFFSET (Flags,0), "S4BIOS Support Present", 0}, + {ACPI_DMT_FLAG1, ACPI_FACS_FLAG_OFFSET (Flags,0), "64-bit Wake Supported (V2)", 0}, + {ACPI_DMT_UINT64, ACPI_FACS_OFFSET (XFirmwareWakingVector), "64 Firmware Waking Vector", 0}, + {ACPI_DMT_UINT8, ACPI_FACS_OFFSET (Version), "Version", 0}, + {ACPI_DMT_UINT24, ACPI_FACS_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_FACS_OFFSET (OspmFlags), "OspmFlags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_FACS_FLAG_OFFSET (OspmFlags,0), "64-bit Wake Env Required (V2)", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * FADT - Fixed ACPI Description Table (Signature is FACP) + * + ******************************************************************************/ + +/* ACPI 1.0 FADT (Version 1) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFadt1[] = +{ + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Facs), "FACS Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Dsdt), "DSDT Address", DT_NON_ZERO}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Model), "Model", 0}, + {ACPI_DMT_FADTPM, ACPI_FADT_OFFSET (PreferredProfile), "PM Profile", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (SciInterrupt), "SCI Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (SmiCommand), "SMI Command Port", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (AcpiEnable), "ACPI Enable Value", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (AcpiDisable), "ACPI Disable Value", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (S4BiosRequest), "S4BIOS Command", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (PstateControl), "P-State Control", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Pm1aEventBlock), "PM1A Event Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Pm1bEventBlock), "PM1B Event Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Pm1aControlBlock), "PM1A Control Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Pm1bControlBlock), "PM1B Control Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Pm2ControlBlock), "PM2 Control Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (PmTimerBlock), "PM Timer Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Gpe0Block), "GPE0 Block Address", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Gpe1Block), "GPE1 Block Address", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Pm1EventLength), "PM1 Event Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Pm1ControlLength), "PM1 Control Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Pm2ControlLength), "PM2 Control Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (PmTimerLength), "PM Timer Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Gpe0BlockLength), "GPE0 Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Gpe1BlockLength), "GPE1 Block Length", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Gpe1Base), "GPE1 Base Offset", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (CstControl), "_CST Support", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (C2Latency), "C2 Latency", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (C3Latency), "C3 Latency", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (FlushSize), "CPU Cache Size", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (FlushStride), "Cache Flush Stride", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (DutyOffset), "Duty Cycle Offset", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (DutyWidth), "Duty Cycle Width", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (DayAlarm), "RTC Day Alarm Index", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (MonthAlarm), "RTC Month Alarm Index", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Century), "RTC Century Index", 0}, + {ACPI_DMT_UINT16, ACPI_FADT_OFFSET (BootFlags), "Boot Flags (decoded below)", DT_FLAG}, + + /* Boot Architecture Flags byte 0 */ + + {ACPI_DMT_FLAG0, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "Legacy Devices Supported (V2)", 0}, + {ACPI_DMT_FLAG1, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "8042 Present on ports 60/64 (V2)", 0}, + {ACPI_DMT_FLAG2, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "VGA Not Present (V4)", 0}, + {ACPI_DMT_FLAG3, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "MSI Not Supported (V4)", 0}, + {ACPI_DMT_FLAG4, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "PCIe ASPM Not Supported (V4)", 0}, + {ACPI_DMT_FLAG5, ACPI_FADT_FLAG_OFFSET (BootFlags,0), "CMOS RTC Not Present (V5)", 0}, + + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_FADT_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + + /* Flags byte 0 */ + + {ACPI_DMT_FLAG0, ACPI_FADT_FLAG_OFFSET (Flags,0), "WBINVD instruction is operational (V1)", 0}, + {ACPI_DMT_FLAG1, ACPI_FADT_FLAG_OFFSET (Flags,0), "WBINVD flushes all caches (V1)", 0}, + {ACPI_DMT_FLAG2, ACPI_FADT_FLAG_OFFSET (Flags,0), "All CPUs support C1 (V1)", 0}, + {ACPI_DMT_FLAG3, ACPI_FADT_FLAG_OFFSET (Flags,0), "C2 works on MP system (V1)", 0}, + {ACPI_DMT_FLAG4, ACPI_FADT_FLAG_OFFSET (Flags,0), "Control Method Power Button (V1)", 0}, + {ACPI_DMT_FLAG5, ACPI_FADT_FLAG_OFFSET (Flags,0), "Control Method Sleep Button (V1)", 0}, + {ACPI_DMT_FLAG6, ACPI_FADT_FLAG_OFFSET (Flags,0), "RTC wake not in fixed reg space (V1)", 0}, + {ACPI_DMT_FLAG7, ACPI_FADT_FLAG_OFFSET (Flags,0), "RTC can wake system from S4 (V1)", 0}, + + /* Flags byte 1 */ + + {ACPI_DMT_FLAG0, ACPI_FADT_FLAG_OFFSET (Flags,1), "32-bit PM Timer (V1)", 0}, + {ACPI_DMT_FLAG1, ACPI_FADT_FLAG_OFFSET (Flags,1), "Docking Supported (V1)", 0}, + {ACPI_DMT_FLAG2, ACPI_FADT_FLAG_OFFSET (Flags,1), "Reset Register Supported (V2)", 0}, + {ACPI_DMT_FLAG3, ACPI_FADT_FLAG_OFFSET (Flags,1), "Sealed Case (V3)", 0}, + {ACPI_DMT_FLAG4, ACPI_FADT_FLAG_OFFSET (Flags,1), "Headless - No Video (V3)", 0}, + {ACPI_DMT_FLAG5, ACPI_FADT_FLAG_OFFSET (Flags,1), "Use native instr after SLP_TYPx (V3)", 0}, + {ACPI_DMT_FLAG6, ACPI_FADT_FLAG_OFFSET (Flags,1), "PCIEXP_WAK Bits Supported (V4)", 0}, + {ACPI_DMT_FLAG7, ACPI_FADT_FLAG_OFFSET (Flags,1), "Use Platform Timer (V4)", 0}, + + /* Flags byte 2 */ + + {ACPI_DMT_FLAG0, ACPI_FADT_FLAG_OFFSET (Flags,2), "RTC_STS valid on S4 wake (V4)", 0}, + {ACPI_DMT_FLAG1, ACPI_FADT_FLAG_OFFSET (Flags,2), "Remote Power-on capable (V4)", 0}, + {ACPI_DMT_FLAG2, ACPI_FADT_FLAG_OFFSET (Flags,2), "Use APIC Cluster Model (V4)", 0}, + {ACPI_DMT_FLAG3, ACPI_FADT_FLAG_OFFSET (Flags,2), "Use APIC Physical Destination Mode (V4)", 0}, + {ACPI_DMT_FLAG4, ACPI_FADT_FLAG_OFFSET (Flags,2), "Hardware Reduced (V5)", 0}, + {ACPI_DMT_FLAG5, ACPI_FADT_FLAG_OFFSET (Flags,2), "Low Power S0 Idle (V5)", 0}, + ACPI_DMT_TERMINATOR +}; + +/* ACPI 1.0 MS Extensions (FADT version 2) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFadt2[] = +{ + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (ResetRegister), "Reset Register", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (ResetValue), "Value to cause reset", 0}, + {ACPI_DMT_UINT24, ACPI_FADT_OFFSET (Reserved4[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* ACPI 2.0+ Extensions (FADT version 3 and 4) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFadt3[] = +{ + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (ResetRegister), "Reset Register", 0}, + {ACPI_DMT_UINT8, ACPI_FADT_OFFSET (ResetValue), "Value to cause reset", 0}, + {ACPI_DMT_UINT24, ACPI_FADT_OFFSET (Reserved4[0]), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_FADT_OFFSET (XFacs), "FACS Address", 0}, + {ACPI_DMT_UINT64, ACPI_FADT_OFFSET (XDsdt), "DSDT Address", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPm1aEventBlock), "PM1A Event Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPm1bEventBlock), "PM1B Event Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPm1aControlBlock), "PM1A Control Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPm1bControlBlock), "PM1B Control Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPm2ControlBlock), "PM2 Control Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XPmTimerBlock), "PM Timer Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XGpe0Block), "GPE0 Block", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (XGpe1Block), "GPE1 Block", 0}, + ACPI_DMT_TERMINATOR +}; + +/* ACPI 5.0 Extensions (FADT version 5) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFadt5[] = +{ + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (SleepControl), "Sleep Control Register", 0}, + {ACPI_DMT_GAS, ACPI_FADT_OFFSET (SleepStatus), "Sleep Status Register", 0}, + ACPI_DMT_TERMINATOR +}; + + +/* + * Remaining tables are not consumed directly by the ACPICA subsystem + */ + +/******************************************************************************* + * + * ASF - Alert Standard Format table (Signature "ASF!") + * + ******************************************************************************/ + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsfHdr[] = +{ + {ACPI_DMT_ASF, ACPI_ASF0_OFFSET (Header.Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_ASF0_OFFSET (Header.Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_ASF0_OFFSET (Header.Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +/* 0: ASF Information */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf0[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF0_OFFSET (MinResetValue), "Minimum Reset Value", 0}, + {ACPI_DMT_UINT8, ACPI_ASF0_OFFSET (MinPollInterval), "Minimum Polling Interval", 0}, + {ACPI_DMT_UINT16, ACPI_ASF0_OFFSET (SystemId), "System ID", 0}, + {ACPI_DMT_UINT32, ACPI_ASF0_OFFSET (MfgId), "Manufacturer ID", 0}, + {ACPI_DMT_UINT8, ACPI_ASF0_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT24, ACPI_ASF0_OFFSET (Reserved2[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: ASF Alerts */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf1[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF1_OFFSET (AssertMask), "AssertMask", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1_OFFSET (DeassertMask), "DeassertMask", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1_OFFSET (Alerts), "Alert Count", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1_OFFSET (DataLength), "Alert Data Length", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1a: ASF Alert data */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf1a[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Address), "Address", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Command), "Command", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Mask), "Mask", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Value), "Value", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (SensorType), "SensorType", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Type), "Type", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Offset), "Offset", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (SourceType), "SourceType", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Severity), "Severity", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (SensorNumber), "SensorNumber", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Entity), "Entity", 0}, + {ACPI_DMT_UINT8, ACPI_ASF1a_OFFSET (Instance), "Instance", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: ASF Remote Control */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf2[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF2_OFFSET (Controls), "Control Count", 0}, + {ACPI_DMT_UINT8, ACPI_ASF2_OFFSET (DataLength), "Control Data Length", 0}, + {ACPI_DMT_UINT16, ACPI_ASF2_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2a: ASF Control data */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf2a[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF2a_OFFSET (Function), "Function", 0}, + {ACPI_DMT_UINT8, ACPI_ASF2a_OFFSET (Address), "Address", 0}, + {ACPI_DMT_UINT8, ACPI_ASF2a_OFFSET (Command), "Command", 0}, + {ACPI_DMT_UINT8, ACPI_ASF2a_OFFSET (Value), "Value", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 3: ASF RMCP Boot Options */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf3[] = +{ + {ACPI_DMT_BUF7, ACPI_ASF3_OFFSET (Capabilities[0]), "Capabilities", 0}, + {ACPI_DMT_UINT8, ACPI_ASF3_OFFSET (CompletionCode), "Completion Code", 0}, + {ACPI_DMT_UINT32, ACPI_ASF3_OFFSET (EnterpriseId), "Enterprise ID", 0}, + {ACPI_DMT_UINT8, ACPI_ASF3_OFFSET (Command), "Command", 0}, + {ACPI_DMT_UINT16, ACPI_ASF3_OFFSET (Parameter), "Parameter", 0}, + {ACPI_DMT_UINT16, ACPI_ASF3_OFFSET (BootOptions), "Boot Options", 0}, + {ACPI_DMT_UINT16, ACPI_ASF3_OFFSET (OemParameters), "Oem Parameters", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 4: ASF Address */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoAsf4[] = +{ + {ACPI_DMT_UINT8, ACPI_ASF4_OFFSET (EpromAddress), "Eprom Address", 0}, + {ACPI_DMT_UINT8, ACPI_ASF4_OFFSET (Devices), "Device Count", DT_COUNT}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * BERT - Boot Error Record table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoBert[] = +{ + {ACPI_DMT_UINT32, ACPI_BERT_OFFSET (RegionLength), "Boot Error Region Length", 0}, + {ACPI_DMT_UINT64, ACPI_BERT_OFFSET (Address), "Boot Error Region Address", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * BGRT - Boot Graphics Resource Table (ACPI 5.0) + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoBgrt[] = +{ + {ACPI_DMT_UINT16, ACPI_BGRT_OFFSET (Version), "Version", 0}, + {ACPI_DMT_UINT8, ACPI_BGRT_OFFSET (Status), "Status", 0}, + {ACPI_DMT_UINT8, ACPI_BGRT_OFFSET (ImageType), "Image Type", 0}, + {ACPI_DMT_UINT64, ACPI_BGRT_OFFSET (ImageAddress), "Image Address", 0}, + {ACPI_DMT_UINT32, ACPI_BGRT_OFFSET (ImageOffsetX), "Image OffsetX", 0}, + {ACPI_DMT_UINT32, ACPI_BGRT_OFFSET (ImageOffsetY), "Image OffsetY", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * BOOT - Simple Boot Flag Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoBoot[] = +{ + {ACPI_DMT_UINT8, ACPI_BOOT_OFFSET (CmosIndex), "Boot Register Index", 0}, + {ACPI_DMT_UINT24, ACPI_BOOT_OFFSET (Reserved[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * CPEP - Corrected Platform Error Polling table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoCpep[] = +{ + {ACPI_DMT_UINT64, ACPI_CPEP_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoCpep0[] = +{ + {ACPI_DMT_UINT8, ACPI_CPEP0_OFFSET (Header.Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_CPEP0_OFFSET (Header.Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT8, ACPI_CPEP0_OFFSET (Id), "Processor ID", 0}, + {ACPI_DMT_UINT8, ACPI_CPEP0_OFFSET (Eid), "Processor EID", 0}, + {ACPI_DMT_UINT32, ACPI_CPEP0_OFFSET (Interval), "Polling Interval", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * DBGP - Debug Port + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDbgp[] = +{ + {ACPI_DMT_UINT8, ACPI_DBGP_OFFSET (Type), "Interface Type", 0}, + {ACPI_DMT_UINT24, ACPI_DBGP_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_DBGP_OFFSET (DebugPort), "Debug Port Register", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * DMAR - DMA Remapping table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmar[] = +{ + {ACPI_DMT_UINT8, ACPI_DMAR_OFFSET (Width), "Host Address Width", 0}, + {ACPI_DMT_UINT8, ACPI_DMAR_OFFSET (Flags), "Flags", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmarHdr[] = +{ + {ACPI_DMT_DMAR, ACPI_DMAR0_OFFSET (Header.Type), "Subtable Type", 0}, + {ACPI_DMT_UINT16, ACPI_DMAR0_OFFSET (Header.Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +/* Common device scope entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmarScope[] = +{ + {ACPI_DMT_UINT8, ACPI_DMARS_OFFSET (EntryType), "Device Scope Entry Type", 0}, + {ACPI_DMT_UINT8, ACPI_DMARS_OFFSET (Length), "Entry Length", DT_LENGTH}, + {ACPI_DMT_UINT16, ACPI_DMARS_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT8, ACPI_DMARS_OFFSET (EnumerationId), "Enumeration ID", 0}, + {ACPI_DMT_UINT8, ACPI_DMARS_OFFSET (Bus), "PCI Bus Number", 0}, + ACPI_DMT_TERMINATOR +}; + +/* DMAR Subtables */ + +/* 0: Hardware Unit Definition */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmar0[] = +{ + {ACPI_DMT_UINT8, ACPI_DMAR0_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT8, ACPI_DMAR0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_DMAR0_OFFSET (Segment), "PCI Segment Number", 0}, + {ACPI_DMT_UINT64, ACPI_DMAR0_OFFSET (Address), "Register Base Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: Reserved Memory Definition */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmar1[] = +{ + {ACPI_DMT_UINT16, ACPI_DMAR1_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_DMAR1_OFFSET (Segment), "PCI Segment Number", 0}, + {ACPI_DMT_UINT64, ACPI_DMAR1_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT64, ACPI_DMAR1_OFFSET (EndAddress), "End Address (limit)", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: Root Port ATS Capability Definition */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmar2[] = +{ + {ACPI_DMT_UINT8, ACPI_DMAR2_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT8, ACPI_DMAR2_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_DMAR2_OFFSET (Segment), "PCI Segment Number", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 3: Remapping Hardware Static Affinity Structure */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDmar3[] = +{ + {ACPI_DMT_UINT32, ACPI_DMAR3_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_DMAR3_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT32, ACPI_DMAR3_OFFSET (ProximityDomain), "Proximity Domain", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * DRTM - Dynamic Root of Trust for Measurement table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm[] = +{ + + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * ECDT - Embedded Controller Boot Resources Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoEcdt[] = +{ + {ACPI_DMT_GAS, ACPI_ECDT_OFFSET (Control), "Command/Status Register", 0}, + {ACPI_DMT_GAS, ACPI_ECDT_OFFSET (Data), "Data Register", 0}, + {ACPI_DMT_UINT32, ACPI_ECDT_OFFSET (Uid), "UID", 0}, + {ACPI_DMT_UINT8, ACPI_ECDT_OFFSET (Gpe), "GPE Number", 0}, + {ACPI_DMT_STRING, ACPI_ECDT_OFFSET (Id[0]), "Namepath", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * EINJ - Error Injection table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoEinj[] = +{ + {ACPI_DMT_UINT32, ACPI_EINJ_OFFSET (HeaderLength), "Injection Header Length", 0}, + {ACPI_DMT_UINT8, ACPI_EINJ_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT24, ACPI_EINJ_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_EINJ_OFFSET (Entries), "Injection Entry Count", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoEinj0[] = +{ + {ACPI_DMT_EINJACT, ACPI_EINJ0_OFFSET (Action), "Action", 0}, + {ACPI_DMT_EINJINST, ACPI_EINJ0_OFFSET (Instruction), "Instruction", 0}, + {ACPI_DMT_UINT8, ACPI_EINJ0_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_EINJ0_FLAG_OFFSET (Flags,0), "Preserve Register Bits", 0}, + + {ACPI_DMT_UINT8, ACPI_EINJ0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_EINJ0_OFFSET (RegisterRegion), "Register Region", 0}, + {ACPI_DMT_UINT64, ACPI_EINJ0_OFFSET (Value), "Value", 0}, + {ACPI_DMT_UINT64, ACPI_EINJ0_OFFSET (Mask), "Mask", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * ERST - Error Record Serialization table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoErst[] = +{ + {ACPI_DMT_UINT32, ACPI_ERST_OFFSET (HeaderLength), "Serialization Header Length", 0}, + {ACPI_DMT_UINT32, ACPI_ERST_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_ERST_OFFSET (Entries), "Instruction Entry Count", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoErst0[] = +{ + {ACPI_DMT_ERSTACT, ACPI_ERST0_OFFSET (Action), "Action", 0}, + {ACPI_DMT_ERSTINST, ACPI_ERST0_OFFSET (Instruction), "Instruction", 0}, + {ACPI_DMT_UINT8, ACPI_ERST0_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_ERST0_FLAG_OFFSET (Flags,0), "Preserve Register Bits", 0}, + + {ACPI_DMT_UINT8, ACPI_ERST0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_ERST0_OFFSET (RegisterRegion), "Register Region", 0}, + {ACPI_DMT_UINT64, ACPI_ERST0_OFFSET (Value), "Value", 0}, + {ACPI_DMT_UINT64, ACPI_ERST0_OFFSET (Mask), "Mask", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * FPDT - Firmware Performance Data Table (ACPI 5.0) + * + ******************************************************************************/ + +/* Main table consists of only the standard ACPI header - subtables follow */ + +/* FPDT subtable header */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFpdtHdr[] = +{ + {ACPI_DMT_UINT16, ACPI_FPDTH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_FPDTH_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT8, ACPI_FPDTH_OFFSET (Revision), "Revision", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 0: Firmware Basic Boot Performance Record */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFpdt0[] = +{ + {ACPI_DMT_UINT32, ACPI_FPDT0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT0_OFFSET (ResetEnd), "Reset End", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT0_OFFSET (LoadStart), "Load Image Start", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT0_OFFSET (StartupStart), "Start Image Start", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT0_OFFSET (ExitServicesEntry), "Exit Services Entry", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT0_OFFSET (ExitServicesExit), "Exit Services Exit", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: S3 Performance Table Pointer Record */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoFpdt1[] = +{ + {ACPI_DMT_UINT32, ACPI_FPDT1_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_FPDT1_OFFSET (Address), "S3PT Address", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * GTDT - Generic Timer Description Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoGtdt[] = +{ + {ACPI_DMT_UINT64, ACPI_GTDT_OFFSET (Address), "Timer Address", 0}, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_GTDT_FLAG_OFFSET (Flags,0), "Memory Present", 0}, + ACPI_DMT_NEW_LINE, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (SecurePl1Interrupt), "Secure PL1 Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (SecurePl1Flags), "SPL1 Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_GTDT_FLAG_OFFSET (SecurePl1Flags,0), "Trigger Mode", 0}, + {ACPI_DMT_FLAG1, ACPI_GTDT_FLAG_OFFSET (SecurePl1Flags,0), "Polarity", 0}, + ACPI_DMT_NEW_LINE, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (NonSecurePl1Interrupt), "Non-Secure PL1 Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (NonSecurePl1Flags), "NSPL1 Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_GTDT_FLAG_OFFSET (NonSecurePl1Flags,0),"Trigger Mode", 0}, + {ACPI_DMT_FLAG1, ACPI_GTDT_FLAG_OFFSET (NonSecurePl1Flags,0),"Polarity", 0}, + ACPI_DMT_NEW_LINE, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (VirtualTimerInterrupt), "Virtual Timer Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (VirtualTimerFlags), "VT Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_GTDT_FLAG_OFFSET (VirtualTimerFlags,0),"Trigger Mode", 0}, + {ACPI_DMT_FLAG1, ACPI_GTDT_FLAG_OFFSET (VirtualTimerFlags,0),"Polarity", 0}, + ACPI_DMT_NEW_LINE, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (NonSecurePl2Interrupt), "Non-Secure PL2 Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_GTDT_OFFSET (NonSecurePl2Flags), "NSPL2 Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_GTDT_FLAG_OFFSET (NonSecurePl2Flags,0),"Trigger Mode", 0}, + {ACPI_DMT_FLAG1, ACPI_GTDT_FLAG_OFFSET (NonSecurePl2Flags,0),"Polarity", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * HEST - Hardware Error Source table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest[] = +{ + {ACPI_DMT_UINT32, ACPI_HEST_OFFSET (ErrorSourceCount), "Error Source Count", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common HEST structures for subtables */ + +#define ACPI_DM_HEST_HEADER \ + {ACPI_DMT_HEST, ACPI_HEST0_OFFSET (Header.Type), "Subtable Type", 0}, \ + {ACPI_DMT_UINT16, ACPI_HEST0_OFFSET (Header.SourceId), "Source Id", 0} + +#define ACPI_DM_HEST_AER \ + {ACPI_DMT_UINT16, ACPI_HEST6_OFFSET (Aer.Reserved1), "Reserved", 0}, \ + {ACPI_DMT_UINT8, ACPI_HEST6_OFFSET (Aer.Flags), "Flags (decoded below)", DT_FLAG}, \ + {ACPI_DMT_FLAG0, ACPI_HEST6_FLAG_OFFSET (Aer.Flags,0), "Firmware First", 0}, \ + {ACPI_DMT_UINT8, ACPI_HEST6_OFFSET (Aer.Enabled), "Enabled", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.RecordsToPreallocate), "Records To Preallocate", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.MaxSectionsPerRecord), "Max Sections Per Record", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.Bus), "Bus", 0}, \ + {ACPI_DMT_UINT16, ACPI_HEST6_OFFSET (Aer.Device), "Device", 0}, \ + {ACPI_DMT_UINT16, ACPI_HEST6_OFFSET (Aer.Function), "Function", 0}, \ + {ACPI_DMT_UINT16, ACPI_HEST6_OFFSET (Aer.DeviceControl), "DeviceControl", 0}, \ + {ACPI_DMT_UINT16, ACPI_HEST6_OFFSET (Aer.Reserved2), "Reserved", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.UncorrectableMask), "Uncorrectable Mask", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.UncorrectableSeverity), "Uncorrectable Severity", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.CorrectableMask), "Correctable Mask", 0}, \ + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (Aer.AdvancedCapabilities), "Advanced Capabilities", 0} + + +/* HEST Subtables */ + +/* 0: IA32 Machine Check Exception */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest0[] = +{ + ACPI_DM_HEST_HEADER, + {ACPI_DMT_UINT16, ACPI_HEST0_OFFSET (Reserved1), "Reserved1", 0}, + {ACPI_DMT_UINT8, ACPI_HEST0_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_HEST0_FLAG_OFFSET (Flags,0), "Firmware First", 0}, + + {ACPI_DMT_UINT8, ACPI_HEST0_OFFSET (Enabled), "Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_HEST0_OFFSET (RecordsToPreallocate), "Records To Preallocate", 0}, + {ACPI_DMT_UINT32, ACPI_HEST0_OFFSET (MaxSectionsPerRecord), "Max Sections Per Record", 0}, + {ACPI_DMT_UINT64, ACPI_HEST0_OFFSET (GlobalCapabilityData), "Global Capability Data", 0}, + {ACPI_DMT_UINT64, ACPI_HEST0_OFFSET (GlobalControlData), "Global Control Data", 0}, + {ACPI_DMT_UINT8, ACPI_HEST0_OFFSET (NumHardwareBanks), "Num Hardware Banks", 0}, + {ACPI_DMT_UINT56, ACPI_HEST0_OFFSET (Reserved3[0]), "Reserved2", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: IA32 Corrected Machine Check */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest1[] = +{ + ACPI_DM_HEST_HEADER, + {ACPI_DMT_UINT16, ACPI_HEST1_OFFSET (Reserved1), "Reserved1", 0}, + {ACPI_DMT_UINT8, ACPI_HEST1_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_HEST1_FLAG_OFFSET (Flags,0), "Firmware First", 0}, + + {ACPI_DMT_UINT8, ACPI_HEST1_OFFSET (Enabled), "Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_HEST1_OFFSET (RecordsToPreallocate), "Records To Preallocate", 0}, + {ACPI_DMT_UINT32, ACPI_HEST1_OFFSET (MaxSectionsPerRecord), "Max Sections Per Record", 0}, + {ACPI_DMT_HESTNTFY, ACPI_HEST1_OFFSET (Notify), "Notify", 0}, + {ACPI_DMT_UINT8, ACPI_HEST1_OFFSET (NumHardwareBanks), "Num Hardware Banks", 0}, + {ACPI_DMT_UINT24, ACPI_HEST1_OFFSET (Reserved2[0]), "Reserved2", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: IA32 Non-Maskable Interrupt */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest2[] = +{ + ACPI_DM_HEST_HEADER, + {ACPI_DMT_UINT32, ACPI_HEST2_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_HEST2_OFFSET (RecordsToPreallocate), "Records To Preallocate", 0}, + {ACPI_DMT_UINT32, ACPI_HEST2_OFFSET (MaxSectionsPerRecord), "Max Sections Per Record", 0}, + {ACPI_DMT_UINT32, ACPI_HEST2_OFFSET (MaxRawDataLength), "Max Raw Data Length", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 6: PCI Express Root Port AER */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest6[] = +{ + ACPI_DM_HEST_HEADER, + ACPI_DM_HEST_AER, + {ACPI_DMT_UINT32, ACPI_HEST6_OFFSET (RootErrorCommand), "Root Error Command", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 7: PCI Express AER (AER Endpoint) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest7[] = +{ + ACPI_DM_HEST_HEADER, + ACPI_DM_HEST_AER, + ACPI_DMT_TERMINATOR +}; + +/* 8: PCI Express/PCI-X Bridge AER */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest8[] = +{ + ACPI_DM_HEST_HEADER, + ACPI_DM_HEST_AER, + {ACPI_DMT_UINT32, ACPI_HEST8_OFFSET (UncorrectableMask2), "2nd Uncorrectable Mask", 0}, + {ACPI_DMT_UINT32, ACPI_HEST8_OFFSET (UncorrectableSeverity2), "2nd Uncorrectable Severity", 0}, + {ACPI_DMT_UINT32, ACPI_HEST8_OFFSET (AdvancedCapabilities2), "2nd Advanced Capabilities", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 9: Generic Hardware Error Source */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHest9[] = +{ + ACPI_DM_HEST_HEADER, + {ACPI_DMT_UINT16, ACPI_HEST9_OFFSET (RelatedSourceId), "Related Source Id", 0}, + {ACPI_DMT_UINT8, ACPI_HEST9_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT8, ACPI_HEST9_OFFSET (Enabled), "Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_HEST9_OFFSET (RecordsToPreallocate), "Records To Preallocate", 0}, + {ACPI_DMT_UINT32, ACPI_HEST9_OFFSET (MaxSectionsPerRecord), "Max Sections Per Record", 0}, + {ACPI_DMT_UINT32, ACPI_HEST9_OFFSET (MaxRawDataLength), "Max Raw Data Length", 0}, + {ACPI_DMT_GAS, ACPI_HEST9_OFFSET (ErrorStatusAddress), "Error Status Address", 0}, + {ACPI_DMT_HESTNTFY, ACPI_HEST9_OFFSET (Notify), "Notify", 0}, + {ACPI_DMT_UINT32, ACPI_HEST9_OFFSET (ErrorBlockLength), "Error Status Block Length", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoHestNotify[] = +{ + {ACPI_DMT_HESTNTYP, ACPI_HESTN_OFFSET (Type), "Notify Type", 0}, + {ACPI_DMT_UINT8, ACPI_HESTN_OFFSET (Length), "Notify Length", DT_LENGTH}, + {ACPI_DMT_UINT16, ACPI_HESTN_OFFSET (ConfigWriteEnable), "Configuration Write Enable", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (PollInterval), "PollInterval", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (Vector), "Vector", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (PollingThresholdValue), "Polling Threshold Value", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (PollingThresholdWindow), "Polling Threshold Window", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (ErrorThresholdValue), "Error Threshold Value", 0}, + {ACPI_DMT_UINT32, ACPI_HESTN_OFFSET (ErrorThresholdWindow), "Error Threshold Window", 0}, + ACPI_DMT_TERMINATOR +}; + + +/* + * IA32 Error Bank(s) - Follows the ACPI_HEST_IA_MACHINE_CHECK and + * ACPI_HEST_IA_CORRECTED structures. + */ +ACPI_DMTABLE_INFO AcpiDmTableInfoHestBank[] = +{ + {ACPI_DMT_UINT8, ACPI_HESTB_OFFSET (BankNumber), "Bank Number", 0}, + {ACPI_DMT_UINT8, ACPI_HESTB_OFFSET (ClearStatusOnInit), "Clear Status On Init", 0}, + {ACPI_DMT_UINT8, ACPI_HESTB_OFFSET (StatusFormat), "Status Format", 0}, + {ACPI_DMT_UINT8, ACPI_HESTB_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_HESTB_OFFSET (ControlRegister), "Control Register", 0}, + {ACPI_DMT_UINT64, ACPI_HESTB_OFFSET (ControlData), "Control Data", 0}, + {ACPI_DMT_UINT32, ACPI_HESTB_OFFSET (StatusRegister), "Status Register", 0}, + {ACPI_DMT_UINT32, ACPI_HESTB_OFFSET (AddressRegister), "Address Register", 0}, + {ACPI_DMT_UINT32, ACPI_HESTB_OFFSET (MiscRegister), "Misc Register", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * HPET - High Precision Event Timer table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoHpet[] = +{ + {ACPI_DMT_UINT32, ACPI_HPET_OFFSET (Id), "Hardware Block ID", 0}, + {ACPI_DMT_GAS, ACPI_HPET_OFFSET (Address), "Timer Block Register", 0}, + {ACPI_DMT_UINT8, ACPI_HPET_OFFSET (Sequence), "Sequence Number", 0}, + {ACPI_DMT_UINT16, ACPI_HPET_OFFSET (MinimumTick), "Minimum Clock Ticks", 0}, + {ACPI_DMT_UINT8, ACPI_HPET_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_HPET_FLAG_OFFSET (Flags,0), "4K Page Protect", 0}, + {ACPI_DMT_FLAG1, ACPI_HPET_FLAG_OFFSET (Flags,0), "64K Page Protect", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * IVRS - I/O Virtualization Reporting Structure + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs[] = +{ + {ACPI_DMT_UINT32, ACPI_IVRS_OFFSET (Info), "Virtualization Info", 0}, + {ACPI_DMT_UINT64, ACPI_IVRS_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHdr[] = +{ + {ACPI_DMT_IVRS, ACPI_IVRSH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_IVRSH_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT16, ACPI_IVRSH_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT16, ACPI_IVRSH_OFFSET (DeviceId), "DeviceId", 0}, + ACPI_DMT_TERMINATOR +}; + +/* IVRS subtables */ + +/* 0x10: I/O Virtualization Hardware Definition (IVHD) Block */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs0[] = +{ + {ACPI_DMT_UINT16, ACPI_IVRS0_OFFSET (CapabilityOffset), "Capability Offset", 0}, + {ACPI_DMT_UINT64, ACPI_IVRS0_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT16, ACPI_IVRS0_OFFSET (PciSegmentGroup), "PCI Segment Group", 0}, + {ACPI_DMT_UINT16, ACPI_IVRS0_OFFSET (Info), "Virtualization Info", 0}, + {ACPI_DMT_UINT32, ACPI_IVRS0_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 0x20, 0x21, 0x22: I/O Virtualization Memory Definition (IVMD) Block */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs1[] = +{ + {ACPI_DMT_UINT16, ACPI_IVRS1_OFFSET (AuxData), "Auxiliary Data", 0}, + {ACPI_DMT_UINT64, ACPI_IVRS1_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_IVRS1_OFFSET (StartAddress), "Start Address", 0}, + {ACPI_DMT_UINT64, ACPI_IVRS1_OFFSET (MemoryLength), "Memory Length", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Device entry header for IVHD block */ + +#define ACPI_DMT_IVRS_DE_HEADER \ + {ACPI_DMT_UINT8, ACPI_IVRSD_OFFSET (Type), "Entry Type", 0}, \ + {ACPI_DMT_UINT16, ACPI_IVRSD_OFFSET (Id), "Device ID", 0}, \ + {ACPI_DMT_UINT8, ACPI_IVRSD_OFFSET (DataSetting), "Data Setting", 0} + +/* 4-byte device entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs4[] = +{ + ACPI_DMT_IVRS_DE_HEADER, + {ACPI_DMT_EXIT, 0, NULL, 0}, +}; + +/* 8-byte device entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8a[] = +{ + ACPI_DMT_IVRS_DE_HEADER, + {ACPI_DMT_UINT8, ACPI_IVRS8A_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_IVRS8A_OFFSET (UsedId), "Source Used Device ID", 0}, + {ACPI_DMT_UINT8, ACPI_IVRS8A_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 8-byte device entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8b[] = +{ + ACPI_DMT_IVRS_DE_HEADER, + {ACPI_DMT_UINT32, ACPI_IVRS8B_OFFSET (ExtendedData), "Extended Data", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 8-byte device entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8c[] = +{ + ACPI_DMT_IVRS_DE_HEADER, + {ACPI_DMT_UINT8, ACPI_IVRS8C_OFFSET (Handle), "Handle", 0}, + {ACPI_DMT_UINT16, ACPI_IVRS8C_OFFSET (UsedId), "Source Used Device ID", 0}, + {ACPI_DMT_UINT8, ACPI_IVRS8C_OFFSET (Variety), "Variety", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * MADT - Multiple APIC Description Table and subtables + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt[] = +{ + {ACPI_DMT_UINT32, ACPI_MADT_OFFSET (Address), "Local Apic Address", 0}, + {ACPI_DMT_UINT32, ACPI_MADT_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT_FLAG_OFFSET (Flags,0), "PC-AT Compatibility", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadtHdr[] = +{ + {ACPI_DMT_MADT, ACPI_MADTH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_MADTH_OFFSET (Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +/* MADT Subtables */ + +/* 0: processor APIC */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt0[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT0_OFFSET (ProcessorId), "Processor ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT0_OFFSET (Id), "Local Apic ID", 0}, + {ACPI_DMT_UINT32, ACPI_MADT0_OFFSET (LapicFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT0_FLAG_OFFSET (LapicFlags,0), "Processor Enabled", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: IO APIC */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt1[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT1_OFFSET (Id), "I/O Apic ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT1_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT1_OFFSET (Address), "Address", 0}, + {ACPI_DMT_UINT32, ACPI_MADT1_OFFSET (GlobalIrqBase), "Interrupt", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: Interrupt Override */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt2[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT2_OFFSET (Bus), "Bus", 0}, + {ACPI_DMT_UINT8, ACPI_MADT2_OFFSET (SourceIrq), "Source", 0}, + {ACPI_DMT_UINT32, ACPI_MADT2_OFFSET (GlobalIrq), "Interrupt", 0}, + {ACPI_DMT_UINT16, ACPI_MADT2_OFFSET (IntiFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAGS0, ACPI_MADT2_FLAG_OFFSET (IntiFlags,0), "Polarity", 0}, + {ACPI_DMT_FLAGS2, ACPI_MADT2_FLAG_OFFSET (IntiFlags,0), "Trigger Mode", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 3: NMI Sources */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt3[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT3_OFFSET (IntiFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAGS0, ACPI_MADT3_FLAG_OFFSET (IntiFlags,0), "Polarity", 0}, + {ACPI_DMT_FLAGS2, ACPI_MADT3_FLAG_OFFSET (IntiFlags,0), "Trigger Mode", 0}, + {ACPI_DMT_UINT32, ACPI_MADT3_OFFSET (GlobalIrq), "Interrupt", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 4: Local APIC NMI */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt4[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT4_OFFSET (ProcessorId), "Processor ID", 0}, + {ACPI_DMT_UINT16, ACPI_MADT4_OFFSET (IntiFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAGS0, ACPI_MADT4_FLAG_OFFSET (IntiFlags,0), "Polarity", 0}, + {ACPI_DMT_FLAGS2, ACPI_MADT4_FLAG_OFFSET (IntiFlags,0), "Trigger Mode", 0}, + {ACPI_DMT_UINT8, ACPI_MADT4_OFFSET (Lint), "Interrupt Input LINT", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 5: Address Override */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt5[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT5_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_MADT5_OFFSET (Address), "APIC Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 6: I/O Sapic */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt6[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT6_OFFSET (Id), "I/O Sapic ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT6_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT6_OFFSET (GlobalIrqBase), "Interrupt Base", 0}, + {ACPI_DMT_UINT64, ACPI_MADT6_OFFSET (Address), "Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 7: Local Sapic */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt7[] = +{ + {ACPI_DMT_UINT8, ACPI_MADT7_OFFSET (ProcessorId), "Processor ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT7_OFFSET (Id), "Local Sapic ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT7_OFFSET (Eid), "Local Sapic EID", 0}, + {ACPI_DMT_UINT24, ACPI_MADT7_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT7_OFFSET (LapicFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT7_FLAG_OFFSET (LapicFlags,0), "Processor Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_MADT7_OFFSET (Uid), "Processor UID", 0}, + {ACPI_DMT_STRING, ACPI_MADT7_OFFSET (UidString[0]), "Processor UID String", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 8: Platform Interrupt Source */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt8[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT8_OFFSET (IntiFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAGS0, ACPI_MADT8_FLAG_OFFSET (IntiFlags,0), "Polarity", 0}, + {ACPI_DMT_FLAGS2, ACPI_MADT8_FLAG_OFFSET (IntiFlags,0), "Trigger Mode", 0}, + {ACPI_DMT_UINT8, ACPI_MADT8_OFFSET (Type), "InterruptType", 0}, + {ACPI_DMT_UINT8, ACPI_MADT8_OFFSET (Id), "Processor ID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT8_OFFSET (Eid), "Processor EID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT8_OFFSET (IoSapicVector), "I/O Sapic Vector", 0}, + {ACPI_DMT_UINT32, ACPI_MADT8_OFFSET (GlobalIrq), "Interrupt", 0}, + {ACPI_DMT_UINT32, ACPI_MADT8_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT8_OFFSET (Flags), "CPEI Override", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 9: Processor Local X2_APIC (ACPI 4.0) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt9[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT9_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT9_OFFSET (LocalApicId), "Processor x2Apic ID", 0}, + {ACPI_DMT_UINT32, ACPI_MADT9_OFFSET (LapicFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT9_FLAG_OFFSET (LapicFlags,0), "Processor Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_MADT9_OFFSET (Uid), "Processor UID", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 10: Local X2_APIC NMI (ACPI 4.0) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt10[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT10_OFFSET (IntiFlags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAGS0, ACPI_MADT10_FLAG_OFFSET (IntiFlags,0), "Polarity", 0}, + {ACPI_DMT_FLAGS2, ACPI_MADT10_FLAG_OFFSET (IntiFlags,0), "Trigger Mode", 0}, + {ACPI_DMT_UINT32, ACPI_MADT10_OFFSET (Uid), "Processor UID", 0}, + {ACPI_DMT_UINT8, ACPI_MADT10_OFFSET (Lint), "Interrupt Input LINT", 0}, + {ACPI_DMT_UINT24, ACPI_MADT10_OFFSET (Reserved[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 11: Generic Interrupt Controller (ACPI 5.0) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt11[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT11_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT11_OFFSET (GicId), "Local GIC Hardware ID", 0}, + {ACPI_DMT_UINT32, ACPI_MADT11_OFFSET (Uid), "Processor UID", 0}, + {ACPI_DMT_UINT32, ACPI_MADT11_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MADT11_FLAG_OFFSET (Flags,0), "Processor Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_MADT11_OFFSET (ParkingVersion), "Parking Protocol Version", 0}, + {ACPI_DMT_UINT32, ACPI_MADT11_OFFSET (PerformanceInterrupt), "Performance Interrupt", 0}, + {ACPI_DMT_UINT64, ACPI_MADT11_OFFSET (ParkedAddress), "Parked Address", 0}, + {ACPI_DMT_UINT64, ACPI_MADT11_OFFSET (BaseAddress), "Base Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 12: Generic Interrupt Distributor (ACPI 5.0) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMadt12[] = +{ + {ACPI_DMT_UINT16, ACPI_MADT12_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MADT12_OFFSET (GicId), "Local GIC Hardware ID", 0}, + {ACPI_DMT_UINT64, ACPI_MADT12_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT32, ACPI_MADT12_OFFSET (GlobalIrqBase), "Interrupt Base", 0}, + {ACPI_DMT_UINT32, ACPI_MADT12_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * MCFG - PCI Memory Mapped Configuration table and Subtable + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg[] = +{ + {ACPI_DMT_UINT64, ACPI_MCFG_OFFSET (Reserved[0]), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg0[] = +{ + {ACPI_DMT_UINT64, ACPI_MCFG0_OFFSET (Address), "Base Address", 0}, + {ACPI_DMT_UINT16, ACPI_MCFG0_OFFSET (PciSegment), "Segment Group Number", 0}, + {ACPI_DMT_UINT8, ACPI_MCFG0_OFFSET (StartBusNumber), "Start Bus Number", 0}, + {ACPI_DMT_UINT8, ACPI_MCFG0_OFFSET (EndBusNumber), "End Bus Number", 0}, + {ACPI_DMT_UINT32, ACPI_MCFG0_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * MCHI - Management Controller Host Interface table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMchi[] = +{ + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (InterfaceType), "Interface Type", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (Protocol), "Protocol", 0}, + {ACPI_DMT_UINT64, ACPI_MCHI_OFFSET (ProtocolData), "Protocol Data", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (InterruptType), "Interrupt Type", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (Gpe), "Gpe", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (PciDeviceFlag), "Pci Device Flag", 0}, + {ACPI_DMT_UINT32, ACPI_MCHI_OFFSET (GlobalInterrupt), "Global Interrupt", 0}, + {ACPI_DMT_GAS, ACPI_MCHI_OFFSET (ControlRegister), "Control Register", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (PciSegment), "Pci Segment", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (PciBus), "Pci Bus", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (PciDevice), "Pci Device", 0}, + {ACPI_DMT_UINT8, ACPI_MCHI_OFFSET (PciFunction), "Pci Function", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * MPST - Memory Power State Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst[] = +{ + {ACPI_DMT_UINT16, ACPI_MPST_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT8, ACPI_MPST_OFFSET (ChannelId), "Channel ID", 0}, + {ACPI_DMT_UINT8, ACPI_MPST_OFFSET (Reserved2), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_MPST_OFFSET (PowerNodeCount), "Power Node Count", 0}, + ACPI_DMT_TERMINATOR +}; + +/* MPST subtables */ + +/* 0: Memory Power Node Structure */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0[] = +{ + {ACPI_DMT_UINT8, ACPI_MPST0_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MPST0_FLAG_OFFSET (Flags,0), "Node Enabled", 0}, + {ACPI_DMT_FLAG1, ACPI_MPST0_FLAG_OFFSET (Flags,0), "Power Managed", 0}, + {ACPI_DMT_FLAG2, ACPI_MPST0_FLAG_OFFSET (Flags,0), "Hot Plug Capable", 0}, + + {ACPI_DMT_UINT8, ACPI_MPST0_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_MPST0_OFFSET (NodeId), "Node ID", 0}, + {ACPI_DMT_UINT32, ACPI_MPST0_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT64, ACPI_MPST0_OFFSET (RangeAddress), "Range Address", 0}, + {ACPI_DMT_UINT64, ACPI_MPST0_OFFSET (RangeLength), "Range Length", 0}, + {ACPI_DMT_UINT8, ACPI_MPST0_OFFSET (NumPowerStates), "Num Power States", 0}, + {ACPI_DMT_UINT8, ACPI_MPST0_OFFSET (NumPhysicalComponents), "Num Physical Components", 0}, + {ACPI_DMT_UINT16, ACPI_MPST0_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 0A: Sub-subtable - Memory Power State Structure (follows Memory Power Node above) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0A[] = +{ + {ACPI_DMT_UINT8, ACPI_MPST0A_OFFSET (PowerState), "Power State", 0}, + {ACPI_DMT_UINT8, ACPI_MPST0A_OFFSET (InfoIndex), "InfoIndex", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 0B: Sub-subtable - Physical Component ID Structure (follows Memory Power State(s) above) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0B[] = +{ + {ACPI_DMT_UINT16, ACPI_MPST0B_OFFSET (ComponentId), "Component Id", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 01: Power Characteristics Count (follows all Power Node(s) above) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst1[] = +{ + {ACPI_DMT_UINT16, ACPI_MPST1_OFFSET (CharacteristicsCount), "Characteristics Count", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 02: Memory Power State Characteristics Structure */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMpst2[] = +{ + {ACPI_DMT_UINT8, ACPI_MPST2_OFFSET (Revision), "Revision", 0}, + {ACPI_DMT_UINT8, ACPI_MPST2_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_MPST2_FLAG_OFFSET (Flags,0), "Memory Preserved", 0}, + {ACPI_DMT_FLAG1, ACPI_MPST2_FLAG_OFFSET (Flags,0), "Auto Entry", 0}, + {ACPI_DMT_FLAG2, ACPI_MPST2_FLAG_OFFSET (Flags,0), "Auto Exit", 0}, + + {ACPI_DMT_UINT16, ACPI_MPST2_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_MPST2_OFFSET (AveragePower), "Average Power", 0}, + {ACPI_DMT_UINT32, ACPI_MPST2_OFFSET (PowerSaving), "Power Saving", 0}, + {ACPI_DMT_UINT64, ACPI_MPST2_OFFSET (ExitLatency), "Exit Latency", 0}, + {ACPI_DMT_UINT64, ACPI_MPST2_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * MSCT - Maximum System Characteristics Table (ACPI 4.0) + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMsct[] = +{ + {ACPI_DMT_UINT32, ACPI_MSCT_OFFSET (ProximityOffset), "Proximity Offset", 0}, + {ACPI_DMT_UINT32, ACPI_MSCT_OFFSET (MaxProximityDomains), "Max Proximity Domains", 0}, + {ACPI_DMT_UINT32, ACPI_MSCT_OFFSET (MaxClockDomains), "Max Clock Domains", 0}, + {ACPI_DMT_UINT64, ACPI_MSCT_OFFSET (MaxAddress), "Max Physical Address", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Subtable - Maximum Proximity Domain Information. Version 1 */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMsct0[] = +{ + {ACPI_DMT_UINT8, ACPI_MSCT0_OFFSET (Revision), "Revision", 0}, + {ACPI_DMT_UINT8, ACPI_MSCT0_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT32, ACPI_MSCT0_OFFSET (RangeStart), "Domain Range Start", 0}, + {ACPI_DMT_UINT32, ACPI_MSCT0_OFFSET (RangeEnd), "Domain Range End", 0}, + {ACPI_DMT_UINT32, ACPI_MSCT0_OFFSET (ProcessorCapacity), "Processor Capacity", 0}, + {ACPI_DMT_UINT64, ACPI_MSCT0_OFFSET (MemoryCapacity), "Memory Capacity", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * PCCT - Platform Communications Channel Table (ACPI 5.0) + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPcct[] = +{ + {ACPI_DMT_UINT32, ACPI_PCCT_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_PCCT_FLAG_OFFSET (Flags,0), "Doorbell", 0}, + {ACPI_DMT_UINT32, ACPI_PCCT_OFFSET (Latency), "Command Latency", 0}, + {ACPI_DMT_UINT32, ACPI_PCCT_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* PCCT subtables */ + +/* 0: Generic Communications Subspace */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPcct0[] = +{ + {ACPI_DMT_UINT8, ACPI_PCCT0_OFFSET (Header.Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_PCCT0_OFFSET (Header.Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT48, ACPI_PCCT0_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_PCCT0_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT64, ACPI_PCCT0_OFFSET (Length), "Address Length", 0}, + {ACPI_DMT_GAS, ACPI_PCCT0_OFFSET (DoorbellRegister), "Doorbell Register", 0}, + {ACPI_DMT_UINT64, ACPI_PCCT0_OFFSET (PreserveMask), "Preserve Mask", 0}, + {ACPI_DMT_UINT64, ACPI_PCCT0_OFFSET (WriteMask), "Write Mask", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * PMTT - Platform Memory Topology Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt[] = +{ + {ACPI_DMT_UINT32, ACPI_PMTT_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmttHdr[] = +{ + {ACPI_DMT_PMTT, ACPI_PMTTH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_PMTTH_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_PMTTH_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT16, ACPI_PMTTH_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_PMTTH_FLAG_OFFSET (Flags,0), "Top-level Device", 0}, + {ACPI_DMT_FLAG1, ACPI_PMTTH_FLAG_OFFSET (Flags,0), "Physical Element", 0}, + {ACPI_DMT_FLAGS2, ACPI_PMTTH_FLAG_OFFSET (Flags,0), "Memory Type", 0}, + {ACPI_DMT_UINT16, ACPI_PMTTH_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* PMTT Subtables */ + +/* 0: Socket */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt0[] = +{ + {ACPI_DMT_UINT16, ACPI_PMTT0_OFFSET (SocketId), "Socket ID", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT0_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: Memory Controller */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1[] = +{ + {ACPI_DMT_UINT32, ACPI_PMTT1_OFFSET (ReadLatency), "Read Latency", 0}, + {ACPI_DMT_UINT32, ACPI_PMTT1_OFFSET (WriteLatency), "Write Latency", 0}, + {ACPI_DMT_UINT32, ACPI_PMTT1_OFFSET (ReadBandwidth), "Read Bandwidth", 0}, + {ACPI_DMT_UINT32, ACPI_PMTT1_OFFSET (WriteBandwidth), "Write Bandwidth", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT1_OFFSET (AccessWidth), "Access Width", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT1_OFFSET (Alignment), "Alignment", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT1_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT1_OFFSET (DomainCount), "Domain Count", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1a: Proximity Domain */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1a[] = +{ + {ACPI_DMT_UINT32, ACPI_PMTT1A_OFFSET (ProximityDomain), "Proximity Domain", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: Physical Component */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt2[] = +{ + {ACPI_DMT_UINT16, ACPI_PMTT2_OFFSET (ComponentId), "Component ID", 0}, + {ACPI_DMT_UINT16, ACPI_PMTT2_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_PMTT2_OFFSET (MemorySize), "Memory Size", 0}, + {ACPI_DMT_UINT32, ACPI_PMTT2_OFFSET (BiosHandle), "Bios Handle", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * S3PT - S3 Performance Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt[] = +{ + {ACPI_DMT_SIG, ACPI_S3PT_OFFSET (Signature[0]), "Signature", 0}, + {ACPI_DMT_UINT32, ACPI_S3PT_OFFSET (Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +/* S3PT subtable header */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoS3ptHdr[] = +{ + {ACPI_DMT_UINT16, ACPI_S3PTH_OFFSET (Type), "Type", 0}, + {ACPI_DMT_UINT8, ACPI_S3PTH_OFFSET (Length), "Length", DT_LENGTH}, + {ACPI_DMT_UINT8, ACPI_S3PTH_OFFSET (Revision), "Revision", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 0: Basic S3 Resume Performance Record */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt0[] = +{ + {ACPI_DMT_UINT32, ACPI_S3PT0_OFFSET (ResumeCount), "Resume Count", 0}, + {ACPI_DMT_UINT64, ACPI_S3PT0_OFFSET (FullResume), "Full Resume", 0}, + {ACPI_DMT_UINT64, ACPI_S3PT0_OFFSET (AverageResume), "Average Resume", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: Basic S3 Suspend Performance Record */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt1[] = +{ + {ACPI_DMT_UINT64, ACPI_S3PT1_OFFSET (SuspendStart), "Suspend Start", 0}, + {ACPI_DMT_UINT64, ACPI_S3PT1_OFFSET (SuspendEnd), "Suspend End", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SBST - Smart Battery Specification Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSbst[] = +{ + {ACPI_DMT_UINT32, ACPI_SBST_OFFSET (WarningLevel), "Warning Level", 0}, + {ACPI_DMT_UINT32, ACPI_SBST_OFFSET (LowLevel), "Low Level", 0}, + {ACPI_DMT_UINT32, ACPI_SBST_OFFSET (CriticalLevel), "Critical Level", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SLIC - Software Licensing Description Table. There is no common table, just + * the standard ACPI header and then subtables. + * + ******************************************************************************/ + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSlicHdr[] = +{ + {ACPI_DMT_SLIC, ACPI_SLICH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT32, ACPI_SLICH_OFFSET (Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoSlic0[] = +{ + {ACPI_DMT_UINT8, ACPI_SLIC0_OFFSET (KeyType), "Key Type", 0}, + {ACPI_DMT_UINT8, ACPI_SLIC0_OFFSET (Version), "Version", 0}, + {ACPI_DMT_UINT16, ACPI_SLIC0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_SLIC0_OFFSET (Algorithm), "Algorithm", 0}, + {ACPI_DMT_NAME4, ACPI_SLIC0_OFFSET (Magic), "Magic", 0}, + {ACPI_DMT_UINT32, ACPI_SLIC0_OFFSET (BitLength), "BitLength", 0}, + {ACPI_DMT_UINT32, ACPI_SLIC0_OFFSET (Exponent), "Exponent", 0}, + {ACPI_DMT_BUF128, ACPI_SLIC0_OFFSET (Modulus[0]), "Modulus", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoSlic1[] = +{ + {ACPI_DMT_UINT32, ACPI_SLIC1_OFFSET (Version), "Version", 0}, + {ACPI_DMT_NAME6, ACPI_SLIC1_OFFSET (OemId[0]), "Oem ID", 0}, + {ACPI_DMT_NAME8, ACPI_SLIC1_OFFSET (OemTableId[0]), "Oem Table ID", 0}, + {ACPI_DMT_NAME8, ACPI_SLIC1_OFFSET (WindowsFlag[0]), "Windows Flag", 0}, + {ACPI_DMT_UINT32, ACPI_SLIC1_OFFSET (SlicVersion), "SLIC Version", 0}, + {ACPI_DMT_BUF16, ACPI_SLIC1_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_BUF128, ACPI_SLIC1_OFFSET (Signature[0]), "Signature", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SLIT - System Locality Information Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSlit[] = +{ + {ACPI_DMT_UINT64, ACPI_SLIT_OFFSET (LocalityCount), "Localities", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SPCR - Serial Port Console Redirection table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSpcr[] = +{ + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (InterfaceType), "Interface Type", 0}, + {ACPI_DMT_UINT24, ACPI_SPCR_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_SPCR_OFFSET (SerialPort), "Serial Port Register", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (InterruptType), "Interrupt Type", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (PcInterrupt), "PCAT-compatible IRQ", 0}, + {ACPI_DMT_UINT32, ACPI_SPCR_OFFSET (Interrupt), "Interrupt", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (BaudRate), "Baud Rate", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (Parity), "Parity", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (StopBits), "Stop Bits", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (FlowControl), "Flow Control", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (TerminalType), "Terminal Type", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (Reserved2), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_SPCR_OFFSET (PciDeviceId), "PCI Device ID", 0}, + {ACPI_DMT_UINT16, ACPI_SPCR_OFFSET (PciVendorId), "PCI Vendor ID", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (PciBus), "PCI Bus", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (PciDevice), "PCI Device", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (PciFunction), "PCI Function", 0}, + {ACPI_DMT_UINT32, ACPI_SPCR_OFFSET (PciFlags), "PCI Flags", 0}, + {ACPI_DMT_UINT8, ACPI_SPCR_OFFSET (PciSegment), "PCI Segment", 0}, + {ACPI_DMT_UINT32, ACPI_SPCR_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SPMI - Server Platform Management Interface table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSpmi[] = +{ + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (InterfaceType), "Interface Type", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT16, ACPI_SPMI_OFFSET (SpecRevision), "IPMI Spec Version", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (InterruptType), "Interrupt Type", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (GpeNumber), "GPE Number", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (Reserved1), "Reserved", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (PciDeviceFlag), "PCI Device Flag", 0}, + {ACPI_DMT_UINT32, ACPI_SPMI_OFFSET (Interrupt), "Interrupt", 0}, + {ACPI_DMT_GAS, ACPI_SPMI_OFFSET (IpmiRegister), "IPMI Register", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (PciSegment), "PCI Segment", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (PciBus), "PCI Bus", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (PciDevice), "PCI Device", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (PciFunction), "PCI Function", 0}, + {ACPI_DMT_UINT8, ACPI_SPMI_OFFSET (Reserved2), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * SRAT - System Resource Affinity Table and Subtables + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSrat[] = +{ + {ACPI_DMT_UINT32, ACPI_SRAT_OFFSET (TableRevision), "Table Revision", 0}, + {ACPI_DMT_UINT64, ACPI_SRAT_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* Common Subtable header (one per Subtable) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSratHdr[] = +{ + {ACPI_DMT_SRAT, ACPI_SRATH_OFFSET (Type), "Subtable Type", 0}, + {ACPI_DMT_UINT8, ACPI_SRATH_OFFSET (Length), "Length", DT_LENGTH}, + ACPI_DMT_TERMINATOR +}; + +/* SRAT Subtables */ + +/* 0: Processor Local APIC/SAPIC Affinity */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSrat0[] = +{ + {ACPI_DMT_UINT8, ACPI_SRAT0_OFFSET (ProximityDomainLo), "Proximity Domain Low(8)", 0}, + {ACPI_DMT_UINT8, ACPI_SRAT0_OFFSET (ApicId), "Apic ID", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT0_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_SRAT0_FLAG_OFFSET (Flags,0), "Enabled", 0}, + {ACPI_DMT_UINT8, ACPI_SRAT0_OFFSET (LocalSapicEid), "Local Sapic EID", 0}, + {ACPI_DMT_UINT24, ACPI_SRAT0_OFFSET (ProximityDomainHi[0]), "Proximity Domain High(24)", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT0_OFFSET (Reserved), "Reserved", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 1: Memory Affinity */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSrat1[] = +{ + {ACPI_DMT_UINT32, ACPI_SRAT1_OFFSET (ProximityDomain), "Proximity Domain", 0}, + {ACPI_DMT_UINT16, ACPI_SRAT1_OFFSET (Reserved), "Reserved1", 0}, + {ACPI_DMT_UINT64, ACPI_SRAT1_OFFSET (BaseAddress), "Base Address", 0}, + {ACPI_DMT_UINT64, ACPI_SRAT1_OFFSET (Length), "Address Length", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT1_OFFSET (Reserved1), "Reserved2", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT1_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_SRAT1_FLAG_OFFSET (Flags,0), "Enabled", 0}, + {ACPI_DMT_FLAG1, ACPI_SRAT1_FLAG_OFFSET (Flags,0), "Hot Pluggable", 0}, + {ACPI_DMT_FLAG2, ACPI_SRAT1_FLAG_OFFSET (Flags,0), "Non-Volatile", 0}, + {ACPI_DMT_UINT64, ACPI_SRAT1_OFFSET (Reserved2), "Reserved3", 0}, + ACPI_DMT_TERMINATOR +}; + +/* 2: Processor Local X2_APIC Affinity (ACPI 4.0) */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[] = +{ + {ACPI_DMT_UINT16, ACPI_SRAT2_OFFSET (Reserved), "Reserved1", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT2_OFFSET (ProximityDomain), "Proximity Domain", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT2_OFFSET (ApicId), "Apic ID", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT2_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_SRAT2_FLAG_OFFSET (Flags,0), "Enabled", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT2_OFFSET (ClockDomain), "Clock Domain", 0}, + {ACPI_DMT_UINT32, ACPI_SRAT2_OFFSET (Reserved2), "Reserved2", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * TCPA - Trusted Computing Platform Alliance table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] = +{ + {ACPI_DMT_UINT16, ACPI_TCPA_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_TCPA_OFFSET (MaxLogLength), "Max Event Log Length", 0}, + {ACPI_DMT_UINT64, ACPI_TCPA_OFFSET (LogAddress), "Event Log Address", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * UEFI - UEFI Boot optimization Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[] = +{ + {ACPI_DMT_UUID, ACPI_UEFI_OFFSET (Identifier[0]), "UUID Identifier", 0}, + {ACPI_DMT_UINT16, ACPI_UEFI_OFFSET (DataOffset), "Data Offset", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * WAET - Windows ACPI Emulated devices Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoWaet[] = +{ + {ACPI_DMT_UINT32, ACPI_WAET_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_WAET_OFFSET (Flags), "RTC needs no INT ack", 0}, + {ACPI_DMT_FLAG1, ACPI_WAET_OFFSET (Flags), "PM timer, one read only", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * WDAT - Watchdog Action Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoWdat[] = +{ + {ACPI_DMT_UINT32, ACPI_WDAT_OFFSET (HeaderLength), "Header Length", DT_LENGTH}, + {ACPI_DMT_UINT16, ACPI_WDAT_OFFSET (PciSegment), "PCI Segment", 0}, + {ACPI_DMT_UINT8, ACPI_WDAT_OFFSET (PciBus), "PCI Bus", 0}, + {ACPI_DMT_UINT8, ACPI_WDAT_OFFSET (PciDevice), "PCI Device", 0}, + {ACPI_DMT_UINT8, ACPI_WDAT_OFFSET (PciFunction), "PCI Function", 0}, + {ACPI_DMT_UINT24, ACPI_WDAT_OFFSET (Reserved[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT_OFFSET (TimerPeriod), "Timer Period", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT_OFFSET (MaxCount), "Max Count", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT_OFFSET (MinCount), "Min Count", 0}, + {ACPI_DMT_UINT8, ACPI_WDAT_OFFSET (Flags), "Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_WDAT_OFFSET (Flags), "Enabled", 0}, + {ACPI_DMT_FLAG7, ACPI_WDAT_OFFSET (Flags), "Stopped When Asleep", 0}, + {ACPI_DMT_UINT24, ACPI_WDAT_OFFSET (Reserved2[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT_OFFSET (Entries), "Watchdog Entry Count", 0}, + ACPI_DMT_TERMINATOR +}; + +/* WDAT Subtables - Watchdog Instruction Entries */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoWdat0[] = +{ + {ACPI_DMT_UINT8, ACPI_WDAT0_OFFSET (Action), "Watchdog Action", 0}, + {ACPI_DMT_UINT8, ACPI_WDAT0_OFFSET (Instruction), "Instruction", 0}, + {ACPI_DMT_UINT16, ACPI_WDAT0_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_WDAT0_OFFSET (RegisterRegion), "Register Region", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT0_OFFSET (Value), "Value", 0}, + {ACPI_DMT_UINT32, ACPI_WDAT0_OFFSET (Mask), "Register Mask", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * WDDT - Watchdog Description Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoWddt[] = +{ + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (SpecVersion), "Specification Version", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (TableVersion), "Table Version", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (PciVendorId), "PCI Vendor ID", 0}, + {ACPI_DMT_GAS, ACPI_WDDT_OFFSET (Address), "Timer Register", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (MaxCount), "Max Count", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (MinCount), "Min Count", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (Period), "Period", 0}, + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (Status), "Status (decoded below)", 0}, + + /* Status Flags byte 0 */ + + {ACPI_DMT_FLAG0, ACPI_WDDT_FLAG_OFFSET (Status,0), "Available", 0}, + {ACPI_DMT_FLAG1, ACPI_WDDT_FLAG_OFFSET (Status,0), "Active", 0}, + {ACPI_DMT_FLAG2, ACPI_WDDT_FLAG_OFFSET (Status,0), "OS Owns", 0}, + + /* Status Flags byte 1 */ + + {ACPI_DMT_FLAG3, ACPI_WDDT_FLAG_OFFSET (Status,1), "User Reset", 0}, + {ACPI_DMT_FLAG4, ACPI_WDDT_FLAG_OFFSET (Status,1), "Timeout Reset", 0}, + {ACPI_DMT_FLAG5, ACPI_WDDT_FLAG_OFFSET (Status,1), "Power Fail Reset", 0}, + {ACPI_DMT_FLAG6, ACPI_WDDT_FLAG_OFFSET (Status,1), "Unknown Reset", 0}, + + {ACPI_DMT_UINT16, ACPI_WDDT_OFFSET (Capability), "Capability (decoded below)", 0}, + + /* Capability Flags byte 0 */ + + {ACPI_DMT_FLAG0, ACPI_WDDT_FLAG_OFFSET (Capability,0), "Auto Reset", 0}, + {ACPI_DMT_FLAG1, ACPI_WDDT_FLAG_OFFSET (Capability,0), "Timeout Alert", 0}, + ACPI_DMT_TERMINATOR +}; + + +/******************************************************************************* + * + * WDRT - Watchdog Resource Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoWdrt[] = +{ + {ACPI_DMT_GAS, ACPI_WDRT_OFFSET (ControlRegister), "Control Register", 0}, + {ACPI_DMT_GAS, ACPI_WDRT_OFFSET (CountRegister), "Count Register", 0}, + {ACPI_DMT_UINT16, ACPI_WDRT_OFFSET (PciDeviceId), "PCI Device ID", 0}, + {ACPI_DMT_UINT16, ACPI_WDRT_OFFSET (PciVendorId), "PCI Vendor ID", 0}, + {ACPI_DMT_UINT8, ACPI_WDRT_OFFSET (PciBus), "PCI Bus", 0}, + {ACPI_DMT_UINT8, ACPI_WDRT_OFFSET (PciDevice), "PCI Device", 0}, + {ACPI_DMT_UINT8, ACPI_WDRT_OFFSET (PciFunction), "PCI Function", 0}, + {ACPI_DMT_UINT8, ACPI_WDRT_OFFSET (PciSegment), "PCI Segment", 0}, + {ACPI_DMT_UINT16, ACPI_WDRT_OFFSET (MaxCount), "Max Count", 0}, + {ACPI_DMT_UINT8, ACPI_WDRT_OFFSET (Units), "Counter Units", 0}, + ACPI_DMT_TERMINATOR +}; + +/*! [Begin] no source code translation */ + +/* + * Generic types (used in UEFI and custom tables) + * + * Examples: + * + * Buffer : cc 04 ff bb + * UINT8 : 11 + * UINT16 : 1122 + * UINT24 : 112233 + * UINT32 : 11223344 + * UINT56 : 11223344556677 + * UINT64 : 1122334455667788 + * + * String : "This is string" + * Unicode : "This string encoded to Unicode" + * + * GUID : 11223344-5566-7788-99aa-bbccddeeff00 + * DevicePath : "\PciRoot(0)\Pci(0x1f,1)\Usb(0,0)" + */ + +#define ACPI_DM_GENERIC_ENTRY(FieldType, FieldName) \ + {{FieldType, 0, FieldName, 0}, ACPI_DMT_TERMINATOR} + +ACPI_DMTABLE_INFO AcpiDmTableInfoGeneric[][2] = +{ + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT8, "UINT8"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT16, "UINT16"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT24, "UINT24"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT32, "UINT32"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT40, "UINT40"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT48, "UINT48"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT56, "UINT56"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UINT64, "UINT64"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_STRING, "String"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UNICODE, "Unicode"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_BUFFER, "Buffer"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_UUID, "GUID"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_STRING, "DevicePath"), + ACPI_DM_GENERIC_ENTRY (ACPI_DMT_LABEL, "Label"), + {ACPI_DMT_TERMINATOR} +}; +/*! [End] no source code translation !*/ diff --git a/source/common/getopt.c b/source/common/getopt.c new file mode 100644 index 000000000000..b253e8a01d6a --- /dev/null +++ b/source/common/getopt.c @@ -0,0 +1,173 @@ + +/****************************************************************************** + * + * Module Name: getopt + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include +#include +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" + +#define ERR(szz,czz) if(AcpiGbl_Opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);} + + +int AcpiGbl_Opterr = 1; +int AcpiGbl_Optind = 1; +char *AcpiGbl_Optarg; + + +/******************************************************************************* + * + * FUNCTION: AcpiGetopt + * + * PARAMETERS: argc, argv - from main + * opts - options info list + * + * RETURN: Option character or EOF + * + * DESCRIPTION: Get the next option + * + ******************************************************************************/ + +int +AcpiGetopt( + int argc, + char **argv, + char *opts) +{ + static int CurrentCharPtr = 1; + int CurrentChar; + char *OptsPtr; + + + if (CurrentCharPtr == 1) + { + if (AcpiGbl_Optind >= argc || + argv[AcpiGbl_Optind][0] != '-' || + argv[AcpiGbl_Optind][1] == '\0') + { + return(EOF); + } + else if (strcmp (argv[AcpiGbl_Optind], "--") == 0) + { + AcpiGbl_Optind++; + return(EOF); + } + } + + /* Get the option */ + + CurrentChar = argv[AcpiGbl_Optind][CurrentCharPtr]; + + /* Make sure that the option is legal */ + + if (CurrentChar == ':' || + (OptsPtr = strchr (opts, CurrentChar)) == NULL) + { + ERR (": illegal option -- ", CurrentChar); + + if (argv[AcpiGbl_Optind][++CurrentCharPtr] == '\0') + { + AcpiGbl_Optind++; + CurrentCharPtr = 1; + } + + return ('?'); + } + + /* Option requires an argument? */ + + if (*++OptsPtr == ':') + { + if (argv[AcpiGbl_Optind][(int) (CurrentCharPtr+1)] != '\0') + { + AcpiGbl_Optarg = &argv[AcpiGbl_Optind++][(int) (CurrentCharPtr+1)]; + } + else if (++AcpiGbl_Optind >= argc) + { + ERR (": option requires an argument -- ", CurrentChar); + + CurrentCharPtr = 1; + return ('?'); + } + else + { + AcpiGbl_Optarg = argv[AcpiGbl_Optind++]; + } + + CurrentCharPtr = 1; + } + + /* Option has optional single-char arguments? */ + + else if (*OptsPtr == '^') + { + if (argv[AcpiGbl_Optind][(int) (CurrentCharPtr+1)] != '\0') + { + AcpiGbl_Optarg = &argv[AcpiGbl_Optind][(int) (CurrentCharPtr+1)]; + } + else + { + AcpiGbl_Optarg = "^"; + } + + AcpiGbl_Optind++; + CurrentCharPtr = 1; + } + + /* Option with no arguments */ + + else + { + if (argv[AcpiGbl_Optind][++CurrentCharPtr] == '\0') + { + CurrentCharPtr = 1; + AcpiGbl_Optind++; + } + + AcpiGbl_Optarg = NULL; + } + + return (CurrentChar); +} diff --git a/source/compiler/Makefile b/source/compiler/Makefile new file mode 100644 index 000000000000..a63538bd0b5f --- /dev/null +++ b/source/compiler/Makefile @@ -0,0 +1,329 @@ +# +# iASL compiler/disassembler +# +# NOTE: This makefile is intended to be used within the native +# ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = iasl + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ASL_COMPILER = $(ACPICA_SRC)/compiler +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ASL_COMPILER) \ + $(ACPICA_DEBUGGER) \ + $(ACPICA_DISASSEMBLER) \ + $(ACPICA_DISPATCHER) \ + $(ACPICA_EXECUTER) \ + $(ACPICA_NAMESPACE) \ + $(ACPICA_PARSER) \ + $(ACPICA_TABLES) \ + $(ACPICA_UTILITIES) \ + $(ACPICA_COMMON) \ + $(ACPICA_OSL) + +HEADERS = \ + $(wildcard $(ASL_COMPILER)/*.h) \ + aslcompiler.y.h \ + dtparser.y.h + +OBJECTS = \ + aslcompilerlex.o \ + aslcompilerparse.o \ + dtparserlex.o \ + dtparserparse.o \ + adfile.o \ + adisasm.o \ + adwalk.o \ + aslanalyze.o \ + aslbtypes.o \ + aslcodegen.o \ + aslcompile.o \ + aslerror.o \ + aslfiles.o \ + aslfold.o \ + asllength.o \ + asllisting.o \ + aslload.o \ + asllookup.o \ + aslmain.o \ + aslmap.o \ + aslopcodes.o \ + asloperands.o \ + aslopt.o \ + aslpredef.o \ + aslresource.o \ + aslrestype1.o \ + aslrestype1i.o \ + aslrestype2.o \ + aslrestype2d.o \ + aslrestype2e.o \ + aslrestype2s.o \ + aslrestype2q.o \ + aslrestype2w.o \ + aslstartup.o \ + aslstubs.o \ + asltransform.o \ + asltree.o \ + aslutils.o \ + asluuid.o \ + aslwalks.o \ + dtcompile.o \ + dtexpress.o \ + dtfield.o \ + dtio.o \ + dtsubtable.o \ + dttable.o \ + dttemplate.o \ + dtutils.o \ + dbfileio.o \ + dmbuffer.o \ + dmextern.o \ + dmnames.o \ + dmobject.o \ + dmopcode.o \ + dmresrc.o \ + dmresrcl.o \ + dmresrcl2.o \ + dmresrcs.o \ + dmrestag.o \ + dmtable.o \ + dmtbdump.o \ + dmtbinfo.o \ + dmutils.o \ + dmwalk.o \ + dsargs.o \ + dscontrol.o \ + dsfield.o \ + dsobject.o \ + dsopcode.o \ + dsutils.o \ + dswexec.o \ + dswload.o \ + dswload2.o \ + dswscope.o \ + dswstate.o \ + exconvrt.o \ + excreate.o \ + exdump.o \ + exmisc.o \ + exmutex.o \ + exnames.o \ + exoparg1.o \ + exoparg2.o \ + exoparg3.o \ + exoparg6.o \ + exprep.o \ + exregion.o \ + exresnte.o \ + exresolv.o \ + exresop.o \ + exstore.o \ + exstoren.o \ + exstorob.o \ + exsystem.o \ + exutils.o \ + getopt.o \ + nsaccess.o \ + nsalloc.o \ + nsdump.o \ + nsnames.o \ + nsobject.o \ + nsparse.o \ + nssearch.o \ + nsutils.o \ + nswalk.o \ + nsxfobj.o \ + osunixxf.o \ + psargs.o \ + psloop.o \ + psopcode.o \ + psparse.o \ + psscope.o \ + pstree.o \ + psutils.o \ + pswalk.o \ + tbfadt.o \ + tbinstal.o \ + tbutils.o \ + tbxface.o \ + utaddress.o \ + utalloc.o \ + utcache.o \ + utcopy.o \ + utdebug.o \ + utdecode.o \ + utdelete.o \ + utglobal.o \ + utinit.o \ + utlock.o \ + utmath.o \ + utmisc.o \ + utmutex.o \ + utobject.o \ + utresrc.o \ + utstate.o \ + utxferror.o \ + utxface.o + +INTERMEDIATES = \ + aslcompilerlex.c \ + aslcompilerparse.c \ + dtparserlex.c \ + dtparserparse.c + +MISC = \ + aslcompilerparse.h \ + aslcompiler.y.h \ + aslcompilerparse.output \ + dtparserparse.h \ + dtparser.y.h \ + dtparserparse.output + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_ASL_COMPILER \ + -I$(ACPICA_INCLUDE) \ + -I$(ASL_COMPILER) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Bison/Flex configuration +# +YACC= bison +YFLAGS+= -v -d -y + +LEX= flex +LFLAGS+= -i -s + +# +# Root rule +# +$(PROG) : $(INTERMEDIATES) $(MISC) $(OBJECTS) + $(CC) $(OBJECTS) $(LDFLAGS) -o $(PROG) + +# +# Parser and Lexer - intermediate C files +# +aslcompilerlex.c : $(ASL_COMPILER)/aslcompiler.l + ${LEX} ${LFLAGS} -PAslCompiler -o$@ $? + +aslcompilerparse.c aslcompilerparse.h : $(ASL_COMPILER)/aslcompiler.y + ${YACC} ${YFLAGS} -pAslCompiler -o$@ $? + +dtparserlex.c : $(ASL_COMPILER)/dtparser.l + ${LEX} ${LFLAGS} -PDtParser -o$@ $? + +dtparserparse.c dtparserparse.h : $(ASL_COMPILER)/dtparser.y + ${YACC} ${YFLAGS} -pDtParser -o$@ $? + +# Rename headers produced by bison/yacc + +dtparser.y.h: dtparserparse.h + @echo Copy intermediate file: + @cp -f -v dtparserparse.h dtparser.y.h + +aslcompiler.y.h : aslcompilerparse.h + @echo Copy intermediate file: + @cp -f -v aslcompilerparse.h aslcompiler.y.h + + +# +# Parsers and Lexers - final object files +# +# Cannot use the common compile warning flags since the C files are created +# by the utilities above and they are not necessarily ANSI C, etc. +# +aslcompilerlex.o : aslcompilerlex.c + $(CC) -c $(CFLAGS) -Wall -Werror -Wstrict-aliasing=0 -o$@ $? + +aslcompilerparse.o : aslcompilerparse.c + $(CC) -c $(CFLAGS) -Wall -Werror -Wstrict-aliasing=0 -o$@ $? + +dtparserlex.o : dtparserlex.c + $(CC) -c $(CFLAGS) -Wall -Werror -Wstrict-aliasing=0 -o$@ $? + +dtparserparse.o : dtparserparse.c + $(CC) -c $(CFLAGS) -Wall -Werror -Wstrict-aliasing=0 -o$@ $? + + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) $(INTERMEDIATES) $(MISC) + +install : + $(INSTALLPROG) diff --git a/source/compiler/aslanalyze.c b/source/compiler/aslanalyze.c new file mode 100644 index 000000000000..7605bf4a072a --- /dev/null +++ b/source/compiler/aslanalyze.c @@ -0,0 +1,569 @@ +/****************************************************************************** + * + * Module Name: aslanalyze.c - Support functions for parse tree walks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslanalyze") + + +/******************************************************************************* + * + * FUNCTION: AnIsInternalMethod + * + * PARAMETERS: Op - Current op + * + * RETURN: Boolean + * + * DESCRIPTION: Check for an internal control method. + * + ******************************************************************************/ + +BOOLEAN +AnIsInternalMethod ( + ACPI_PARSE_OBJECT *Op) +{ + + if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) || + (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI"))) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AnGetInternalMethodReturnType + * + * PARAMETERS: Op - Current op + * + * RETURN: Btype + * + * DESCRIPTION: Get the return type of an internal method + * + ******************************************************************************/ + +UINT32 +AnGetInternalMethodReturnType ( + ACPI_PARSE_OBJECT *Op) +{ + + if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) || + (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI"))) + { + return (ACPI_BTYPE_STRING); + } + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: AnCheckId + * + * PARAMETERS: Op - Current parse op + * Type - HID or CID + * + * RETURN: None + * + * DESCRIPTION: Perform various checks on _HID and _CID strings. Only limited + * checks can be performed on _CID strings. + * + ******************************************************************************/ + +void +AnCheckId ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAME Type) +{ + UINT32 i; + ACPI_SIZE Length; + + + /* Only care about string versions of _HID/_CID (integers are legal) */ + + if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL) + { + return; + } + + /* For both _HID and _CID, the string must be non-null */ + + Length = strlen (Op->Asl.Value.String); + if (!Length) + { + AslError (ASL_ERROR, ASL_MSG_NULL_STRING, + Op, NULL); + return; + } + + /* + * One of the things we want to catch here is the use of a leading + * asterisk in the string -- an odd construct that certain platform + * manufacturers are fond of. Technically, a leading asterisk is OK + * for _CID, but a valid use of this has not been seen. + */ + if (*Op->Asl.Value.String == '*') + { + AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK, + Op, Op->Asl.Value.String); + return; + } + + /* _CID strings are bus-specific, no more checks can be performed */ + + if (Type == ASL_TYPE_CID) + { + return; + } + + /* For _HID, all characters must be alphanumeric */ + + for (i = 0; Op->Asl.Value.String[i]; i++) + { + if (!isalnum ((int) Op->Asl.Value.String[i])) + { + AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, + Op, Op->Asl.Value.String); + return; + } + } + + /* + * _HID String must be one of these forms: + * + * "AAA####" A is an uppercase letter and # is a hex digit + * "ACPI####" # is a hex digit + * "NNNN####" N is an uppercase letter or decimal digit (0-9) + * # is a hex digit (ACPI 5.0) + */ + if ((Length < 7) || (Length > 8)) + { + AslError (ASL_ERROR, ASL_MSG_HID_LENGTH, + Op, Op->Asl.Value.String); + return; + } + + /* _HID Length is valid (7 or 8), now check the prefix (first 3 or 4 chars) */ + + if (Length == 7) + { + /* AAA####: Ensure the alphabetic prefix is all uppercase */ + + for (i = 0; i < 3; i++) + { + if (!isupper ((int) Op->Asl.Value.String[i])) + { + AslError (ASL_ERROR, ASL_MSG_UPPER_CASE, + Op, &Op->Asl.Value.String[i]); + return; + } + } + } + else /* Length == 8 */ + { + /* + * ACPI#### or NNNN####: + * Ensure the prefix contains only uppercase alpha or decimal digits + */ + for (i = 0; i < 4; i++) + { + if (!isupper ((int) Op->Asl.Value.String[i]) && + !isdigit ((int) Op->Asl.Value.String[i])) + { + AslError (ASL_ERROR, ASL_MSG_HID_PREFIX, + Op, &Op->Asl.Value.String[i]); + return; + } + } + } + + /* Remaining characters (suffix) must be hex digits */ + + for (; i < Length; i++) + { + if (!isxdigit ((int) Op->Asl.Value.String[i])) + { + AslError (ASL_ERROR, ASL_MSG_HID_SUFFIX, + Op, &Op->Asl.Value.String[i]); + break; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AnLastStatementIsReturn + * + * PARAMETERS: Op - A method parse node + * + * RETURN: TRUE if last statement is an ASL RETURN. False otherwise + * + * DESCRIPTION: Walk down the list of top level statements within a method + * to find the last one. Check if that last statement is in + * fact a RETURN statement. + * + ******************************************************************************/ + +BOOLEAN +AnLastStatementIsReturn ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Check if last statement is a return */ + + Next = ASL_GET_CHILD_NODE (Op); + while (Next) + { + if ((!Next->Asl.Next) && + (Next->Asl.ParseOpcode == PARSEOP_RETURN)) + { + return (TRUE); + } + + Next = ASL_GET_PEER_NODE (Next); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AnCheckMethodReturnValue + * + * PARAMETERS: Op - Parent + * OpInfo - Parent info + * ArgOp - Method invocation op + * RequiredBtypes - What caller requires + * ThisNodeBtype - What this node returns (if anything) + * + * RETURN: None + * + * DESCRIPTION: Check a method invocation for 1) A return value and if it does + * in fact return a value, 2) check the type of the return value. + * + ******************************************************************************/ + +void +AnCheckMethodReturnValue ( + ACPI_PARSE_OBJECT *Op, + const ACPI_OPCODE_INFO *OpInfo, + ACPI_PARSE_OBJECT *ArgOp, + UINT32 RequiredBtypes, + UINT32 ThisNodeBtype) +{ + ACPI_PARSE_OBJECT *OwningOp; + ACPI_NAMESPACE_NODE *Node; + + + Node = ArgOp->Asl.Node; + + + /* Examine the parent op of this method */ + + OwningOp = Node->Op; + if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL) + { + /* Method NEVER returns a value */ + + AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName); + } + else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL) + { + /* Method SOMETIMES returns a value, SOMETIMES not */ + + AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName); + } + else if (!(ThisNodeBtype & RequiredBtypes)) + { + /* Method returns a value, but the type is wrong */ + + AnFormatBtype (StringBuffer, ThisNodeBtype); + AnFormatBtype (StringBuffer2, RequiredBtypes); + + /* + * The case where the method does not return any value at all + * was already handled in the namespace cross reference + * -- Only issue an error if the method in fact returns a value, + * but it is of the wrong type + */ + if (ThisNodeBtype != 0) + { + sprintf (MsgBuffer, + "Method returns [%s], %s operator requires [%s]", + StringBuffer, OpInfo->Name, StringBuffer2); + + AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AnIsResultUsed + * + * PARAMETERS: Op - Parent op for the operator + * + * RETURN: TRUE if result from this operation is actually consumed + * + * DESCRIPTION: Determine if the function result value from an operator is + * used. + * + ******************************************************************************/ + +BOOLEAN +AnIsResultUsed ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Parent; + + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_INCREMENT: + case PARSEOP_DECREMENT: + + /* These are standalone operators, no return value */ + + return (TRUE); + + default: + break; + } + + /* Examine parent to determine if the return value is used */ + + Parent = Op->Asl.Parent; + switch (Parent->Asl.ParseOpcode) + { + /* If/While - check if the operator is the predicate */ + + case PARSEOP_IF: + case PARSEOP_WHILE: + + /* First child is the predicate */ + + if (Parent->Asl.Child == Op) + { + return (TRUE); + } + return (FALSE); + + /* Not used if one of these is the parent */ + + case PARSEOP_METHOD: + case PARSEOP_DEFINITIONBLOCK: + case PARSEOP_ELSE: + + return (FALSE); + + default: + /* Any other type of parent means that the result is used */ + + return (TRUE); + } +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckForGpeNameConflict + * + * PARAMETERS: Op - Current parse op + * + * RETURN: None + * + * DESCRIPTION: Check for a conflict between GPE names within this scope. + * Conflict means two GPE names with the same GPE number, but + * different types -- such as _L1C and _E1C. + * + ******************************************************************************/ + +void +ApCheckForGpeNameConflict ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *NextOp; + UINT32 GpeNumber; + char Name[ACPI_NAME_SIZE + 1]; + char Target[ACPI_NAME_SIZE]; + + + /* Need a null-terminated string version of NameSeg */ + + ACPI_MOVE_32_TO_32 (Name, &Op->Asl.NameSeg); + Name[ACPI_NAME_SIZE] = 0; + + /* + * For a GPE method: + * 1st char must be underscore + * 2nd char must be L or E + * 3rd/4th chars must be a hex number + */ + if ((Name[0] != '_') || + ((Name[1] != 'L') && (Name[1] != 'E'))) + { + return; + } + + /* Verify 3rd/4th chars are a valid hex value */ + + GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); + if (GpeNumber == ACPI_UINT32_MAX) + { + return; + } + + /* + * We are now sure we have an _Lxx or _Exx. + * Create the target name that would cause collision (Flip E/L) + */ + ACPI_MOVE_32_TO_32 (Target, Name); + + /* Inject opposite letter ("L" versus "E") */ + + if (Name[1] == 'L') + { + Target[1] = 'E'; + } + else /* Name[1] == 'E' */ + { + Target[1] = 'L'; + } + + /* Search all peers (objects within this scope) for target match */ + + NextOp = Op->Asl.Next; + while (NextOp) + { + /* + * We mostly care about methods, but check Name() constructs also, + * even though they will get another error for not being a method. + * All GPE names must be defined as control methods. + */ + if ((NextOp->Asl.ParseOpcode == PARSEOP_METHOD) || + (NextOp->Asl.ParseOpcode == PARSEOP_NAME)) + { + if (ACPI_COMPARE_NAME (Target, NextOp->Asl.NameSeg)) + { + /* Found both _Exy and _Lxy in the same scope, error */ + + AslError (ASL_ERROR, ASL_MSG_GPE_NAME_CONFLICT, NextOp, + Name); + return; + } + } + + NextOp = NextOp->Asl.Next; + } + + /* OK, no conflict found */ + + return; +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckRegMethod + * + * PARAMETERS: Op - Current parse op + * + * RETURN: None + * + * DESCRIPTION: Ensure that a _REG method has a corresponding Operation + * Region declaration within the same scope. Note: _REG is defined + * to have two arguments and must therefore be defined as a + * control method. + * + ******************************************************************************/ + +void +ApCheckRegMethod ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_PARSE_OBJECT *Parent; + + + /* We are only interested in _REG methods */ + + if (!ACPI_COMPARE_NAME (METHOD_NAME__REG, &Op->Asl.NameSeg)) + { + return; + } + + /* Get the start of the current scope */ + + Parent = Op->Asl.Parent; + Next = Parent->Asl.Child; + + /* Search entire scope for an operation region declaration */ + + while (Next) + { + if (Next->Asl.ParseOpcode == PARSEOP_OPERATIONREGION) + { + return; /* Found region, OK */ + } + + Next = Next->Asl.Next; + } + + /* No region found, issue warning */ + + AslError (ASL_WARNING, ASL_MSG_NO_REGION, Op, NULL); +} diff --git a/source/compiler/aslbtypes.c b/source/compiler/aslbtypes.c new file mode 100644 index 000000000000..85561722db54 --- /dev/null +++ b/source/compiler/aslbtypes.c @@ -0,0 +1,525 @@ +/****************************************************************************** + * + * Module Name: aslbtypes - Support for bitfield types + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslbtypes") + +/* Local prototypes */ + +static UINT32 +AnMapEtypeToBtype ( + UINT32 Etype); + + +/******************************************************************************* + * + * FUNCTION: AnMapArgTypeToBtype + * + * PARAMETERS: ArgType - The ARGI required type(s) for this + * argument, from the opcode info table + * + * RETURN: The corresponding Bit-encoded types + * + * DESCRIPTION: Convert an encoded ARGI required argument type code into a + * bitfield type code. Implements the implicit source conversion + * rules. + * + ******************************************************************************/ + +UINT32 +AnMapArgTypeToBtype ( + UINT32 ArgType) +{ + + switch (ArgType) + { + + /* Simple types */ + + case ARGI_ANYTYPE: + return (ACPI_BTYPE_OBJECTS_AND_REFS); + + case ARGI_PACKAGE: + return (ACPI_BTYPE_PACKAGE); + + case ARGI_EVENT: + return (ACPI_BTYPE_EVENT); + + case ARGI_MUTEX: + return (ACPI_BTYPE_MUTEX); + + case ARGI_DDBHANDLE: + /* + * DDBHandleObject := SuperName + * ACPI_BTYPE_REFERENCE: Index reference as parameter of Load/Unload + */ + return (ACPI_BTYPE_DDB_HANDLE | ACPI_BTYPE_REFERENCE); + + /* Interchangeable types */ + /* + * Source conversion rules: + * Integer, String, and Buffer are all interchangeable + */ + case ARGI_INTEGER: + case ARGI_STRING: + case ARGI_BUFFER: + case ARGI_BUFFER_OR_STRING: + case ARGI_COMPUTEDATA: + return (ACPI_BTYPE_COMPUTE_DATA); + + /* References */ + + case ARGI_INTEGER_REF: + return (ACPI_BTYPE_INTEGER); + + case ARGI_OBJECT_REF: + return (ACPI_BTYPE_ALL_OBJECTS); + + case ARGI_DEVICE_REF: + return (ACPI_BTYPE_DEVICE_OBJECTS); + + case ARGI_REFERENCE: + return (ACPI_BTYPE_REFERENCE); + + case ARGI_TARGETREF: + case ARGI_FIXED_TARGET: + case ARGI_SIMPLE_TARGET: + return (ACPI_BTYPE_OBJECTS_AND_REFS); + + /* Complex types */ + + case ARGI_DATAOBJECT: + + /* + * Buffer, string, package or reference to a Op - + * Used only by SizeOf operator + */ + return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | + ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE); + + case ARGI_COMPLEXOBJ: + + /* Buffer, String, or package */ + + return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | ACPI_BTYPE_PACKAGE); + + case ARGI_REF_OR_STRING: + return (ACPI_BTYPE_STRING | ACPI_BTYPE_REFERENCE); + + case ARGI_REGION_OR_BUFFER: + + /* Used by Load() only. Allow buffers in addition to regions/fields */ + + return (ACPI_BTYPE_REGION | ACPI_BTYPE_BUFFER | ACPI_BTYPE_FIELD_UNIT); + + case ARGI_DATAREFOBJ: + return (ACPI_BTYPE_INTEGER |ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | + ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE); + + default: + break; + } + + return (ACPI_BTYPE_OBJECTS_AND_REFS); +} + + +/******************************************************************************* + * + * FUNCTION: AnMapEtypeToBtype + * + * PARAMETERS: Etype - Encoded ACPI Type + * + * RETURN: Btype corresponding to the Etype + * + * DESCRIPTION: Convert an encoded ACPI type to a bitfield type applying the + * operand conversion rules. In other words, returns the type(s) + * this Etype is implicitly converted to during interpretation. + * + ******************************************************************************/ + +static UINT32 +AnMapEtypeToBtype ( + UINT32 Etype) +{ + + + if (Etype == ACPI_TYPE_ANY) + { + return (ACPI_BTYPE_OBJECTS_AND_REFS); + } + + /* Try the standard ACPI data types */ + + if (Etype <= ACPI_TYPE_EXTERNAL_MAX) + { + /* + * This switch statement implements the allowed operand conversion + * rules as per the "ASL Data Types" section of the ACPI + * specification. + */ + switch (Etype) + { + case ACPI_TYPE_INTEGER: + return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_DDB_HANDLE); + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + return (ACPI_BTYPE_COMPUTE_DATA); + + case ACPI_TYPE_PACKAGE: + return (ACPI_BTYPE_PACKAGE); + + case ACPI_TYPE_FIELD_UNIT: + return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); + + case ACPI_TYPE_BUFFER_FIELD: + return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_BUFFER_FIELD); + + case ACPI_TYPE_DDB_HANDLE: + return (ACPI_BTYPE_INTEGER | ACPI_BTYPE_DDB_HANDLE); + + case ACPI_BTYPE_DEBUG_OBJECT: + + /* Cannot be used as a source operand */ + + return (0); + + default: + return (1 << (Etype - 1)); + } + } + + /* Try the internal data types */ + + switch (Etype) + { + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* Named fields can be either Integer/Buffer/String */ + + return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); + + case ACPI_TYPE_LOCAL_ALIAS: + + return (ACPI_BTYPE_INTEGER); + + + case ACPI_TYPE_LOCAL_RESOURCE: + case ACPI_TYPE_LOCAL_RESOURCE_FIELD: + + return (ACPI_BTYPE_REFERENCE); + + default: + printf ("Unhandled encoded type: %X\n", Etype); + return (0); + } +} + + +/******************************************************************************* + * + * FUNCTION: AnFormatBtype + * + * PARAMETERS: Btype - Bitfield of ACPI types + * Buffer - Where to put the ascii string + * + * RETURN: None. + * + * DESCRIPTION: Convert a Btype to a string of ACPI types + * + ******************************************************************************/ + +void +AnFormatBtype ( + char *Buffer, + UINT32 Btype) +{ + UINT32 Type; + BOOLEAN First = TRUE; + + + *Buffer = 0; + + if (Btype == 0) + { + strcat (Buffer, "NoReturnValue"); + return; + } + + for (Type = 1; Type <= ACPI_TYPE_EXTERNAL_MAX; Type++) + { + if (Btype & 0x00000001) + { + if (!First) + { + strcat (Buffer, "|"); + } + First = FALSE; + strcat (Buffer, AcpiUtGetTypeName (Type)); + } + Btype >>= 1; + } + + if (Btype & 0x00000001) + { + if (!First) + { + strcat (Buffer, "|"); + } + First = FALSE; + strcat (Buffer, "Reference"); + } + + Btype >>= 1; + if (Btype & 0x00000001) + { + if (!First) + { + strcat (Buffer, "|"); + } + First = FALSE; + strcat (Buffer, "Resource"); + } +} + + +/******************************************************************************* + * + * FUNCTION: AnGetBtype + * + * PARAMETERS: Op - Parse node whose type will be returned. + * + * RETURN: The Btype associated with the Op. + * + * DESCRIPTION: Get the (bitfield) ACPI type associated with the parse node. + * Handles the case where the node is a name or method call and + * the actual type must be obtained from the namespace node. + * + ******************************************************************************/ + +UINT32 +AnGetBtype ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *ReferencedNode; + UINT32 ThisNodeBtype = 0; + + + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || + (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) + { + Node = Op->Asl.Node; + if (!Node) + { + DbgPrint (ASL_DEBUG_OUTPUT, + "No attached Nsnode: [%s] at line %u name [%s], ignoring typecheck\n", + Op->Asl.ParseOpName, Op->Asl.LineNumber, + Op->Asl.ExternalName); + return (ACPI_UINT32_MAX); + } + + ThisNodeBtype = AnMapEtypeToBtype (Node->Type); + if (!ThisNodeBtype) + { + AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, + "could not map type"); + } + + /* + * Since it was a named reference, enable the + * reference bit also + */ + ThisNodeBtype |= ACPI_BTYPE_REFERENCE; + + if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) + { + ReferencedNode = Node->Op; + if (!ReferencedNode) + { + /* Check for an internal method */ + + if (AnIsInternalMethod (Op)) + { + return (AnGetInternalMethodReturnType (Op)); + } + + AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, + "null Op pointer"); + return (ACPI_UINT32_MAX); + } + + if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED) + { + ThisNodeBtype = ReferencedNode->Asl.AcpiBtype; + } + else + { + return (ACPI_UINT32_MAX -1); + } + } + } + else + { + ThisNodeBtype = Op->Asl.AcpiBtype; + } + + return (ThisNodeBtype); +} + + +/******************************************************************************* + * + * FUNCTION: AnMapObjTypeToBtype + * + * PARAMETERS: Op - A parse node + * + * RETURN: A Btype + * + * DESCRIPTION: Map object to the associated "Btype" + * + ******************************************************************************/ + +UINT32 +AnMapObjTypeToBtype ( + ACPI_PARSE_OBJECT *Op) +{ + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_OBJECTTYPE_BFF: /* "BuffFieldObj" */ + return (ACPI_BTYPE_BUFFER_FIELD); + + case PARSEOP_OBJECTTYPE_BUF: /* "BuffObj" */ + return (ACPI_BTYPE_BUFFER); + + case PARSEOP_OBJECTTYPE_DDB: /* "DDBHandleObj" */ + return (ACPI_BTYPE_DDB_HANDLE); + + case PARSEOP_OBJECTTYPE_DEV: /* "DeviceObj" */ + return (ACPI_BTYPE_DEVICE); + + case PARSEOP_OBJECTTYPE_EVT: /* "EventObj" */ + return (ACPI_BTYPE_EVENT); + + case PARSEOP_OBJECTTYPE_FLD: /* "FieldUnitObj" */ + return (ACPI_BTYPE_FIELD_UNIT); + + case PARSEOP_OBJECTTYPE_INT: /* "IntObj" */ + return (ACPI_BTYPE_INTEGER); + + case PARSEOP_OBJECTTYPE_MTH: /* "MethodObj" */ + return (ACPI_BTYPE_METHOD); + + case PARSEOP_OBJECTTYPE_MTX: /* "MutexObj" */ + return (ACPI_BTYPE_MUTEX); + + case PARSEOP_OBJECTTYPE_OPR: /* "OpRegionObj" */ + return (ACPI_BTYPE_REGION); + + case PARSEOP_OBJECTTYPE_PKG: /* "PkgObj" */ + return (ACPI_BTYPE_PACKAGE); + + case PARSEOP_OBJECTTYPE_POW: /* "PowerResObj" */ + return (ACPI_BTYPE_POWER); + + case PARSEOP_OBJECTTYPE_STR: /* "StrObj" */ + return (ACPI_BTYPE_STRING); + + case PARSEOP_OBJECTTYPE_THZ: /* "ThermalZoneObj" */ + return (ACPI_BTYPE_THERMAL); + + case PARSEOP_OBJECTTYPE_UNK: /* "UnknownObj" */ + return (ACPI_BTYPE_OBJECTS_AND_REFS); + + default: + return (0); + } +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AnMapBtypeToEtype + * + * PARAMETERS: Btype - Bitfield of ACPI types + * + * RETURN: The Etype corresponding the the Btype + * + * DESCRIPTION: Convert a bitfield type to an encoded type + * + ******************************************************************************/ + +UINT32 +AnMapBtypeToEtype ( + UINT32 Btype) +{ + UINT32 i; + UINT32 Etype; + + + if (Btype == 0) + { + return (0); + } + + Etype = 1; + for (i = 1; i < Btype; i *= 2) + { + Etype++; + } + + return (Etype); +} +#endif diff --git a/source/compiler/aslcodegen.c b/source/compiler/aslcodegen.c new file mode 100644 index 000000000000..825dd194fc07 --- /dev/null +++ b/source/compiler/aslcodegen.c @@ -0,0 +1,593 @@ + +/****************************************************************************** + * + * Module Name: aslcodegen - AML code generation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslcodegen") + +/* Local prototypes */ + +static ACPI_STATUS +CgAmlWriteWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static void +CgLocalWriteAmlData ( + ACPI_PARSE_OBJECT *Op, + void *Buffer, + UINT32 Length); + +static void +CgWriteAmlOpcode ( + ACPI_PARSE_OBJECT *Op); + +static void +CgWriteTableHeader ( + ACPI_PARSE_OBJECT *Op); + +static void +CgCloseTable ( + void); + +static void +CgWriteNode ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: CgGenerateAmlOutput + * + * PARAMETERS: None. + * + * RETURN: None + * + * DESCRIPTION: Generate AML code. Currently generates the listing file + * simultaneously. + * + ******************************************************************************/ + +void +CgGenerateAmlOutput ( + void) +{ + + DbgPrint (ASL_DEBUG_OUTPUT, "\nWriting AML\n\n"); + + /* Generate the AML output file */ + + FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); + Gbl_SourceLine = 0; + Gbl_NextError = Gbl_ErrorLog; + + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, + CgAmlWriteWalk, NULL, NULL); + CgCloseTable (); +} + + +/******************************************************************************* + * + * FUNCTION: CgAmlWriteWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Parse tree walk to generate the AML code. + * + ******************************************************************************/ + +static ACPI_STATUS +CgAmlWriteWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + /* + * Print header at level 0. Alignment assumes 32-bit pointers + */ + if (!Level) + { + DbgPrint (ASL_TREE_OUTPUT, + "Final parse tree used for AML output:\n"); + DbgPrint (ASL_TREE_OUTPUT, + "%*s Value P_Op A_Op OpLen PByts Len SubLen PSubLen OpPtr Child Parent Flags AcTyp Final Col L\n", + 76, " "); + } + + /* Debug output */ + + DbgPrint (ASL_TREE_OUTPUT, + "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level); + UtPrintFormattedName (Op->Asl.ParseOpcode, Level); + + if (Op->Asl.ParseOpcode == PARSEOP_NAMESEG || + Op->Asl.ParseOpcode == PARSEOP_NAMESTRING || + Op->Asl.ParseOpcode == PARSEOP_METHODCALL) + { + DbgPrint (ASL_TREE_OUTPUT, + "%10.32s ", Op->Asl.ExternalName); + } + else + { + DbgPrint (ASL_TREE_OUTPUT, " "); + } + + DbgPrint (ASL_TREE_OUTPUT, + "%08X %04X %04X %01X %04X %04X %04X %04X %08X %08X %08X %08X %08X %04X %02d %02d\n", + /* 1 */ (UINT32) Op->Asl.Value.Integer, + /* 2 */ Op->Asl.ParseOpcode, + /* 3 */ Op->Asl.AmlOpcode, + /* 4 */ Op->Asl.AmlOpcodeLength, + /* 5 */ Op->Asl.AmlPkgLenBytes, + /* 6 */ Op->Asl.AmlLength, + /* 7 */ Op->Asl.AmlSubtreeLength, + /* 8 */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0, + /* 9 */ Op, + /* 10 */ Op->Asl.Child, + /* 11 */ Op->Asl.Parent, + /* 12 */ Op->Asl.CompileFlags, + /* 13 */ Op->Asl.AcpiBtype, + /* 14 */ Op->Asl.FinalAmlLength, + /* 15 */ Op->Asl.Column, + /* 16 */ Op->Asl.LineNumber); + + /* Generate the AML for this node */ + + CgWriteNode (Op); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: CgLocalWriteAmlData + * + * PARAMETERS: Op - Current parse op + * Buffer - Buffer to write + * Length - Size of data in buffer + * + * RETURN: None + * + * DESCRIPTION: Write a buffer of AML data to the AML output file. + * + ******************************************************************************/ + +static void +CgLocalWriteAmlData ( + ACPI_PARSE_OBJECT *Op, + void *Buffer, + UINT32 Length) +{ + + /* Write the raw data to the AML file */ + + FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length); + + /* Update the final AML length for this node (used for listings) */ + + if (Op) + { + Op->Asl.FinalAmlLength += Length; + } +} + + +/******************************************************************************* + * + * FUNCTION: CgWriteAmlOpcode + * + * PARAMETERS: Op - Parse node with an AML opcode + * + * RETURN: None. + * + * DESCRIPTION: Write the AML opcode corresponding to a parse node. + * + ******************************************************************************/ + +static void +CgWriteAmlOpcode ( + ACPI_PARSE_OBJECT *Op) +{ + UINT8 PkgLenFirstByte; + UINT32 i; + union { + UINT16 Opcode; + UINT8 OpcodeBytes[2]; + } Aml; + union { + UINT32 Len; + UINT8 LenBytes[4]; + } PkgLen; + + + /* We expect some DEFAULT_ARGs, just ignore them */ + + if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + return; + } + + switch (Op->Asl.AmlOpcode) + { + case AML_UNASSIGNED_OPCODE: + + /* These opcodes should not get here */ + + printf ("Found a node with an unassigned AML opcode\n"); + fprintf (stderr, "Found a node with an unassigned AML opcode\n"); + return; + + case AML_INT_RESERVEDFIELD_OP: + + /* Special opcodes for within a field definition */ + + Aml.Opcode = AML_FIELD_OFFSET_OP; + break; + + case AML_INT_ACCESSFIELD_OP: + + Aml.Opcode = AML_FIELD_ACCESS_OP; + break; + + case AML_INT_CONNECTION_OP: + + Aml.Opcode = AML_FIELD_CONNECTION_OP; + break; + + default: + Aml.Opcode = Op->Asl.AmlOpcode; + break; + } + + + switch (Aml.Opcode) + { + case AML_PACKAGE_LENGTH: + + /* Value is the length to be encoded (Used in field definitions) */ + + PkgLen.Len = (UINT32) Op->Asl.Value.Integer; + break; + + default: + + /* Check for two-byte opcode */ + + if (Aml.Opcode > 0x00FF) + { + /* Write the high byte first */ + + CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1); + } + + CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1); + + /* Subtreelength doesn't include length of package length bytes */ + + PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes; + break; + } + + /* Does this opcode have an associated "PackageLength" field? */ + + if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) + { + if (Op->Asl.AmlPkgLenBytes == 1) + { + /* Simplest case -- no bytes to follow, just write the count */ + + CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1); + } + else if (Op->Asl.AmlPkgLenBytes != 0) + { + /* + * Encode the "bytes to follow" in the first byte, top two bits. + * The low-order nybble of the length is in the bottom 4 bits + */ + PkgLenFirstByte = (UINT8) + (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) | + (PkgLen.LenBytes[0] & 0x0F)); + + CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1); + + /* + * Shift the length over by the 4 bits we just stuffed + * in the first byte + */ + PkgLen.Len >>= 4; + + /* Now we can write the remaining bytes - either 1, 2, or 3 bytes */ + + for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++) + { + CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1); + } + } + } + + switch (Aml.Opcode) + { + case AML_BYTE_OP: + + CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1); + break; + + case AML_WORD_OP: + + CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2); + break; + + case AML_DWORD_OP: + + CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4); + break; + + case AML_QWORD_OP: + + CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8); + break; + + case AML_STRING_OP: + + CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength); + break; + + default: + /* All data opcodes must appear above */ + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: CgWriteTableHeader + * + * PARAMETERS: Op - The DEFINITIONBLOCK node + * + * RETURN: None + * + * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK + * + ******************************************************************************/ + +static void +CgWriteTableHeader ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Child; + + + /* AML filename */ + + Child = Op->Asl.Child; + + /* Signature */ + + Child = Child->Asl.Next; + strncpy (TableHeader.Signature, Child->Asl.Value.String, 4); + + /* Revision */ + + Child = Child->Asl.Next; + TableHeader.Revision = (UINT8) Child->Asl.Value.Integer; + + /* Command-line Revision override */ + + if (Gbl_RevisionOverride) + { + TableHeader.Revision = Gbl_RevisionOverride; + } + + /* OEMID */ + + Child = Child->Asl.Next; + strncpy (TableHeader.OemId, Child->Asl.Value.String, 6); + + /* OEM TableID */ + + Child = Child->Asl.Next; + strncpy (TableHeader.OemTableId, Child->Asl.Value.String, 8); + + /* OEM Revision */ + + Child = Child->Asl.Next; + TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer; + + /* Compiler ID */ + + strncpy (TableHeader.AslCompilerId, ASL_CREATOR_ID, 4); + + /* Compiler version */ + + TableHeader.AslCompilerRevision = ASL_REVISION; + + /* Table length. Checksum zero for now, will rewrite later */ + + TableHeader.Length = Gbl_TableLength; + TableHeader.Checksum = 0; + + CgLocalWriteAmlData (Op, &TableHeader, sizeof (ACPI_TABLE_HEADER)); +} + + +/******************************************************************************* + * + * FUNCTION: CgCloseTable + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Complete the ACPI table by calculating the checksum and + * re-writing the header. + * + ******************************************************************************/ + +static void +CgCloseTable ( + void) +{ + signed char Sum; + UINT8 FileByte; + + + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + Sum = 0; + + /* Calculate the checksum over the entire file */ + + while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) == AE_OK) + { + Sum = (signed char) (Sum + FileByte); + } + + /* Re-write the table header with the checksum */ + + TableHeader.Checksum = (UINT8) (0 - Sum); + + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + CgLocalWriteAmlData (NULL, &TableHeader, sizeof (ACPI_TABLE_HEADER)); +} + + +/******************************************************************************* + * + * FUNCTION: CgWriteNode + * + * PARAMETERS: Op - Parse node to write. + * + * RETURN: None. + * + * DESCRIPTION: Write the AML that corresponds to a parse node. + * + ******************************************************************************/ + +static void +CgWriteNode ( + ACPI_PARSE_OBJECT *Op) +{ + ASL_RESOURCE_NODE *Rnode; + + + /* Always check for DEFAULT_ARG and other "Noop" nodes */ + /* TBD: this may not be the best place for this check */ + + if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) || + (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) || + (Op->Asl.ParseOpcode == PARSEOP_INCLUDE) || + (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END)) + { + return; + } + + Op->Asl.FinalAmlLength = 0; + + switch (Op->Asl.AmlOpcode) + { + case AML_RAW_DATA_BYTE: + case AML_RAW_DATA_WORD: + case AML_RAW_DATA_DWORD: + case AML_RAW_DATA_QWORD: + + CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength); + return; + + + case AML_RAW_DATA_BUFFER: + + CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength); + return; + + + case AML_RAW_DATA_CHAIN: + + Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer); + while (Rnode) + { + CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength); + Rnode = Rnode->Next; + } + return; + + default: + /* Internal data opcodes must all appear above */ + break; + } + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFAULT_ARG: + + break; + + case PARSEOP_DEFINITIONBLOCK: + + CgWriteTableHeader (Op); + break; + + case PARSEOP_NAMESEG: + case PARSEOP_NAMESTRING: + case PARSEOP_METHODCALL: + + CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength); + break; + + default: + + CgWriteAmlOpcode (Op); + break; + } +} + + diff --git a/source/compiler/aslcompile.c b/source/compiler/aslcompile.c new file mode 100644 index 000000000000..8f16bf3547f2 --- /dev/null +++ b/source/compiler/aslcompile.c @@ -0,0 +1,845 @@ + +/****************************************************************************** + * + * Module Name: aslcompile - top level compile module + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" + +#include +#include +#include + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslcompile") + +/* Local prototypes */ + +static void +CmFlushSourceCode ( + void); + +static void +FlConsumeAnsiComment ( + ASL_FILE_INFO *FileInfo, + ASL_FILE_STATUS *Status); + +static void +FlConsumeNewComment ( + ASL_FILE_INFO *FileInfo, + ASL_FILE_STATUS *Status); + + +/******************************************************************************* + * + * FUNCTION: AslCompilerSignon + * + * PARAMETERS: FileId - ID of the output file + * + * RETURN: None + * + * DESCRIPTION: Display compiler signon + * + ******************************************************************************/ + +void +AslCompilerSignon ( + UINT32 FileId) +{ + char *Prefix = ""; + char *UtilityName; + + + /* Set line prefix depending on the destination file type */ + + switch (FileId) + { + case ASL_FILE_ASM_SOURCE_OUTPUT: + case ASL_FILE_ASM_INCLUDE_OUTPUT: + + Prefix = "; "; + break; + + case ASL_FILE_HEX_OUTPUT: + + if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM) + { + Prefix = "; "; + } + else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) || + (Gbl_HexOutputFlag == HEX_OUTPUT_ASL)) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n"); + Prefix = " * "; + } + break; + + case ASL_FILE_C_SOURCE_OUTPUT: + case ASL_FILE_C_INCLUDE_OUTPUT: + + Prefix = " * "; + break; + + default: + /* No other output types supported */ + break; + } + + /* Running compiler or disassembler? */ + + if (Gbl_DisasmFlag) + { + UtilityName = AML_DISASSEMBLER_NAME; + } + else + { + UtilityName = ASL_COMPILER_NAME; + } + + /* Compiler signon with copyright */ + + FlPrintFile (FileId, "%s\n", Prefix); + FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix)); +} + + +/******************************************************************************* + * + * FUNCTION: AslCompilerFileHeader + * + * PARAMETERS: FileId - ID of the output file + * + * RETURN: None + * + * DESCRIPTION: Header used at the beginning of output files + * + ******************************************************************************/ + +void +AslCompilerFileHeader ( + UINT32 FileId) +{ + struct tm *NewTime; + time_t Aclock; + char *Prefix = ""; + + + /* Set line prefix depending on the destination file type */ + + switch (FileId) + { + case ASL_FILE_ASM_SOURCE_OUTPUT: + case ASL_FILE_ASM_INCLUDE_OUTPUT: + + Prefix = "; "; + break; + + case ASL_FILE_HEX_OUTPUT: + + if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM) + { + Prefix = "; "; + } + else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) || + (Gbl_HexOutputFlag == HEX_OUTPUT_ASL)) + { + Prefix = " * "; + } + break; + + case ASL_FILE_C_SOURCE_OUTPUT: + case ASL_FILE_C_INCLUDE_OUTPUT: + + Prefix = " * "; + break; + + default: + /* No other output types supported */ + break; + } + + /* Compilation header with timestamp */ + + (void) time (&Aclock); + NewTime = localtime (&Aclock); + + FlPrintFile (FileId, + "%sCompilation of \"%s\" - %s%s\n", + Prefix, Gbl_Files[ASL_FILE_INPUT].Filename, asctime (NewTime), + Prefix); + + switch (FileId) + { + case ASL_FILE_C_SOURCE_OUTPUT: + case ASL_FILE_C_INCLUDE_OUTPUT: + FlPrintFile (FileId, " */\n"); + break; + + default: + /* Nothing to do for other output types */ + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: CmFlushSourceCode + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Read in any remaining source code after the parse tree + * has been constructed. + * + ******************************************************************************/ + +static void +CmFlushSourceCode ( + void) +{ + char Buffer; + + + while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR) + { + InsertLineBuffer ((int) Buffer); + } + + ResetCurrentLineBuffer (); +} + + +/******************************************************************************* + * + * FUNCTION: FlConsume* + * + * PARAMETERS: FileInfo - Points to an open input file + * + * RETURN: Number of lines consumed + * + * DESCRIPTION: Step over both types of comment during check for ascii chars + * + ******************************************************************************/ + +static void +FlConsumeAnsiComment ( + ASL_FILE_INFO *FileInfo, + ASL_FILE_STATUS *Status) +{ + UINT8 Byte; + BOOLEAN ClosingComment = FALSE; + + + while (fread (&Byte, 1, 1, FileInfo->Handle)) + { + /* Scan until comment close is found */ + + if (ClosingComment) + { + if (Byte == '/') + { + return; + } + + if (Byte != '*') + { + /* Reset */ + + ClosingComment = FALSE; + } + } + else if (Byte == '*') + { + ClosingComment = TRUE; + } + + /* Maintain line count */ + + if (Byte == 0x0A) + { + Status->Line++; + } + + Status->Offset++; + } +} + + +static void +FlConsumeNewComment ( + ASL_FILE_INFO *FileInfo, + ASL_FILE_STATUS *Status) +{ + UINT8 Byte; + + + while (fread (&Byte, 1, 1, FileInfo->Handle)) + { + Status->Offset++; + + /* Comment ends at newline */ + + if (Byte == 0x0A) + { + Status->Line++; + return; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: FlCheckForAscii + * + * PARAMETERS: FileInfo - Points to an open input file + * + * RETURN: Status + * + * DESCRIPTION: Verify that the input file is entirely ASCII. Ignores characters + * within comments. Note: does not handle nested comments and does + * not handle comment delimiters within string literals. However, + * on the rare chance this happens and an invalid character is + * missed, the parser will catch the error by failing in some + * spectactular manner. + * + ******************************************************************************/ + +ACPI_STATUS +FlCheckForAscii ( + ASL_FILE_INFO *FileInfo) +{ + UINT8 Byte; + ACPI_SIZE BadBytes = 0; + BOOLEAN OpeningComment = FALSE; + ASL_FILE_STATUS Status; + + + Status.Line = 1; + Status.Offset = 0; + + /* Read the entire file */ + + while (fread (&Byte, 1, 1, FileInfo->Handle)) + { + /* Ignore comment fields (allow non-ascii within) */ + + if (OpeningComment) + { + /* Check for second comment open delimiter */ + + if (Byte == '*') + { + FlConsumeAnsiComment (FileInfo, &Status); + } + + if (Byte == '/') + { + FlConsumeNewComment (FileInfo, &Status); + } + + /* Reset */ + + OpeningComment = FALSE; + } + else if (Byte == '/') + { + OpeningComment = TRUE; + } + + /* Check for an ASCII character */ + + if (!ACPI_IS_ASCII (Byte)) + { + if (BadBytes < 10) + { + AcpiOsPrintf ( + "Non-ASCII character [0x%2.2X] found in line %u, file offset 0x%.2X\n", + Byte, Status.Line, Status.Offset); + } + + BadBytes++; + } + + /* Update line counter */ + + else if (Byte == 0x0A) + { + Status.Line++; + } + + Status.Offset++; + } + + /* Seek back to the beginning of the source file */ + + fseek (FileInfo->Handle, 0, SEEK_SET); + + /* Were there any non-ASCII characters in the file? */ + + if (BadBytes) + { + AcpiOsPrintf ( + "%u non-ASCII characters found in input source text, could be a binary file\n", + BadBytes); + AslError (ASL_ERROR, ASL_MSG_NON_ASCII, NULL, FileInfo->Filename); + return (AE_BAD_CHARACTER); + } + + /* File is OK */ + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: CmDoCompile + * + * PARAMETERS: None + * + * RETURN: Status (0 = OK) + * + * DESCRIPTION: This procedure performs the entire compile + * + ******************************************************************************/ + +int +CmDoCompile ( + void) +{ + ACPI_STATUS Status; + UINT8 FullCompile; + UINT8 Event; + + + FullCompile = UtBeginEvent ("*** Total Compile time ***"); + Event = UtBeginEvent ("Open input and output files"); + UtEndEvent (Event); + + /* Build the parse tree */ + + Event = UtBeginEvent ("Parse source code and build parse tree"); + AslCompilerparse(); + UtEndEvent (Event); + + /* Flush out any remaining source after parse tree is complete */ + + Event = UtBeginEvent ("Flush source input"); + CmFlushSourceCode (); + + /* Did the parse tree get successfully constructed? */ + + if (!RootNode) + { + AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, + NULL, "- Could not resolve parse tree root node"); + CmCleanupAndExit (); + return -1; + } + + /* Optional parse tree dump, compiler debug output only */ + + LsDumpParseTree (); + + OpcGetIntegerWidth (RootNode); + UtEndEvent (Event); + + /* Pre-process parse tree for any operator transforms */ + + Event = UtBeginEvent ("Parse tree transforms"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, + TrAmlTransformWalk, NULL, NULL); + UtEndEvent (Event); + + /* Generate AML opcodes corresponding to the parse tokens */ + + Event = UtBeginEvent ("Generate AML opcodes"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, + OpcAmlOpcodeWalk, NULL); + UtEndEvent (Event); + + /* + * Now that the input is parsed, we can open the AML output file. + * Note: by default, the name of this file comes from the table descriptor + * within the input file. + */ + Event = UtBeginEvent ("Open AML output file"); + Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); + if (ACPI_FAILURE (Status)) + { + AePrintErrorLog (ASL_FILE_STDERR); + return -1; + } + UtEndEvent (Event); + + /* Interpret and generate all compile-time constants */ + + Event = UtBeginEvent ("Constant folding via AML interpreter"); + DbgPrint (ASL_DEBUG_OUTPUT, + "\nInterpreting compile-time constant expressions\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, + OpcAmlConstantWalk, NULL, NULL); + UtEndEvent (Event); + + /* Update AML opcodes if necessary, after constant folding */ + + Event = UtBeginEvent ("Updating AML opcodes after constant folding"); + DbgPrint (ASL_DEBUG_OUTPUT, + "\nUpdating AML opcodes after constant folding\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, + NULL, OpcAmlOpcodeUpdateWalk, NULL); + UtEndEvent (Event); + + /* Calculate all AML package lengths */ + + Event = UtBeginEvent ("Generate AML package lengths"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, + LnPackageLengthWalk, NULL); + UtEndEvent (Event); + + if (Gbl_ParseOnlyFlag) + { + AePrintErrorLog (ASL_FILE_STDOUT); + UtDisplaySummary (ASL_FILE_STDOUT); + if (Gbl_DebugFlag) + { + /* Print error summary to the debug file */ + + AePrintErrorLog (ASL_FILE_STDERR); + UtDisplaySummary (ASL_FILE_STDERR); + } + return 0; + } + + /* + * Create an internal namespace and use it as a symbol table + */ + + /* Namespace loading */ + + Event = UtBeginEvent ("Create ACPI Namespace"); + Status = LdLoadNamespace (RootNode); + UtEndEvent (Event); + if (ACPI_FAILURE (Status)) + { + return -1; + } + + /* Namespace cross-reference */ + + AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace"); + Status = LkCrossReferenceNamespace (); + if (ACPI_FAILURE (Status)) + { + return -1; + } + + /* Namespace - Check for non-referenced objects */ + + LkFindUnreferencedObjects (); + UtEndEvent (AslGbl_NamespaceEvent); + + /* + * Semantic analysis. This can happen only after the + * namespace has been loaded and cross-referenced. + * + * part one - check control methods + */ + Event = UtBeginEvent ("Analyze control method return types"); + AnalysisWalkInfo.MethodStack = NULL; + + DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, + AnMethodAnalysisWalkBegin, + AnMethodAnalysisWalkEnd, &AnalysisWalkInfo); + UtEndEvent (Event); + + /* Semantic error checking part two - typing of method returns */ + + Event = UtBeginEvent ("Determine object types returned by methods"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, + NULL, AnMethodTypingWalkEnd, NULL); + UtEndEvent (Event); + + /* Semantic error checking part three - operand type checking */ + + Event = UtBeginEvent ("Analyze AML operand types"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, + NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo); + UtEndEvent (Event); + + /* Semantic error checking part four - other miscellaneous checks */ + + Event = UtBeginEvent ("Miscellaneous analysis"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, + AnOtherSemanticAnalysisWalkBegin, + NULL, &AnalysisWalkInfo); + UtEndEvent (Event); + + /* Calculate all AML package lengths */ + + Event = UtBeginEvent ("Finish AML package length generation"); + DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, + LnInitLengthsWalk, NULL); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, + LnPackageLengthWalk, NULL); + UtEndEvent (Event); + + /* Code generation - emit the AML */ + + Event = UtBeginEvent ("Generate AML code and write output files"); + CgGenerateAmlOutput (); + UtEndEvent (Event); + + Event = UtBeginEvent ("Write optional output files"); + CmDoOutputFiles (); + UtEndEvent (Event); + + UtEndEvent (FullCompile); + CmCleanupAndExit (); + return 0; +} + + +/******************************************************************************* + * + * FUNCTION: CmDoOutputFiles + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create all "listing" type files + * + ******************************************************************************/ + +void +CmDoOutputFiles ( + void) +{ + + /* Create listings and hex files */ + + LsDoListings (); + LsDoHexOutput (); + + /* Dump the namespace to the .nsp file if requested */ + + (void) LsDisplayNamespace (); +} + + +/******************************************************************************* + * + * FUNCTION: CmDumpEvent + * + * PARAMETERS: Event - A compiler event struct + * + * RETURN: None. + * + * DESCRIPTION: Dump a compiler event struct + * + ******************************************************************************/ + +static void +CmDumpEvent ( + ASL_EVENT_INFO *Event) +{ + UINT32 Delta; + UINT32 USec; + UINT32 MSec; + + if (!Event->Valid) + { + return; + } + + /* Delta will be in 100-nanosecond units */ + + Delta = (UINT32) (Event->EndTime - Event->StartTime); + + USec = Delta / 10; + MSec = Delta / 10000; + + /* Round milliseconds up */ + + if ((USec - (MSec * 1000)) >= 500) + { + MSec++; + } + + DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n", + USec, MSec, Event->EventName); +} + + +/******************************************************************************* + * + * FUNCTION: CmCleanupAndExit + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Close all open files and exit the compiler + * + ******************************************************************************/ + +void +CmCleanupAndExit ( + void) +{ + UINT32 i; + + + AePrintErrorLog (ASL_FILE_STDOUT); + if (Gbl_DebugFlag) + { + /* Print error summary to the debug file */ + + AePrintErrorLog (ASL_FILE_STDERR); + } + + DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n"); + for (i = 0; i < AslGbl_NextEvent; i++) + { + CmDumpEvent (&AslGbl_Events[i]); + } + + if (Gbl_CompileTimesFlag) + { + printf ("\nElapsed time for major events\n\n"); + for (i = 0; i < AslGbl_NextEvent; i++) + { + CmDumpEvent (&AslGbl_Events[i]); + } + + printf ("\nMiscellaneous compile statistics\n\n"); + printf ("%11u : %s\n", TotalParseNodes, "Parse nodes"); + printf ("%11u : %s\n", Gbl_NsLookupCount, "Namespace searches"); + printf ("%11u : %s\n", TotalNamedObjects, "Named objects"); + printf ("%11u : %s\n", TotalMethods, "Control methods"); + printf ("%11u : %s\n", TotalAllocations, "Memory Allocations"); + printf ("%11u : %s\n", TotalAllocated, "Total allocated memory"); + printf ("%11u : %s\n", TotalFolds, "Constant subtrees folded"); + printf ("\n"); + } + + if (Gbl_NsLookupCount) + { + DbgPrint (ASL_DEBUG_OUTPUT, + "\n\nMiscellaneous compile statistics\n\n"); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%32s : %u\n", "Total Namespace searches", + Gbl_NsLookupCount); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%32s : %u usec\n", "Time per search", ((UINT32) + (AslGbl_Events[AslGbl_NamespaceEvent].EndTime - + AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) / + Gbl_NsLookupCount); + } + + if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) + { + printf ("\nMaximum error count (%u) exceeded\n", + ASL_MAX_ERROR_COUNT); + } + + UtDisplaySummary (ASL_FILE_STDOUT); + + /* Close all open files */ + + for (i = 2; i < ASL_MAX_FILE_TYPE; i++) + { + FlCloseFile (i); + } + + /* Delete AML file if there are errors */ + + if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors) && + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle) + { + if (remove (Gbl_Files[ASL_FILE_AML_OUTPUT].Filename)) + { + printf ("%s: ", + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename); + perror ("Could not delete AML file"); + } + } + + /* + * Delete intermediate ("combined") source file (if -ls flag not set) + * This file is created during normal ASL/AML compiles. It is not + * created by the data table compiler. + * + * If the -ls flag is set, then the .SRC file should not be deleted. + * In this case, Gbl_SourceOutputFlag is set to TRUE. + * + * Note: Handles are cleared by FlCloseFile above, so we look at the + * filename instead, to determine if the .SRC file was actually + * created. + * + * TBD: SourceOutput should be .TMP, then rename if we want to keep it? + */ + if (!Gbl_SourceOutputFlag && Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename) + { + if (remove (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename)) + { + printf ("%s: ", + Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); + perror ("Could not delete SRC file"); + } + } +} + + diff --git a/source/compiler/aslcompiler.h b/source/compiler/aslcompiler.h new file mode 100644 index 000000000000..aa69c702bba4 --- /dev/null +++ b/source/compiler/aslcompiler.h @@ -0,0 +1,1091 @@ + +/****************************************************************************** + * + * Module Name: aslcompiler.h - common include file for iASL + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ASLCOMPILER_H +#define __ASLCOMPILER_H + +#include "acpi.h" +#include "accommon.h" +#include "amlresrc.h" +#include "acdebug.h" + +/* Microsoft-specific */ + +#if (defined WIN32 || defined WIN64) + +/* warn : used #pragma pack */ +#pragma warning(disable:4103) + +/* warn : named type definition in parentheses */ +#pragma warning(disable:4115) +#endif + +#include +#include +#include +#include +#include +#include + +/* Compiler headers */ + +#include "asldefine.h" +#include "asltypes.h" +#include "aslmessages.h" +#include "aslglobal.h" + + +/******************************************************************************* + * + * Compiler prototypes + * + ******************************************************************************/ + +/* + * parser - generated from flex/bison, lex/yacc, etc. + */ +int +AslCompilerparse( + void); + +ACPI_PARSE_OBJECT * +AslDoError ( + void); + +int +AslCompilerlex( + void); + +void +ResetCurrentLineBuffer ( + void); + +void +InsertLineBuffer ( + int SourceChar); + +int +AslPopInputFileStack ( + void); + +void +AslPushInputFileStack ( + FILE *InputFile, + char *Filename); + +/* + * aslstartup - entered from main() + */ +void +AslInitializeGlobals ( + void); + +typedef +ACPI_STATUS (*ASL_PATHNAME_CALLBACK) ( + char *); + +ACPI_STATUS +AslDoOnePathname ( + char *Pathname, + ASL_PATHNAME_CALLBACK Callback); + +ACPI_STATUS +AslDoOneFile ( + char *Filename); + +/* + * aslcompile - compile mainline + */ +void +AslCompilerSignon ( + UINT32 FileId); + +void +AslCompilerFileHeader ( + UINT32 FileId); + +int +CmDoCompile ( + void); + +void +CmDoOutputFiles ( + void); + +void +CmCleanupAndExit ( + void); + +ACPI_STATUS +FlCheckForAscii ( + ASL_FILE_INFO *FileInfo); + + +/* + * aslwalks - semantic analysis and parse tree walks + */ +ACPI_STATUS +AnOtherSemanticAnalysisWalkBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +AnOtherSemanticAnalysisWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +AnOperandTypecheckWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +AnMethodAnalysisWalkBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +AnMethodAnalysisWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +AnMethodTypingWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/* + * aslbtypes - bitfield data types + */ +UINT32 +AnMapObjTypeToBtype ( + ACPI_PARSE_OBJECT *Op); + +UINT32 +AnMapArgTypeToBtype ( + UINT32 ArgType); + +UINT32 +AnGetBtype ( + ACPI_PARSE_OBJECT *Op); + +void +AnFormatBtype ( + char *Buffer, + UINT32 Btype); + + +/* + * aslanalyze - Support functions for parse tree walks + */ +void +AnCheckId ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAME Type); + +/* Values for Type argument above */ + +#define ASL_TYPE_HID 0 +#define ASL_TYPE_CID 1 + +BOOLEAN +AnIsInternalMethod ( + ACPI_PARSE_OBJECT *Op); + +UINT32 +AnGetInternalMethodReturnType ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AnLastStatementIsReturn ( + ACPI_PARSE_OBJECT *Op); + +void +AnCheckMethodReturnValue ( + ACPI_PARSE_OBJECT *Op, + const ACPI_OPCODE_INFO *OpInfo, + ACPI_PARSE_OBJECT *ArgOp, + UINT32 RequiredBtypes, + UINT32 ThisNodeBtype); + +BOOLEAN +AnIsResultUsed ( + ACPI_PARSE_OBJECT *Op); + +void +ApCheckForGpeNameConflict ( + ACPI_PARSE_OBJECT *Op); + +void +ApCheckRegMethod ( + ACPI_PARSE_OBJECT *Op); + + +/* + * aslerror - error handling/reporting + */ +void +AslError ( + UINT8 Level, + UINT8 MessageId, + ACPI_PARSE_OBJECT *Op, + char *ExtraMessage); + +void +AslCoreSubsystemError ( + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status, + char *ExtraMessage, + BOOLEAN Abort); + +int +AslCompilererror( + const char *s); + +void +AslCommonError ( + UINT8 Level, + UINT8 MessageId, + UINT32 CurrentLineNumber, + UINT32 LogicalLineNumber, + UINT32 LogicalByteOffset, + UINT32 Column, + char *Filename, + char *ExtraMessage); + +void +AePrintException ( + UINT32 FileId, + ASL_ERROR_MSG *Enode, + char *Header); + +void +AePrintErrorLog ( + UINT32 FileId); + +void +AeClearErrorLog ( + void); + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + + +/* + * asllisting - generate all "listing" type files + */ +void +LsDoListings ( + void); + +void +LsWriteNodeToAsmListing ( + ACPI_PARSE_OBJECT *Op); + +void +LsWriteNode ( + ACPI_PARSE_OBJECT *Op, + UINT32 FileId); + +void +LsDoHexOutput ( + void); + +void +LsDumpParseTree ( + void); + +/* + * aslfold - constant folding + */ +ACPI_STATUS +OpcAmlConstantWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/* + * aslopcodes - generate AML opcodes + */ +ACPI_STATUS +OpcAmlOpcodeWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +OpcAmlOpcodeUpdateWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +void +OpcGenerateAmlOpcode ( + ACPI_PARSE_OBJECT *Op); + +UINT32 +OpcSetOptimalIntegerSize ( + ACPI_PARSE_OBJECT *Op); + +void +OpcGetIntegerWidth ( + ACPI_PARSE_OBJECT *Op); + + +/* + * asloperands - generate AML operands for the AML opcodes + */ +ACPI_PARSE_OBJECT * +UtGetArg ( + ACPI_PARSE_OBJECT *Op, + UINT32 Argn); + +void +OpnGenerateAmlOperands ( + ACPI_PARSE_OBJECT *Op); + +void +OpnDoPackage ( + ACPI_PARSE_OBJECT *Op); + + +/* + * aslopt - optmization + */ +void +OptOptimizeNamePath ( + ACPI_PARSE_OBJECT *Op, + UINT32 Flags, + ACPI_WALK_STATE *WalkState, + char *AmlNameString, + ACPI_NAMESPACE_NODE *TargetNode); + + +/* + * aslcodegen - code generation + */ +void +CgGenerateAmlOutput ( + void); + + +/* + * aslfile + */ +void +FlOpenFile ( + UINT32 FileId, + char *Filename, + char *Mode); + + +/* + * asllength - calculate/adjust AML package lengths + */ +ACPI_STATUS +LnPackageLengthWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +ACPI_STATUS +LnInitLengthsWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +void +CgGenerateAmlLengths ( + ACPI_PARSE_OBJECT *Op); + + +/* + * aslmap - opcode mappings and reserved method names + */ +ACPI_OBJECT_TYPE +AslMapNamedOpcodeToDataType ( + UINT16 Opcode); + + +/* + * aslpredef - ACPI predefined names support + */ +BOOLEAN +ApCheckForPredefinedMethod ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo); + +void +ApCheckPredefinedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo); + +UINT32 +ApCheckForPredefinedName ( + ACPI_PARSE_OBJECT *Op, + char *Name); + +void +ApCheckForPredefinedObject ( + ACPI_PARSE_OBJECT *Op, + char *Name); + +void +ApDisplayReservedNames ( + void); + + +/* + * asltransform - parse tree transformations + */ +ACPI_STATUS +TrAmlTransformWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/* + * asltree - parse tree support + */ +ACPI_STATUS +TrWalkParseTree ( + ACPI_PARSE_OBJECT *Op, + UINT32 Visitation, + ASL_WALK_CALLBACK DescendingCallback, + ASL_WALK_CALLBACK AscendingCallback, + void *Context); + +/* Values for "Visitation" parameter above */ + +#define ASL_WALK_VISIT_DOWNWARD 0x01 +#define ASL_WALK_VISIT_UPWARD 0x02 +#define ASL_WALK_VISIT_TWICE (ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_UPWARD) + + +ACPI_PARSE_OBJECT * +TrAllocateNode ( + UINT32 ParseOpcode); + +void +TrReleaseNode ( + ACPI_PARSE_OBJECT *Op); + +ACPI_PARSE_OBJECT * +TrUpdateNode ( + UINT32 ParseOpcode, + ACPI_PARSE_OBJECT *Op); + +ACPI_PARSE_OBJECT * +TrCreateNode ( + UINT32 ParseOpcode, + UINT32 NumChildren, + ...); + +ACPI_PARSE_OBJECT * +TrCreateLeafNode ( + UINT32 ParseOpcode); + +ACPI_PARSE_OBJECT * +TrCreateValuedLeafNode ( + UINT32 ParseOpcode, + UINT64 Value); + +ACPI_PARSE_OBJECT * +TrCreateConstantLeafNode ( + UINT32 ParseOpcode); + +ACPI_PARSE_OBJECT * +TrLinkChildren ( + ACPI_PARSE_OBJECT *Op, + UINT32 NumChildren, + ...); + +void +TrSetEndLineNumber ( + ACPI_PARSE_OBJECT *Op); + +void +TrWalkTree ( + void); + +ACPI_PARSE_OBJECT * +TrLinkPeerNode ( + ACPI_PARSE_OBJECT *Op1, + ACPI_PARSE_OBJECT *Op2); + +ACPI_PARSE_OBJECT * +TrLinkChildNode ( + ACPI_PARSE_OBJECT *Op1, + ACPI_PARSE_OBJECT *Op2); + +ACPI_PARSE_OBJECT * +TrSetNodeFlags ( + ACPI_PARSE_OBJECT *Op, + UINT32 Flags); + +ACPI_PARSE_OBJECT * +TrLinkPeerNodes ( + UINT32 NumPeers, + ...); + + +/* + * aslfiles - File I/O support + */ +void +AslAbort ( + void); + +void +FlAddIncludeDirectory ( + char *Dir); + +void +FlOpenIncludeFile ( + ACPI_PARSE_OBJECT *Op); + +void +FlFileError ( + UINT32 FileId, + UINT8 ErrorId); + +UINT32 +FlGetFileSize ( + UINT32 FileId); + +ACPI_STATUS +FlReadFile ( + UINT32 FileId, + void *Buffer, + UINT32 Length); + +void +FlWriteFile ( + UINT32 FileId, + void *Buffer, + UINT32 Length); + +void +FlSeekFile ( + UINT32 FileId, + long Offset); + +void +FlCloseFile ( + UINT32 FileId); + +void +FlPrintFile ( + UINT32 FileId, + char *Format, + ...); + +void +FlSetLineNumber ( + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +FlOpenInputFile ( + char *InputFilename); + +ACPI_STATUS +FlOpenAmlOutputFile ( + char *InputFilename); + +ACPI_STATUS +FlOpenMiscOutputFiles ( + char *InputFilename); + + +/* + * asload - load namespace in prep for cross reference + */ +ACPI_STATUS +LdLoadNamespace ( + ACPI_PARSE_OBJECT *RootOp); + + +/* + * asllookup - namespace cross reference + */ +ACPI_STATUS +LkCrossReferenceNamespace ( + void); + +void +LkFindUnreferencedObjects ( + void); + +ACPI_STATUS +LsDisplayNamespace ( + void); + +void +LsSetupNsList ( + void *Handle); + + +/* + * aslutils - common compiler utilites + */ +void +DbgPrint ( + UINT32 Type, + char *Format, + ...); + +/* Type values for above */ + +#define ASL_DEBUG_OUTPUT 0 +#define ASL_PARSE_OUTPUT 1 +#define ASL_TREE_OUTPUT 2 + +void +UtDisplaySupportedTables ( + void); + +void +UtDisplayConstantOpcodes ( + void); + +UINT8 +UtBeginEvent ( + char *Name); + +void +UtEndEvent ( + UINT8 Event); + +void * +UtLocalCalloc ( + UINT32 Size); + +void +UtPrintFormattedName ( + UINT16 ParseOpcode, + UINT32 Level); + +void +UtDisplaySummary ( + UINT32 FileId); + +UINT8 +UtHexCharToValue ( + int HexChar); + +void +UtConvertByteToHex ( + UINT8 RawByte, + UINT8 *Buffer); + +void +UtConvertByteToAsmHex ( + UINT8 RawByte, + UINT8 *Buffer); + +char * +UtGetOpName ( + UINT32 ParseOpcode); + +void +UtSetParseOpName ( + ACPI_PARSE_OBJECT *Op); + +char * +UtGetStringBuffer ( + UINT32 Length); + +ACPI_STATUS +UtInternalizeName ( + char *ExternalName, + char **ConvertedName); + +void +UtAttachNamepathToOwner ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *NameNode); + +ACPI_PARSE_OBJECT * +UtCheckIntegerRange ( + ACPI_PARSE_OBJECT *Op, + UINT32 LowValue, + UINT32 HighValue); + +UINT64 +UtDoConstant ( + char *String); + +ACPI_STATUS +UtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger); + + +/* + * asluuid - UUID support + */ +ACPI_STATUS +AuValidateUuid ( + char *InString); + +ACPI_STATUS +AuConvertStringToUuid ( + char *InString, + char *UuIdBuffer); + +ACPI_STATUS +AuConvertUuidToString ( + char *UuIdBuffer, + char *OutString); + +/* + * aslresource - Resource template generation utilities + */ +void +RsSmallAddressCheck ( + UINT8 Type, + UINT32 Minimum, + UINT32 Maximum, + UINT32 Length, + UINT32 Alignment, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *AlignOp, + ACPI_PARSE_OBJECT *Op); + +void +RsLargeAddressCheck ( + UINT64 Minimum, + UINT64 Maximum, + UINT64 Length, + UINT64 Granularity, + UINT8 Flags, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *GranOp, + ACPI_PARSE_OBJECT *Op); + +UINT16 +RsGetStringDataLength ( + ACPI_PARSE_OBJECT *InitializerOp); + +ASL_RESOURCE_NODE * +RsAllocateResourceNode ( + UINT32 Size); + +void +RsCreateResourceField ( + ACPI_PARSE_OBJECT *Op, + char *Name, + UINT32 ByteOffset, + UINT32 BitOffset, + UINT32 BitLength); + +void +RsSetFlagBits ( + UINT8 *Flags, + ACPI_PARSE_OBJECT *Op, + UINT8 Position, + UINT8 DefaultBit); + +void +RsSetFlagBits16 ( + UINT16 *Flags, + ACPI_PARSE_OBJECT *Op, + UINT8 Position, + UINT8 DefaultBit); + +ACPI_PARSE_OBJECT * +RsCompleteNodeAndGetNext ( + ACPI_PARSE_OBJECT *Op); + +void +RsCheckListForDuplicates ( + ACPI_PARSE_OBJECT *Op); + +ASL_RESOURCE_NODE * +RsDoOneResourceDescriptor ( + ACPI_PARSE_OBJECT *DescriptorTypeOp, + UINT32 CurrentByteOffset, + UINT8 *State); + +/* Values for State above */ + +#define ACPI_RSTATE_NORMAL 0 +#define ACPI_RSTATE_START_DEPENDENT 1 +#define ACPI_RSTATE_DEPENDENT_LIST 2 + +UINT32 +RsLinkDescriptorChain ( + ASL_RESOURCE_NODE **PreviousRnode, + ASL_RESOURCE_NODE *Rnode); + +void +RsDoResourceTemplate ( + ACPI_PARSE_OBJECT *Op); + + +/* + * aslrestype1 - Miscellaneous Small descriptors + */ +ASL_RESOURCE_NODE * +RsDoEndTagDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoEndDependentDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoMemory24Descriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoMemory32Descriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoMemory32FixedDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoStartDependentDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoStartDependentNoPriDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoVendorSmallDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype1i - I/O-related Small descriptors + */ +ASL_RESOURCE_NODE * +RsDoDmaDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoFixedDmaDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoFixedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoIrqDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoIrqNoFlagsDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype2 - Large resource descriptors + */ +ASL_RESOURCE_NODE * +RsDoInterruptDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoVendorLargeDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoGeneralRegisterDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoGpioIntDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoGpioIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoI2cSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoSpiSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoUartSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +/* + * aslrestype2d - DWord address descriptors + */ +ASL_RESOURCE_NODE * +RsDoDwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoDwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoDwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype2e - Extended address descriptors + */ +ASL_RESOURCE_NODE * +RsDoExtendedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoExtendedMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoExtendedSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype2q - QWord address descriptors + */ +ASL_RESOURCE_NODE * +RsDoQwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoQwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoQwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype2w - Word address descriptors + */ +ASL_RESOURCE_NODE * +RsDoWordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoWordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoWordBusNumberDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +/* + * Entry to data table compiler subsystem + */ +ACPI_STATUS +DtDoCompile( + void); + +ACPI_STATUS +DtCreateTemplates ( + char *Signature); + +#endif /* __ASLCOMPILER_H */ + diff --git a/source/compiler/aslcompiler.l b/source/compiler/aslcompiler.l new file mode 100644 index 000000000000..39f94bfafb3a --- /dev/null +++ b/source/compiler/aslcompiler.l @@ -0,0 +1,1301 @@ +%{ +/****************************************************************************** + * + * Module Name: aslcompiler.l - Flex/lex input file + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#include +#include +YYSTYPE AslCompilerlval; + +/* + * Generation: Use the following command line: + * + * flex.exe -PAslCompiler -i -o$(InputPath).c $(InputPath) + * + * -i: Scanner must be case-insensitive + */ + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslscan") + +/* Local prototypes */ + +char +comment (void); +char +comment2 (void); +void +count (int type); +char +literal (void); +void +copy (void); + +/*! [Begin] no source code translation */ + +%} + /* Definitions */ + +LeadNameChar [A-Za-z_] +DigitChar [0-9] +HexDigitChar [A-Fa-f0-9] +RootChar [\\] +Nothing [] + +NameChar [A-Za-z_0-9] +NameSeg1 {LeadNameChar}{NameChar} +NameSeg2 {LeadNameChar}{NameChar}{NameChar} +NameSeg3 {LeadNameChar}{NameChar}{NameChar}{NameChar} +NameSeg {LeadNameChar}|{NameSeg1}|{NameSeg2}|{NameSeg3} + +NameString {RootChar}|{RootChar}{NamePath}|[\^]+{NamePath}|{NonEmptyNamePath} +NamePath {NonEmptyNamePath}? +NonEmptyNamePath {NameSeg}{NamePathTail}* +NamePathTail [.]{NameSeg} + +%% + /* Rules */ + +[ ] { count (0); } +[\n] { count (0); } /* Handle files with both LF and CR/LF */ +[\r] { count (0); } /* termination on both Unix and Windows */ +[ \t] { count (0); } + + +"/*" { if (!comment ()) yyterminate (); } +"//" { if (!comment2 ()) yyterminate (); } + +"\"" { if (literal ()) return (PARSEOP_STRING_LITERAL); else yyterminate (); } +";" { count (0); return(';'); } + + +0[xX]{HexDigitChar}+ | +{DigitChar}+ { AslCompilerlval.i = UtDoConstant ((char *) AslCompilertext); + count (1); return (PARSEOP_INTEGER); } + +"Include" { count (1); return (PARSEOP_INCLUDE); } +"#include" { count (1); return (PARSEOP_INCLUDE_CSTYLE); } +"#line" { count (1); return (PARSEOP_LINE_CSTYLE); } +"External" { count (1); return (PARSEOP_EXTERNAL); } + + /**************************************************************************** + * + * Main ASL operators + * + ****************************************************************************/ + +"AccessAs" { count (1); return (PARSEOP_ACCESSAS); } +"Acquire" { count (3); return (PARSEOP_ACQUIRE); } +"Add" { count (3); return (PARSEOP_ADD); } +"Alias" { count (2); return (PARSEOP_ALIAS); } +"And" { count (3); return (PARSEOP_AND); } +"BankField" { count (2); return (PARSEOP_BANKFIELD); } +"Break" { count (3); return (PARSEOP_BREAK); } +"BreakPoint" { count (3); return (PARSEOP_BREAKPOINT); } +"Buffer" { count (1); return (PARSEOP_BUFFER); } +"Case" { count (3); return (PARSEOP_CASE); } +"Concatenate" { count (3); return (PARSEOP_CONCATENATE); } +"ConcatenateResTemplate" { count (3); return (PARSEOP_CONCATENATERESTEMPLATE); } +"CondRefOf" { count (3); return (PARSEOP_CONDREFOF); } +"Connection" { count (2); return (PARSEOP_CONNECTION); } +"Continue" { count (3); return (PARSEOP_CONTINUE); } +"CopyObject" { count (3); return (PARSEOP_COPYOBJECT); } +"CreateBitField" { count (2); return (PARSEOP_CREATEBITFIELD); } +"CreateByteField" { count (2); return (PARSEOP_CREATEBYTEFIELD); } +"CreateDWordField" { count (2); return (PARSEOP_CREATEDWORDFIELD); } +"CreateField" { count (2); return (PARSEOP_CREATEFIELD); } +"CreateQWordField" { count (2); return (PARSEOP_CREATEQWORDFIELD); } +"CreateWordField" { count (2); return (PARSEOP_CREATEWORDFIELD); } +"DataTableRegion" { count (2); return (PARSEOP_DATATABLEREGION); } +"Debug" { count (1); return (PARSEOP_DEBUG); } +"Decrement" { count (3); return (PARSEOP_DECREMENT); } +"Default" { count (3); return (PARSEOP_DEFAULT); } +"DefinitionBlock" { count (1); return (PARSEOP_DEFINITIONBLOCK); } +"DeRefOf" { count (3); return (PARSEOP_DEREFOF); } +"Device" { count (2); return (PARSEOP_DEVICE); } +"Divide" { count (3); return (PARSEOP_DIVIDE); } +"Eisaid" { count (1); return (PARSEOP_EISAID); } +"Else" { count (3); return (PARSEOP_ELSE); } +"ElseIf" { count (3); return (PARSEOP_ELSEIF); } +"Event" { count (2); return (PARSEOP_EVENT); } +"Fatal" { count (3); return (PARSEOP_FATAL); } +"Field" { count (2); return (PARSEOP_FIELD); } +"FindSetLeftBit" { count (3); return (PARSEOP_FINDSETLEFTBIT); } +"FindSetRightBit" { count (3); return (PARSEOP_FINDSETRIGHTBIT); } +"FromBcd" { count (3); return (PARSEOP_FROMBCD); } +"Function" { count (2); return (PARSEOP_FUNCTION); } +"If" { count (3); return (PARSEOP_IF); } +"Increment" { count (3); return (PARSEOP_INCREMENT); } +"Index" { count (3); return (PARSEOP_INDEX); } +"IndexField" { count (2); return (PARSEOP_INDEXFIELD); } +"LAnd" { count (3); return (PARSEOP_LAND); } +"LEqual" { count (3); return (PARSEOP_LEQUAL); } +"LGreater" { count (3); return (PARSEOP_LGREATER); } +"LGreaterEqual" { count (3); return (PARSEOP_LGREATEREQUAL); } +"LLess" { count (3); return (PARSEOP_LLESS); } +"LLessEqual" { count (3); return (PARSEOP_LLESSEQUAL); } +"LNot" { count (3); return (PARSEOP_LNOT); } +"LNotEqual" { count (3); return (PARSEOP_LNOTEQUAL); } +"Load" { count (3); return (PARSEOP_LOAD); } +"LoadTable" { count (3); return (PARSEOP_LOADTABLE); } +"LOr" { count (3); return (PARSEOP_LOR); } +"Match" { count (3); return (PARSEOP_MATCH); } +"Method" { count (2); return (PARSEOP_METHOD); } +"Mid" { count (3); return (PARSEOP_MID); } +"Mod" { count (3); return (PARSEOP_MOD); } +"Multiply" { count (3); return (PARSEOP_MULTIPLY); } +"Mutex" { count (2); return (PARSEOP_MUTEX); } +"Name" { count (2); return (PARSEOP_NAME); } +"NAnd" { count (3); return (PARSEOP_NAND); } +"Noop" { count (3); return (PARSEOP_NOOP); } +"NOr" { count (3); return (PARSEOP_NOR); } +"Not" { count (3); return (PARSEOP_NOT); } +"Notify" { count (3); return (PARSEOP_NOTIFY); } +"ObjectType" { count (3); return (PARSEOP_OBJECTTYPE); } +"Offset" { count (1); return (PARSEOP_OFFSET); } +"One" { count (1); return (PARSEOP_ONE); } +"Ones" { count (1); return (PARSEOP_ONES); } +"OperationRegion" { count (2); return (PARSEOP_OPERATIONREGION); } +"Or" { count (3); return (PARSEOP_OR); } +"Package" { count (1); return (PARSEOP_PACKAGE); } +"PowerResource" { count (2); return (PARSEOP_POWERRESOURCE); } +"Processor" { count (2); return (PARSEOP_PROCESSOR); } +"RefOf" { count (3); return (PARSEOP_REFOF); } +"Release" { count (3); return (PARSEOP_RELEASE); } +"Reset" { count (3); return (PARSEOP_RESET); } +"Return" { count (3); return (PARSEOP_RETURN); } +"Revision" { count (1); return (PARSEOP_REVISION); } +"Scope" { count (2); return (PARSEOP_SCOPE); } +"ShiftLeft" { count (3); return (PARSEOP_SHIFTLEFT); } +"ShiftRight" { count (3); return (PARSEOP_SHIFTRIGHT); } +"Signal" { count (3); return (PARSEOP_SIGNAL); } +"SizeOf" { count (3); return (PARSEOP_SIZEOF); } +"Sleep" { count (3); return (PARSEOP_SLEEP); } +"Stall" { count (3); return (PARSEOP_STALL); } +"Store" { count (3); return (PARSEOP_STORE); } +"Subtract" { count (3); return (PARSEOP_SUBTRACT); } +"Switch" { count (3); return (PARSEOP_SWITCH); } +"ThermalZone" { count (2); return (PARSEOP_THERMALZONE); } +"Timer" { count (3); return (PARSEOP_TIMER); } +"ToBcd" { count (3); return (PARSEOP_TOBCD); } +"ToBuffer" { count (3); return (PARSEOP_TOBUFFER); } +"ToDecimalString" { count (3); return (PARSEOP_TODECIMALSTRING); } +"ToHexString" { count (3); return (PARSEOP_TOHEXSTRING); } +"ToInteger" { count (3); return (PARSEOP_TOINTEGER); } +"ToString" { count (3); return (PARSEOP_TOSTRING); } +"ToUuid" { count (1); return (PARSEOP_TOUUID); } +"Unicode" { count (1); return (PARSEOP_UNICODE); } +"Unload" { count (3); return (PARSEOP_UNLOAD); } +"Wait" { count (3); return (PARSEOP_WAIT); } +"While" { count (3); return (PARSEOP_WHILE); } +"XOr" { count (3); return (PARSEOP_XOR); } +"Zero" { count (1); return (PARSEOP_ZERO); } + + /* Control method arguments and locals */ + +"Arg0" { count (1); return (PARSEOP_ARG0); } +"Arg1" { count (1); return (PARSEOP_ARG1); } +"Arg2" { count (1); return (PARSEOP_ARG2); } +"Arg3" { count (1); return (PARSEOP_ARG3); } +"Arg4" { count (1); return (PARSEOP_ARG4); } +"Arg5" { count (1); return (PARSEOP_ARG5); } +"Arg6" { count (1); return (PARSEOP_ARG6); } +"Local0" { count (1); return (PARSEOP_LOCAL0); } +"Local1" { count (1); return (PARSEOP_LOCAL1); } +"Local2" { count (1); return (PARSEOP_LOCAL2); } +"Local3" { count (1); return (PARSEOP_LOCAL3); } +"Local4" { count (1); return (PARSEOP_LOCAL4); } +"Local5" { count (1); return (PARSEOP_LOCAL5); } +"Local6" { count (1); return (PARSEOP_LOCAL6); } +"Local7" { count (1); return (PARSEOP_LOCAL7); } + + + /**************************************************************************** + * + * Resource Descriptor macros + * + ****************************************************************************/ + +"ResourceTemplate" { count (1); return (PARSEOP_RESOURCETEMPLATE); } +"RawDataBuffer" { count (1); return (PARSEOP_DATABUFFER); } + +"DMA" { count (1); return (PARSEOP_DMA); } +"DWordIO" { count (1); return (PARSEOP_DWORDIO); } +"DWordMemory" { count (1); return (PARSEOP_DWORDMEMORY); } +"DWordSpace" { count (1); return (PARSEOP_DWORDSPACE); } +"EndDependentFn" { count (1); return (PARSEOP_ENDDEPENDENTFN); } +"ExtendedIO" { count (1); return (PARSEOP_EXTENDEDIO); } +"ExtendedMemory" { count (1); return (PARSEOP_EXTENDEDMEMORY); } +"ExtendedSpace" { count (1); return (PARSEOP_EXTENDEDSPACE); } +"FixedDma" { count (1); return (PARSEOP_FIXEDDMA); } +"FixedIO" { count (1); return (PARSEOP_FIXEDIO); } +"GpioInt" { count (1); return (PARSEOP_GPIO_INT); } +"GpioIo" { count (1); return (PARSEOP_GPIO_IO); } +"I2cSerialBus" { count (1); return (PARSEOP_I2C_SERIALBUS); } +"Interrupt" { count (1); return (PARSEOP_INTERRUPT); } +"IO" { count (1); return (PARSEOP_IO); } +"IRQ" { count (1); return (PARSEOP_IRQ); } +"IRQNoFlags" { count (1); return (PARSEOP_IRQNOFLAGS); } +"Memory24" { count (1); return (PARSEOP_MEMORY24); } +"Memory32" { count (1); return (PARSEOP_MEMORY32); } +"Memory32Fixed" { count (1); return (PARSEOP_MEMORY32FIXED); } +"QWordIO" { count (1); return (PARSEOP_QWORDIO); } +"QWordMemory" { count (1); return (PARSEOP_QWORDMEMORY); } +"QWordSpace" { count (1); return (PARSEOP_QWORDSPACE); } +"Register" { count (1); return (PARSEOP_REGISTER); } +"SpiSerialBus" { count (1); return (PARSEOP_SPI_SERIALBUS); } +"StartDependentFn" { count (1); return (PARSEOP_STARTDEPENDENTFN); } +"StartDependentFnNoPri" { count (1); return (PARSEOP_STARTDEPENDENTFN_NOPRI); } +"UartSerialBus" { count (1); return (PARSEOP_UART_SERIALBUS); } +"VendorLong" { count (1); return (PARSEOP_VENDORLONG); } +"VendorShort" { count (1); return (PARSEOP_VENDORSHORT); } +"WordBusNumber" { count (1); return (PARSEOP_WORDBUSNUMBER); } +"WordIO" { count (1); return (PARSEOP_WORDIO); } +"WordSpace" { count (1); return (PARSEOP_WORDSPACE); } + + + /**************************************************************************** + * + * Keywords used as arguments to ASL operators and macros + * + ****************************************************************************/ + + /* AccessAttribKeyword: Serial Bus Attributes (ACPI 5.0) */ + +"AttribQuick" { count (0); return (PARSEOP_ACCESSATTRIB_QUICK); } +"AttribSendReceive" { count (0); return (PARSEOP_ACCESSATTRIB_SND_RCV); } +"AttribByte" { count (0); return (PARSEOP_ACCESSATTRIB_BYTE); } +"AttribWord" { count (0); return (PARSEOP_ACCESSATTRIB_WORD); } +"AttribBlock" { count (0); return (PARSEOP_ACCESSATTRIB_BLOCK); } +"AttribProcessCall" { count (0); return (PARSEOP_ACCESSATTRIB_WORD_CALL); } +"AttribBlockProcessCall" { count (0); return (PARSEOP_ACCESSATTRIB_BLOCK_CALL); } + + /* AccessAttribKeyword: Legacy synonyms for above (pre-ACPI 5.0) */ + +"SMBQuick" { count (0); return (PARSEOP_ACCESSATTRIB_QUICK); } +"SMBSendReceive" { count (0); return (PARSEOP_ACCESSATTRIB_SND_RCV); } +"SMBByte" { count (0); return (PARSEOP_ACCESSATTRIB_BYTE); } +"SMBWord" { count (0); return (PARSEOP_ACCESSATTRIB_WORD); } +"SMBBlock" { count (0); return (PARSEOP_ACCESSATTRIB_BLOCK); } +"SMBProcessCall" { count (0); return (PARSEOP_ACCESSATTRIB_WORD_CALL); } +"SMBBlockProcessCall" { count (0); return (PARSEOP_ACCESSATTRIB_BLOCK_CALL); } + + /* AccessTypeKeyword: Field Access Types */ + +"AnyAcc" { count (0); return (PARSEOP_ACCESSTYPE_ANY); } +"ByteAcc" { count (0); return (PARSEOP_ACCESSTYPE_BYTE); } +"WordAcc" { count (0); return (PARSEOP_ACCESSTYPE_WORD); } +"DWordAcc" { count (0); return (PARSEOP_ACCESSTYPE_DWORD); } +"QWordAcc" { count (0); return (PARSEOP_ACCESSTYPE_QWORD); } +"BufferAcc" { count (0); return (PARSEOP_ACCESSTYPE_BUF); } + + /* AddressingModeKeyword: Mode - Resource Descriptors (ACPI 5.0) */ + +"AddressingMode7Bit" { count (0); return (PARSEOP_ADDRESSINGMODE_7BIT); } +"AddressingMode10Bit" { count (0); return (PARSEOP_ADDRESSINGMODE_10BIT); } + + /* AddressKeyword: ACPI memory range types */ + +"AddressRangeMemory" { count (0); return (PARSEOP_ADDRESSTYPE_MEMORY); } +"AddressRangeReserved" { count (0); return (PARSEOP_ADDRESSTYPE_RESERVED); } +"AddressRangeNVS" { count (0); return (PARSEOP_ADDRESSTYPE_NVS); } +"AddressRangeACPI" { count (0); return (PARSEOP_ADDRESSTYPE_ACPI); } + + /* BusMasterKeyword: DMA Bus Mastering */ + +"BusMaster" { count (0); return (PARSEOP_BUSMASTERTYPE_MASTER); } +"NotBusMaster" { count (0); return (PARSEOP_BUSMASTERTYPE_NOTMASTER); } + + /* ByteLengthKeyword: Bits per Byte - Resource Descriptors (ACPI 5.0) */ + +"DataBitsFive" { count (0); return (PARSEOP_BITSPERBYTE_FIVE); } +"DataBitsSix" { count (0); return (PARSEOP_BITSPERBYTE_SIX); } +"DataBitsSeven" { count (0); return (PARSEOP_BITSPERBYTE_SEVEN); } +"DataBitsEight" { count (0); return (PARSEOP_BITSPERBYTE_EIGHT); } +"DataBitsNine" { count (0); return (PARSEOP_BITSPERBYTE_NINE); } + + /* ClockPhaseKeyword: Resource Descriptors (ACPI 5.0) */ + +"ClockPhaseFirst" { count (0); return (PARSEOP_CLOCKPHASE_FIRST); } +"ClockPhaseSecond" { count (0); return (PARSEOP_CLOCKPHASE_SECOND); } + + /* ClockPolarityKeyword: Resource Descriptors (ACPI 5.0) */ + +"ClockPolarityLow" { count (0); return (PARSEOP_CLOCKPOLARITY_LOW); } +"ClockPolarityHigh" { count (0); return (PARSEOP_CLOCKPOLARITY_HIGH); } + + /* DecodeKeyword: Type of Memory Decoding - Resource Descriptors */ + +"PosDecode" { count (0); return (PARSEOP_DECODETYPE_POS); } +"SubDecode" { count (0); return (PARSEOP_DECODETYPE_SUB); } + + /* DmaTypeKeyword: DMA Types - DMA Resource Descriptor */ + +"Compatibility" { count (0); return (PARSEOP_DMATYPE_COMPATIBILITY); } +"TypeA" { count (0); return (PARSEOP_DMATYPE_A); } +"TypeB" { count (0); return (PARSEOP_DMATYPE_B); } +"TypeF" { count (0); return (PARSEOP_DMATYPE_F); } + + /* EndianKeyword: Endian type - Resource Descriptor (ACPI 5.0) */ + +"LittleEndian" { count (0); return (PARSEOP_ENDIAN_LITTLE); } +"BigEndian" { count (0); return (PARSEOP_ENDIAN_BIG); } + + /* ExtendedAttribKeyword: Bus attributes, AccessAs operator (ACPI 5.0) */ + +"AttribBytes" { count (0); return (PARSEOP_ACCESSATTRIB_MULTIBYTE); } +"AttribRawBytes" { count (0); return (PARSEOP_ACCESSATTRIB_RAW_BYTES); } +"AttribRawProcessBytes" { count (0); return (PARSEOP_ACCESSATTRIB_RAW_PROCESS); } + + /* FlowControlKeyword: Resource Descriptors (ACPI 5.0) */ + +"FlowControlHardware" { count (0); return (PARSEOP_FLOWCONTROL_HW); } +"FlowControlNone" { count (0); return (PARSEOP_FLOWCONTROL_NONE); } +"FlowControlXon" { count (0); return (PARSEOP_FLOWCONTROL_SW); } + + /* InterruptLevelKeyword: Interrupt Active Types */ + +"ActiveBoth" { count (0); return (PARSEOP_INTLEVEL_ACTIVEBOTH); } +"ActiveHigh" { count (0); return (PARSEOP_INTLEVEL_ACTIVEHIGH); } +"ActiveLow" { count (0); return (PARSEOP_INTLEVEL_ACTIVELOW); } + + /* InterruptTypeKeyword: Interrupt Types */ + +"Edge" { count (0); return (PARSEOP_INTTYPE_EDGE); } +"Level" { count (0); return (PARSEOP_INTTYPE_LEVEL); } + + /* IoDecodeKeyword: Type of Memory Decoding - Resource Descriptors */ + +"Decode10" { count (0); return (PARSEOP_IODECODETYPE_10); } +"Decode16" { count (0); return (PARSEOP_IODECODETYPE_16); } + + /* IoRestrictionKeyword: I/O Restriction - GPIO Resource Descriptors (ACPI 5.0) */ + +"IoRestrictionNone" { count (0); return (PARSEOP_IORESTRICT_NONE); } +"IoRestrictionInputOnly" { count (0); return (PARSEOP_IORESTRICT_IN); } +"IoRestrictionOutputOnly" { count (0); return (PARSEOP_IORESTRICT_OUT); } +"IoRestrictionNoneAndPreserve" { count (0); return (PARSEOP_IORESTRICT_PRESERVE); } + + /* LockRuleKeyword: Global Lock use for Field Operator */ + +"Lock" { count (0); return (PARSEOP_LOCKRULE_LOCK); } +"NoLock" { count (0); return (PARSEOP_LOCKRULE_NOLOCK); } + + /* MatchOpKeyword: Types for Match Operator */ + +"MTR" { count (0); return (PARSEOP_MATCHTYPE_MTR); } +"MEQ" { count (0); return (PARSEOP_MATCHTYPE_MEQ); } +"MLE" { count (0); return (PARSEOP_MATCHTYPE_MLE); } +"MLT" { count (0); return (PARSEOP_MATCHTYPE_MLT); } +"MGE" { count (0); return (PARSEOP_MATCHTYPE_MGE); } +"MGT" { count (0); return (PARSEOP_MATCHTYPE_MGT); } + + /* MaxKeyword: Max Range Type - Resource Descriptors */ + +"MaxFixed" { count (0); return (PARSEOP_MAXTYPE_FIXED); } +"MaxNotFixed" { count (0); return (PARSEOP_MAXTYPE_NOTFIXED); } + + /* MemTypeKeyword: Memory Types - Resource Descriptors */ + +"Cacheable" { count (0); return (PARSEOP_MEMTYPE_CACHEABLE); } +"WriteCombining" { count (0); return (PARSEOP_MEMTYPE_WRITECOMBINING); } +"Prefetchable" { count (0); return (PARSEOP_MEMTYPE_PREFETCHABLE); } +"NonCacheable" { count (0); return (PARSEOP_MEMTYPE_NONCACHEABLE); } + + /* MinKeyword: Min Range Type - Resource Descriptors */ + +"MinFixed" { count (0); return (PARSEOP_MINTYPE_FIXED); } +"MinNotFixed" { count (0); return (PARSEOP_MINTYPE_NOTFIXED); } + + /* ObjectTypeKeyword: ACPI Object Types */ + +"UnknownObj" { count (0); return (PARSEOP_OBJECTTYPE_UNK); } +"IntObj" { count (0); return (PARSEOP_OBJECTTYPE_INT); } +"StrObj" { count (0); return (PARSEOP_OBJECTTYPE_STR); } +"BuffObj" { count (0); return (PARSEOP_OBJECTTYPE_BUF); } +"PkgObj" { count (0); return (PARSEOP_OBJECTTYPE_PKG); } +"FieldUnitObj" { count (0); return (PARSEOP_OBJECTTYPE_FLD); } +"DeviceObj" { count (0); return (PARSEOP_OBJECTTYPE_DEV); } +"EventObj" { count (0); return (PARSEOP_OBJECTTYPE_EVT); } +"MethodObj" { count (0); return (PARSEOP_OBJECTTYPE_MTH); } +"MutexObj" { count (0); return (PARSEOP_OBJECTTYPE_MTX); } +"OpRegionObj" { count (0); return (PARSEOP_OBJECTTYPE_OPR); } +"PowerResObj" { count (0); return (PARSEOP_OBJECTTYPE_POW); } +"ProcessorObj" { count (0); return (PARSEOP_OBJECTTYPE_PRO); } +"ThermalZoneObj" { count (0); return (PARSEOP_OBJECTTYPE_THZ); } +"BuffFieldObj" { count (0); return (PARSEOP_OBJECTTYPE_BFF); } +"DDBHandleObj" { count (0); return (PARSEOP_OBJECTTYPE_DDB); } + + /* ParityKeyword: Resource Descriptors (ACPI 5.0) */ + +"ParityTypeSpace" { count (0); return (PARSEOP_PARITYTYPE_SPACE); } +"ParityTypeMark" { count (0); return (PARSEOP_PARITYTYPE_MARK); } +"ParityTypeOdd" { count (0); return (PARSEOP_PARITYTYPE_ODD); } +"ParityTypeEven" { count (0); return (PARSEOP_PARITYTYPE_EVEN); } +"ParityTypeNone" { count (0); return (PARSEOP_PARITYTYPE_NONE); } + + /* PinConfigKeyword: Pin Configuration - GPIO Resource Descriptors (ACPI 5.0) */ + +"PullDefault" { count (0); return (PARSEOP_PIN_PULLDEFAULT); } +"PullUp" { count (0); return (PARSEOP_PIN_PULLUP); } +"PullDown" { count (0); return (PARSEOP_PIN_PULLDOWN); } +"PullNone" { count (0); return (PARSEOP_PIN_NOPULL); } + + /* PolarityKeyword: Resource Descriptors (ACPI 5.0) */ + +"PolarityLow" { count (0); return (PARSEOP_DEVICEPOLARITY_LOW); } +"PolarityHigh" { count (0); return (PARSEOP_DEVICEPOLARITY_HIGH); } + + /* RangeTypeKeyword: I/O Range Types - Resource Descriptors */ + +"ISAOnlyRanges" { count (0); return (PARSEOP_RANGETYPE_ISAONLY); } +"NonISAOnlyRanges" { count (0); return (PARSEOP_RANGETYPE_NONISAONLY); } +"EntireRange" { count (0); return (PARSEOP_RANGETYPE_ENTIRE); } + + /* ReadWriteKeyword: Memory Access Types - Resource Descriptors */ + +"ReadWrite" { count (0); return (PARSEOP_READWRITETYPE_BOTH); } +"ReadOnly" { count (0); return (PARSEOP_READWRITETYPE_READONLY); } + + /* RegionSpaceKeyword: Operation Region Address Space Types */ + +"SystemIO" { count (0); return (PARSEOP_REGIONSPACE_IO); } +"SystemMemory" { count (0); return (PARSEOP_REGIONSPACE_MEM); } +"PCI_Config" { count (0); return (PARSEOP_REGIONSPACE_PCI); } +"EmbeddedControl" { count (0); return (PARSEOP_REGIONSPACE_EC); } +"SMBus" { count (0); return (PARSEOP_REGIONSPACE_SMBUS); } +"SystemCMOS" { count (0); return (PARSEOP_REGIONSPACE_CMOS); } +"PciBarTarget" { count (0); return (PARSEOP_REGIONSPACE_PCIBAR); } +"IPMI" { count (0); return (PARSEOP_REGIONSPACE_IPMI); } +"GeneralPurposeIo" { count (0); return (PARSEOP_REGIONSPACE_GPIO); } /* ACPI 5.0 */ +"GenericSerialBus" { count (0); return (PARSEOP_REGIONSPACE_GSBUS); } /* ACPI 5.0 */ +"FFixedHW" { count (0); return (PARSEOP_REGIONSPACE_FFIXEDHW); } + + /* ResourceTypeKeyword: Resource Usage - Resource Descriptors */ + +"ResourceConsumer" { count (0); return (PARSEOP_RESOURCETYPE_CONSUMER); } +"ResourceProducer" { count (0); return (PARSEOP_RESOURCETYPE_PRODUCER); } + + /* SerializeRuleKeyword: Control Method Serialization */ + +"Serialized" { count (0); return (PARSEOP_SERIALIZERULE_SERIAL); } +"NotSerialized" { count (0); return (PARSEOP_SERIALIZERULE_NOTSERIAL); } + + /* ShareTypeKeyword: Interrupt Sharing - Resource Descriptors */ + +"Shared" { count (0); return (PARSEOP_SHARETYPE_SHARED); } +"Exclusive" { count (0); return (PARSEOP_SHARETYPE_EXCLUSIVE); } +"SharedAndWake" { count (0); return (PARSEOP_SHARETYPE_SHAREDWAKE); } /* ACPI 5.0 */ +"ExclusiveAndWake" { count (0); return (PARSEOP_SHARETYPE_EXCLUSIVEWAKE); } /* ACPI 5.0 */ + + /* SlaveModeKeyword: Resource Descriptors (ACPI 5.0) */ + +"ControllerInitiated" { count (0); return (PARSEOP_SLAVEMODE_CONTROLLERINIT); } +"DeviceInitiated" { count (0); return (PARSEOP_SLAVEMODE_DEVICEINIT); } + + /* StopBitsKeyword: Resource Descriptors (ACPI 5.0) */ + +"StopBitsOne" { count (0); return (PARSEOP_STOPBITS_ONE); } +"StopBitsOnePlusHalf" { count (0); return (PARSEOP_STOPBITS_ONEPLUSHALF); } +"StopBitsTwo" { count (0); return (PARSEOP_STOPBITS_TWO); } +"StopBitsZero" { count (0); return (PARSEOP_STOPBITS_ZERO); } + + /* TransferWidthKeyword: DMA Widths - Fixed DMA Resource Descriptor (ACPI 5.0) */ + +"Width8bit" { count (0); return (PARSEOP_XFERSIZE_8); } +"Width16bit" { count (0); return (PARSEOP_XFERSIZE_16); } +"Width32bit" { count (0); return (PARSEOP_XFERSIZE_32); } +"Width64bit" { count (0); return (PARSEOP_XFERSIZE_64); } +"Width128bit" { count (0); return (PARSEOP_XFERSIZE_128); } +"Width256bit" { count (0); return (PARSEOP_XFERSIZE_256); } + + /* TranslationKeyword: Translation Density Types - Resource Descriptors */ + +"SparseTranslation" { count (0); return (PARSEOP_TRANSLATIONTYPE_SPARSE); } +"DenseTranslation" { count (0); return (PARSEOP_TRANSLATIONTYPE_DENSE); } + + /* TypeKeyword: Translation Types - Resource Descriptors */ + +"TypeTranslation" { count (0); return (PARSEOP_TYPE_TRANSLATION); } +"TypeStatic" { count (0); return (PARSEOP_TYPE_STATIC); } + + /* UpdateRuleKeyword: Field Update Rules */ + +"Preserve" { count (0); return (PARSEOP_UPDATERULE_PRESERVE); } +"WriteAsOnes" { count (0); return (PARSEOP_UPDATERULE_ONES); } +"WriteAsZeros" { count (0); return (PARSEOP_UPDATERULE_ZEROS); } + + /* WireModeKeyword: SPI Wire Mode - Resource Descriptors (ACPI 5.0) */ + +"FourWireMode" { count (0); return (PARSEOP_WIREMODE_FOUR); } +"ThreeWireMode" { count (0); return (PARSEOP_WIREMODE_THREE); } + + /* XferTypeKeyword: DMA Transfer Types */ + +"Transfer8" { count (0); return (PARSEOP_XFERTYPE_8); } +"Transfer8_16" { count (0); return (PARSEOP_XFERTYPE_8_16); } +"Transfer16" { count (0); return (PARSEOP_XFERTYPE_16); } + + /* Predefined compiler names */ + +"__DATE__" { count (0); return (PARSEOP___DATE__); } +"__FILE__" { count (0); return (PARSEOP___FILE__); } +"__LINE__" { count (0); return (PARSEOP___LINE__); } +"__PATH__" { count (0); return (PARSEOP___PATH__); } + + +"{" { count (0); return('{'); } +"}" { count (0); return('}'); } +"," { count (0); return(','); } +"(" { count (0); return('('); } +")" { count (0); return(')'); } + +{NameSeg} { char *s; + count (0); + s=malloc (ACPI_NAME_SIZE + 1); + if (strcmp (AslCompilertext, "\\")) + { + strcpy (s, "____"); + AcpiUtStrupr (AslCompilertext); + } + memcpy (s, AslCompilertext, strlen (AslCompilertext)); + AslCompilerlval.s = s; + DbgPrint (ASL_PARSE_OUTPUT, "NameSeg: %s\n", s); + return (PARSEOP_NAMESEG); } + +{NameString} { char *s; + count (0); + s=malloc (strlen (AslCompilertext)+1); + AcpiUtStrupr (AslCompilertext); + strcpy (s, AslCompilertext); + s[strlen (AslCompilertext)] = 0; + AslCompilerlval.s = s; + DbgPrint (ASL_PARSE_OUTPUT, "NameString: %s\n", s); + return (PARSEOP_NAMESTRING); } + +"*" | +"/" { count (1); + AslCompilererror ("Parse error, expecting ASL keyword or name");} + +. { count (1); + sprintf (MsgBuffer, + "Invalid character (0x%2.2X), expecting ASL keyword or name", + *AslCompilertext); + AslCompilererror (MsgBuffer);} + +<> { if (AslPopInputFileStack ()) + yyterminate(); + else + return (PARSEOP_INCLUDE_END);}; + +%% + +/*! [End] no source code translation !*/ + +typedef struct asl_file_node +{ + FILE *File; + UINT32 CurrentLineNumber; + YY_BUFFER_STATE State; + char *Filename; + struct asl_file_node *Next; + +} ASL_FILE_NODE; + +ASL_FILE_NODE *InputStack = NULL; + + +/******************************************************************************* + * + * FUNCTION: AslPopInputFileStack + * + * PARAMETERS: None + * + * RETURN: 0 if a node was popped, -1 otherwise + * + * DESCRIPTION: Pop the top of the input file stack and point the parser to + * the saved parse buffer contained in the fnode. Also, set the + * global line counters to the saved values. This function is + * called when an include file reaches EOF. + * + ******************************************************************************/ + +int +AslPopInputFileStack ( + void) +{ + ASL_FILE_NODE *Fnode; + + + Fnode = InputStack; + DbgPrint (ASL_PARSE_OUTPUT, "\nPop InputFile Stack, Fnode %p\n\n", Fnode); + + + if (!Fnode) + { + return -1; + } + + /* Close the current include file */ + + fclose (yyin); + + /* Update the top-of-stack */ + + InputStack = Fnode->Next; + + /* Reset global line counter and filename */ + + Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename; + Gbl_CurrentLineNumber = Fnode->CurrentLineNumber; + + /* Point the parser to the popped file */ + + yy_delete_buffer (YY_CURRENT_BUFFER); + yy_switch_to_buffer (Fnode->State); + + /* All done with this node */ + + ACPI_FREE (Fnode); + return 0; +} + + +/******************************************************************************* + * + * FUNCTION: AslPushInputFileStack + * + * PARAMETERS: InputFile - Open file pointer + * Filename - Name of the file + * + * RETURN: None + * + * DESCRIPTION: Push the InputFile onto the file stack, and point the parser + * to this file. Called when an include file is successfully + * opened. + * + ******************************************************************************/ + +void +AslPushInputFileStack ( + FILE *InputFile, + char *Filename) +{ + ASL_FILE_NODE *Fnode; + YY_BUFFER_STATE State; + + + /* Save the current state in an Fnode */ + + Fnode = UtLocalCalloc (sizeof (ASL_FILE_NODE)); + + Fnode->File = yyin; + Fnode->Next = InputStack; + Fnode->State = YY_CURRENT_BUFFER; + Fnode->CurrentLineNumber = Gbl_CurrentLineNumber; + Fnode->Filename = Gbl_Files[ASL_FILE_INPUT].Filename; + + /* Push it on the stack */ + + InputStack = Fnode; + + /* Point the parser to this file */ + + State = yy_create_buffer (InputFile, YY_BUF_SIZE); + yy_switch_to_buffer (State); + + DbgPrint (ASL_PARSE_OUTPUT, "\nPush InputFile Stack, returning %p\n\n", InputFile); + + /* Reset the global line count and filename */ + + Gbl_Files[ASL_FILE_INPUT].Filename = Filename; + Gbl_CurrentLineNumber = 1; + yyin = InputFile; +} + + +/******************************************************************************* + * + * FUNCTION: ResetCurrentLineBuffer + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers. + * + ******************************************************************************/ + +void +ResetCurrentLineBuffer ( + void) +{ + + if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle) + { + FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer, + Gbl_LineBufPtr - Gbl_CurrentLineBuffer); + } + + Gbl_CurrentLineOffset += Gbl_CurrentColumn; + Gbl_CurrentColumn = 0; + + Gbl_CurrentLineNumber++; + Gbl_LogicalLineNumber++; + Gbl_LineBufPtr = Gbl_CurrentLineBuffer; +} + + +/******************************************************************************* + * + * FUNCTION: InsertLineBuffer + * + * PARAMETERS: SourceChar - One char from the input ASL source file + * + * RETURN: None + * + * DESCRIPTION: Put one character of the source file into the temp line buffer + * + ******************************************************************************/ + +#define ASL_SPACES_PER_TAB 4 + +void +InsertLineBuffer ( + int SourceChar) +{ + UINT32 i; + UINT32 Count = 1; + + + if (SourceChar == EOF) + { + return; + } + + Gbl_InputByteCount++; + + /* Handle tabs. Convert to spaces */ + + if (SourceChar == '\t') + { + SourceChar = ' '; + Count = ASL_SPACES_PER_TAB - + (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1)); + } + + + for (i = 0; i < Count; i++) + { + Gbl_CurrentColumn++; + + /* Insert the character into the line buffer */ + + *Gbl_LineBufPtr = (UINT8) SourceChar; + Gbl_LineBufPtr++; + + if (Gbl_LineBufPtr > (Gbl_CurrentLineBuffer + (ASL_LINE_BUFFER_SIZE - 1))) + { +#if 0 + /* + * Warning if we have split a long source line. + * + */ + sprintf (MsgBuffer, "Max %u", ASL_LINE_BUFFER_SIZE); + AslCommonError (ASL_WARNING, ASL_MSG_LONG_LINE, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, MsgBuffer); +#endif + + ResetCurrentLineBuffer (); + } + else if (SourceChar == '\n') + { + /* End of line */ + + ResetCurrentLineBuffer (); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: count + * + * PARAMETERS: yytext - Contains the matched keyword. + * Type - Keyword/Character type: + * 0 = anything except a keyword + * 1 = pseudo-keywords + * 2 = non-executable ASL keywords + * 3 = executable ASL keywords + * + * RETURN: None + * + * DESCRIPTION: Count keywords and put them into the line buffer + * + ******************************************************************************/ + +void +count ( + int Type) +{ + int i; + + + switch (Type) + { + case 2: + TotalKeywords++; + TotalNamedObjects++; + break; + + case 3: + TotalKeywords++; + TotalExecutableOpcodes++; + break; + } + + for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++) + { + InsertLineBuffer (yytext[i]); + *Gbl_LineBufPtr = 0; + } +} + + +/******************************************************************************* + * + * FUNCTION: comment + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Process a standard comment. + * + ******************************************************************************/ + +char +comment (void) +{ + char c; + char c1 = 0; + + + InsertLineBuffer ('/'); + InsertLineBuffer ('*'); + +loop: + + /* Eat chars until end-of-comment */ + + while ((c = (char) input()) != '*' && c != EOF) + { + InsertLineBuffer (c); + c1 = c; + } + + if (c == EOF) + { + goto EarlyEOF; + } + + /* + * Check for nested comment -- can help catch cases where a previous + * comment was accidently left unterminated + */ + if ((c1 == '/') && (c == '*')) + { + AslCommonError (ASL_WARNING, ASL_MSG_NESTED_COMMENT, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_InputByteCount, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + } + + /* Comment is closed only if the NEXT character is a slash */ + + InsertLineBuffer (c); + + if ((c1 = (char) input()) != '/' && c1 != EOF) + { + unput(c1); + goto loop; + } + + if (c1 == EOF) + { + goto EarlyEOF; + } + + InsertLineBuffer (c1); + return TRUE; + + +EarlyEOF: + /* + * Premature End-Of-File + */ + AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: comment + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Process a new "//" comment. + * + ******************************************************************************/ + +char +comment2 (void) +{ + char c; + + + InsertLineBuffer ('/'); + InsertLineBuffer ('/'); + + while ((c = (char) input()) != '\n' && c != EOF) + { + InsertLineBuffer (c); + } + + if (c == EOF) + { + /* End of file is OK, change to newline. Let parser detect EOF later */ + + c = '\n'; + } + + InsertLineBuffer (c); + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: literal + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Process a string literal (surrounded by quotes) + * + ******************************************************************************/ + +#define ASL_NORMAL_CHAR 0 +#define ASL_ESCAPE_SEQUENCE 1 +#define ASL_OCTAL_CONSTANT 2 +#define ASL_HEX_CONSTANT 3 + +char +literal (void) +{ + char *StringBuffer = MsgBuffer; + char *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE; + char *CleanString; + char StringChar; + UINT32 State = ASL_NORMAL_CHAR; + UINT32 i = 0; + UINT8 Digit; + char ConvertBuffer[4]; + + + /* + * Eat chars until end-of-literal. + * NOTE: Put back the original surrounding quotes into the + * source line buffer. + */ + InsertLineBuffer ('\"'); + while ((StringChar = (char) input()) != EOF) + { + InsertLineBuffer (StringChar); + +DoCharacter: + + switch (State) + { + case ASL_NORMAL_CHAR: + + switch (StringChar) + { + case '\\': + /* + * Special handling for backslash-escape sequence. We will + * toss the backslash and translate the escape char(s). + */ + State = ASL_ESCAPE_SEQUENCE; + continue; + + case '\"': + + /* String terminator */ + + goto CompletedString; + } + break; + + + case ASL_ESCAPE_SEQUENCE: + + State = ASL_NORMAL_CHAR; + switch (StringChar) + { + case 'a': + StringChar = 0x07; /* BELL */ + break; + + case 'b': + StringChar = 0x08; /* BACKSPACE */ + break; + + case 'f': + StringChar = 0x0C; /* FORMFEED */ + break; + + case 'n': + StringChar = 0x0A; /* LINEFEED */ + break; + + case 'r': + StringChar = 0x0D; /* CARRIAGE RETURN*/ + break; + + case 't': + StringChar = 0x09; /* HORIZONTAL TAB */ + break; + + case 'v': + StringChar = 0x0B; /* VERTICAL TAB */ + break; + + case 'x': + State = ASL_HEX_CONSTANT; + i = 0; + continue; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + break; + + default: + + /* Check for an octal digit (0-7) */ + + if (ACPI_IS_OCTAL_DIGIT (StringChar)) + { + State = ASL_OCTAL_CONSTANT; + ConvertBuffer[0] = StringChar; + i = 1; + continue; + } + + /* Unknown escape sequence issue warning, but use the character */ + + AslCommonError (ASL_WARNING, ASL_MSG_INVALID_ESCAPE, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + break; + } + break; + + + case ASL_OCTAL_CONSTANT: + + /* Up to three octal digits allowed */ + + if (!ACPI_IS_OCTAL_DIGIT (StringChar) || + (i > 2)) + { + /* + * Reached end of the constant. Convert the assembled ASCII + * string and resume processing of the next character + */ + ConvertBuffer[i] = 0; + Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8); + + /* Check for NULL or non-ascii character (ignore if so) */ + + if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) + { + AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + } + else + { + *StringBuffer = (char) Digit; + StringBuffer++; + if (StringBuffer >= EndBuffer) + { + goto BufferOverflow; + } + } + + State = ASL_NORMAL_CHAR; + goto DoCharacter; + break; + } + + /* Append another digit of the constant */ + + ConvertBuffer[i] = StringChar; + i++; + continue; + + + case ASL_HEX_CONSTANT: + + /* Up to two hex digits allowed */ + + if (!ACPI_IS_XDIGIT (StringChar) || + (i > 1)) + { + /* + * Reached end of the constant. Convert the assembled ASCII + * string and resume processing of the next character + */ + ConvertBuffer[i] = 0; + Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16); + + /* Check for NULL or non-ascii character (ignore if so) */ + + if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) + { + AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + } + else + { + *StringBuffer = (char) Digit; + StringBuffer++; + if (StringBuffer >= EndBuffer) + { + goto BufferOverflow; + } + } + + State = ASL_NORMAL_CHAR; + goto DoCharacter; + break; + } + + /* Append another digit of the constant */ + + ConvertBuffer[i] = StringChar; + i++; + continue; + } + + /* Save the finished character */ + + *StringBuffer = StringChar; + StringBuffer++; + if (StringBuffer >= EndBuffer) + { + goto BufferOverflow; + } + } + + /* + * Premature End-Of-File + */ + AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + return (FALSE); + + +CompletedString: + /* + * Null terminate the input string and copy string to a new buffer + */ + *StringBuffer = 0; + + CleanString = UtGetStringBuffer (strlen (MsgBuffer) + 1); + if (!CleanString) + { + AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + return (FALSE); + } + + ACPI_STRCPY (CleanString, MsgBuffer); + AslCompilerlval.s = CleanString; + return (TRUE); + + +BufferOverflow: + + /* Literal was too long */ + + AslCommonError (ASL_ERROR, ASL_MSG_STRING_LENGTH, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_CurrentLineOffset, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, "Max length 4096"); + return (FALSE); +} + + diff --git a/source/compiler/aslcompiler.y b/source/compiler/aslcompiler.y new file mode 100644 index 000000000000..c2cb0a5dd1ac --- /dev/null +++ b/source/compiler/aslcompiler.y @@ -0,0 +1,3571 @@ +%{ +/****************************************************************************** + * + * Module Name: aslcompiler.y - Bison/Yacc input file (ASL grammar and actions) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include +#include +#include +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslparse") + +/* + * Global Notes: + * + * October 2005: The following list terms have been optimized (from the + * original ASL grammar in the ACPI specification) to force the immediate + * reduction of each list item so that the parse stack use doesn't increase on + * each list element and possibly overflow on very large lists (>4000 items). + * This dramatically reduces use of the parse stack overall. + * + * ArgList, TermList, Objectlist, ByteList, DWordList, PackageList, + * ResourceMacroList, and FieldUnitList + */ + +void * AslLocalAllocate (unsigned int Size); + +/* Bison/yacc configuration */ + +#define static +#undef alloca +#define alloca AslLocalAllocate +#define yytname AslCompilername + +#define YYINITDEPTH 600 /* State stack depth */ +#define YYDEBUG 1 /* Enable debug output */ +#define YYERROR_VERBOSE 1 /* Verbose error messages */ + +/* + * The windows version of bison defines this incorrectly as "32768" (Not negative). + * We use a custom (edited binary) version of bison that defines YYFLAG as YYFBAD + * instead (#define YYFBAD 32768), so we can define it correctly here. + * + * The problem is that if YYFLAG is positive, the extended syntax error messages + * are disabled. + */ +#define YYFLAG -32768 + +%} + +/* + * Declare the type of values in the grammar + */ +%union { + UINT64 i; + char *s; + ACPI_PARSE_OBJECT *n; +} + +/*! [Begin] no source code translation */ + +/* + * These shift/reduce conflicts are expected. There should be zero + * reduce/reduce conflicts. + */ +%expect 86 + +/****************************************************************************** + * + * Token types: These are returned by the lexer + * + * NOTE: This list MUST match the AslKeywordMapping table found + * in aslmap.c EXACTLY! Double check any changes! + * + *****************************************************************************/ + +%token PARSEOP_ACCESSAS +%token PARSEOP_ACCESSATTRIB_BLOCK +%token PARSEOP_ACCESSATTRIB_BLOCK_CALL +%token PARSEOP_ACCESSATTRIB_BYTE +%token PARSEOP_ACCESSATTRIB_MULTIBYTE +%token PARSEOP_ACCESSATTRIB_QUICK +%token PARSEOP_ACCESSATTRIB_RAW_BYTES +%token PARSEOP_ACCESSATTRIB_RAW_PROCESS +%token PARSEOP_ACCESSATTRIB_SND_RCV +%token PARSEOP_ACCESSATTRIB_WORD +%token PARSEOP_ACCESSATTRIB_WORD_CALL +%token PARSEOP_ACCESSTYPE_ANY +%token PARSEOP_ACCESSTYPE_BUF +%token PARSEOP_ACCESSTYPE_BYTE +%token PARSEOP_ACCESSTYPE_DWORD +%token PARSEOP_ACCESSTYPE_QWORD +%token PARSEOP_ACCESSTYPE_WORD +%token PARSEOP_ACQUIRE +%token PARSEOP_ADD +%token PARSEOP_ADDRESSINGMODE_7BIT +%token PARSEOP_ADDRESSINGMODE_10BIT +%token PARSEOP_ADDRESSTYPE_ACPI +%token PARSEOP_ADDRESSTYPE_MEMORY +%token PARSEOP_ADDRESSTYPE_NVS +%token PARSEOP_ADDRESSTYPE_RESERVED +%token PARSEOP_ALIAS +%token PARSEOP_AND +%token PARSEOP_ARG0 +%token PARSEOP_ARG1 +%token PARSEOP_ARG2 +%token PARSEOP_ARG3 +%token PARSEOP_ARG4 +%token PARSEOP_ARG5 +%token PARSEOP_ARG6 +%token PARSEOP_BANKFIELD +%token PARSEOP_BITSPERBYTE_EIGHT +%token PARSEOP_BITSPERBYTE_FIVE +%token PARSEOP_BITSPERBYTE_NINE +%token PARSEOP_BITSPERBYTE_SEVEN +%token PARSEOP_BITSPERBYTE_SIX +%token PARSEOP_BREAK +%token PARSEOP_BREAKPOINT +%token PARSEOP_BUFFER +%token PARSEOP_BUSMASTERTYPE_MASTER +%token PARSEOP_BUSMASTERTYPE_NOTMASTER +%token PARSEOP_BYTECONST +%token PARSEOP_CASE +%token PARSEOP_CLOCKPHASE_FIRST +%token PARSEOP_CLOCKPHASE_SECOND +%token PARSEOP_CLOCKPOLARITY_HIGH +%token PARSEOP_CLOCKPOLARITY_LOW +%token PARSEOP_CONCATENATE +%token PARSEOP_CONCATENATERESTEMPLATE +%token PARSEOP_CONDREFOF +%token PARSEOP_CONNECTION +%token PARSEOP_CONTINUE +%token PARSEOP_COPYOBJECT +%token PARSEOP_CREATEBITFIELD +%token PARSEOP_CREATEBYTEFIELD +%token PARSEOP_CREATEDWORDFIELD +%token PARSEOP_CREATEFIELD +%token PARSEOP_CREATEQWORDFIELD +%token PARSEOP_CREATEWORDFIELD +%token PARSEOP_DATABUFFER +%token PARSEOP_DATATABLEREGION +%token PARSEOP_DEBUG +%token PARSEOP_DECODETYPE_POS +%token PARSEOP_DECODETYPE_SUB +%token PARSEOP_DECREMENT +%token PARSEOP_DEFAULT +%token PARSEOP_DEFAULT_ARG +%token PARSEOP_DEFINITIONBLOCK +%token PARSEOP_DEREFOF +%token PARSEOP_DEVICE +%token PARSEOP_DEVICEPOLARITY_HIGH +%token PARSEOP_DEVICEPOLARITY_LOW +%token PARSEOP_DIVIDE +%token PARSEOP_DMA +%token PARSEOP_DMATYPE_A +%token PARSEOP_DMATYPE_COMPATIBILITY +%token PARSEOP_DMATYPE_B +%token PARSEOP_DMATYPE_F +%token PARSEOP_DWORDCONST +%token PARSEOP_DWORDIO +%token PARSEOP_DWORDMEMORY +%token PARSEOP_DWORDSPACE +%token PARSEOP_EISAID +%token PARSEOP_ELSE +%token PARSEOP_ELSEIF +%token PARSEOP_ENDDEPENDENTFN +%token PARSEOP_ENDIAN_BIG +%token PARSEOP_ENDIAN_LITTLE +%token PARSEOP_ENDTAG +%token PARSEOP_ERRORNODE +%token PARSEOP_EVENT +%token PARSEOP_EXTENDEDIO +%token PARSEOP_EXTENDEDMEMORY +%token PARSEOP_EXTENDEDSPACE +%token PARSEOP_EXTERNAL +%token PARSEOP_FATAL +%token PARSEOP_FIELD +%token PARSEOP_FINDSETLEFTBIT +%token PARSEOP_FINDSETRIGHTBIT +%token PARSEOP_FIXEDDMA +%token PARSEOP_FIXEDIO +%token PARSEOP_FLOWCONTROL_HW +%token PARSEOP_FLOWCONTROL_NONE +%token PARSEOP_FLOWCONTROL_SW +%token PARSEOP_FROMBCD +%token PARSEOP_FUNCTION +%token PARSEOP_GPIO_INT +%token PARSEOP_GPIO_IO +%token PARSEOP_I2C_SERIALBUS +%token PARSEOP_IF +%token PARSEOP_INCLUDE +%token PARSEOP_INCLUDE_CSTYLE +%token PARSEOP_INCLUDE_END +%token PARSEOP_INCREMENT +%token PARSEOP_INDEX +%token PARSEOP_INDEXFIELD +%token PARSEOP_INTEGER +%token PARSEOP_INTERRUPT +%token PARSEOP_INTLEVEL_ACTIVEBOTH +%token PARSEOP_INTLEVEL_ACTIVEHIGH +%token PARSEOP_INTLEVEL_ACTIVELOW +%token PARSEOP_INTTYPE_EDGE +%token PARSEOP_INTTYPE_LEVEL +%token PARSEOP_IO +%token PARSEOP_IODECODETYPE_10 +%token PARSEOP_IODECODETYPE_16 +%token PARSEOP_IORESTRICT_IN +%token PARSEOP_IORESTRICT_NONE +%token PARSEOP_IORESTRICT_OUT +%token PARSEOP_IORESTRICT_PRESERVE +%token PARSEOP_IRQ +%token PARSEOP_IRQNOFLAGS +%token PARSEOP_LAND +%token PARSEOP_LEQUAL +%token PARSEOP_LGREATER +%token PARSEOP_LGREATEREQUAL +%token PARSEOP_LINE_CSTYLE +%token PARSEOP_LLESS +%token PARSEOP_LLESSEQUAL +%token PARSEOP_LNOT +%token PARSEOP_LNOTEQUAL +%token PARSEOP_LOAD +%token PARSEOP_LOADTABLE +%token PARSEOP_LOCAL0 +%token PARSEOP_LOCAL1 +%token PARSEOP_LOCAL2 +%token PARSEOP_LOCAL3 +%token PARSEOP_LOCAL4 +%token PARSEOP_LOCAL5 +%token PARSEOP_LOCAL6 +%token PARSEOP_LOCAL7 +%token PARSEOP_LOCKRULE_LOCK +%token PARSEOP_LOCKRULE_NOLOCK +%token PARSEOP_LOR +%token PARSEOP_MATCH +%token PARSEOP_MATCHTYPE_MEQ +%token PARSEOP_MATCHTYPE_MGE +%token PARSEOP_MATCHTYPE_MGT +%token PARSEOP_MATCHTYPE_MLE +%token PARSEOP_MATCHTYPE_MLT +%token PARSEOP_MATCHTYPE_MTR +%token PARSEOP_MAXTYPE_FIXED +%token PARSEOP_MAXTYPE_NOTFIXED +%token PARSEOP_MEMORY24 +%token PARSEOP_MEMORY32 +%token PARSEOP_MEMORY32FIXED +%token PARSEOP_MEMTYPE_CACHEABLE +%token PARSEOP_MEMTYPE_NONCACHEABLE +%token PARSEOP_MEMTYPE_PREFETCHABLE +%token PARSEOP_MEMTYPE_WRITECOMBINING +%token PARSEOP_METHOD +%token PARSEOP_METHODCALL +%token PARSEOP_MID +%token PARSEOP_MINTYPE_FIXED +%token PARSEOP_MINTYPE_NOTFIXED +%token PARSEOP_MOD +%token PARSEOP_MULTIPLY +%token PARSEOP_MUTEX +%token PARSEOP_NAME +%token PARSEOP_NAMESEG +%token PARSEOP_NAMESTRING +%token PARSEOP_NAND +%token PARSEOP_NOOP +%token PARSEOP_NOR +%token PARSEOP_NOT +%token PARSEOP_NOTIFY +%token PARSEOP_OBJECTTYPE +%token PARSEOP_OBJECTTYPE_BFF +%token PARSEOP_OBJECTTYPE_BUF +%token PARSEOP_OBJECTTYPE_DDB +%token PARSEOP_OBJECTTYPE_DEV +%token PARSEOP_OBJECTTYPE_EVT +%token PARSEOP_OBJECTTYPE_FLD +%token PARSEOP_OBJECTTYPE_INT +%token PARSEOP_OBJECTTYPE_MTH +%token PARSEOP_OBJECTTYPE_MTX +%token PARSEOP_OBJECTTYPE_OPR +%token PARSEOP_OBJECTTYPE_PKG +%token PARSEOP_OBJECTTYPE_POW +%token PARSEOP_OBJECTTYPE_PRO +%token PARSEOP_OBJECTTYPE_STR +%token PARSEOP_OBJECTTYPE_THZ +%token PARSEOP_OBJECTTYPE_UNK +%token PARSEOP_OFFSET +%token PARSEOP_ONE +%token PARSEOP_ONES +%token PARSEOP_OPERATIONREGION +%token PARSEOP_OR +%token PARSEOP_PACKAGE +%token PARSEOP_PACKAGE_LENGTH +%token PARSEOP_PARITYTYPE_EVEN +%token PARSEOP_PARITYTYPE_MARK +%token PARSEOP_PARITYTYPE_NONE +%token PARSEOP_PARITYTYPE_ODD +%token PARSEOP_PARITYTYPE_SPACE +%token PARSEOP_PIN_NOPULL +%token PARSEOP_PIN_PULLDEFAULT +%token PARSEOP_PIN_PULLDOWN +%token PARSEOP_PIN_PULLUP +%token PARSEOP_POWERRESOURCE +%token PARSEOP_PROCESSOR +%token PARSEOP_QWORDCONST +%token PARSEOP_QWORDIO +%token PARSEOP_QWORDMEMORY +%token PARSEOP_QWORDSPACE +%token PARSEOP_RANGETYPE_ENTIRE +%token PARSEOP_RANGETYPE_ISAONLY +%token PARSEOP_RANGETYPE_NONISAONLY +%token PARSEOP_RAW_DATA +%token PARSEOP_READWRITETYPE_BOTH +%token PARSEOP_READWRITETYPE_READONLY +%token PARSEOP_REFOF +%token PARSEOP_REGIONSPACE_CMOS +%token PARSEOP_REGIONSPACE_EC +%token PARSEOP_REGIONSPACE_FFIXEDHW +%token PARSEOP_REGIONSPACE_GPIO +%token PARSEOP_REGIONSPACE_GSBUS +%token PARSEOP_REGIONSPACE_IO +%token PARSEOP_REGIONSPACE_IPMI +%token PARSEOP_REGIONSPACE_MEM +%token PARSEOP_REGIONSPACE_PCI +%token PARSEOP_REGIONSPACE_PCIBAR +%token PARSEOP_REGIONSPACE_SMBUS +%token PARSEOP_REGISTER +%token PARSEOP_RELEASE +%token PARSEOP_RESERVED_BYTES +%token PARSEOP_RESET +%token PARSEOP_RESOURCETEMPLATE +%token PARSEOP_RESOURCETYPE_CONSUMER +%token PARSEOP_RESOURCETYPE_PRODUCER +%token PARSEOP_RETURN +%token PARSEOP_REVISION +%token PARSEOP_SCOPE +%token PARSEOP_SERIALIZERULE_NOTSERIAL +%token PARSEOP_SERIALIZERULE_SERIAL +%token PARSEOP_SHARETYPE_EXCLUSIVE +%token PARSEOP_SHARETYPE_EXCLUSIVEWAKE +%token PARSEOP_SHARETYPE_SHARED +%token PARSEOP_SHARETYPE_SHAREDWAKE +%token PARSEOP_SHIFTLEFT +%token PARSEOP_SHIFTRIGHT +%token PARSEOP_SIGNAL +%token PARSEOP_SIZEOF +%token PARSEOP_SLAVEMODE_CONTROLLERINIT +%token PARSEOP_SLAVEMODE_DEVICEINIT +%token PARSEOP_SLEEP +%token PARSEOP_SPI_SERIALBUS +%token PARSEOP_STALL +%token PARSEOP_STARTDEPENDENTFN +%token PARSEOP_STARTDEPENDENTFN_NOPRI +%token PARSEOP_STOPBITS_ONE +%token PARSEOP_STOPBITS_ONEPLUSHALF +%token PARSEOP_STOPBITS_TWO +%token PARSEOP_STOPBITS_ZERO +%token PARSEOP_STORE +%token PARSEOP_STRING_LITERAL +%token PARSEOP_SUBTRACT +%token PARSEOP_SWITCH +%token PARSEOP_THERMALZONE +%token PARSEOP_TIMER +%token PARSEOP_TOBCD +%token PARSEOP_TOBUFFER +%token PARSEOP_TODECIMALSTRING +%token PARSEOP_TOHEXSTRING +%token PARSEOP_TOINTEGER +%token PARSEOP_TOSTRING +%token PARSEOP_TOUUID +%token PARSEOP_TRANSLATIONTYPE_DENSE +%token PARSEOP_TRANSLATIONTYPE_SPARSE +%token PARSEOP_TYPE_STATIC +%token PARSEOP_TYPE_TRANSLATION +%token PARSEOP_UART_SERIALBUS +%token PARSEOP_UNICODE +%token PARSEOP_UNLOAD +%token PARSEOP_UPDATERULE_ONES +%token PARSEOP_UPDATERULE_PRESERVE +%token PARSEOP_UPDATERULE_ZEROS +%token PARSEOP_VAR_PACKAGE +%token PARSEOP_VENDORLONG +%token PARSEOP_VENDORSHORT +%token PARSEOP_WAIT +%token PARSEOP_WHILE +%token PARSEOP_WIREMODE_FOUR +%token PARSEOP_WIREMODE_THREE +%token PARSEOP_WORDBUSNUMBER +%token PARSEOP_WORDCONST +%token PARSEOP_WORDIO +%token PARSEOP_WORDSPACE +%token PARSEOP_XFERSIZE_8 +%token PARSEOP_XFERSIZE_16 +%token PARSEOP_XFERSIZE_32 +%token PARSEOP_XFERSIZE_64 +%token PARSEOP_XFERSIZE_128 +%token PARSEOP_XFERSIZE_256 +%token PARSEOP_XFERTYPE_8 +%token PARSEOP_XFERTYPE_8_16 +%token PARSEOP_XFERTYPE_16 +%token PARSEOP_XOR +%token PARSEOP_ZERO + +/* + * Special functions. These should probably stay at the end of this + * table. + */ +%token PARSEOP___DATE__ +%token PARSEOP___FILE__ +%token PARSEOP___LINE__ +%token PARSEOP___PATH__ + + +/****************************************************************************** + * + * Production names + * + *****************************************************************************/ + +%type ArgList +%type ASLCode +%type BufferData +%type BufferTermData +%type CompilerDirective +%type DataObject +%type DefinitionBlockTerm +%type IntegerData +%type NamedObject +%type NameSpaceModifier +%type Object +%type ObjectList +%type PackageData +%type ParameterTypePackage +%type ParameterTypePackageList +%type ParameterTypesPackage +%type ParameterTypesPackageList +%type RequiredTarget +%type SimpleTarget +%type StringData +%type Target +%type Term +%type TermArg +%type TermList +%type UserTerm + +/* Type4Opcode is obsolete */ + +%type Type1Opcode +%type Type2BufferOpcode +%type Type2BufferOrStringOpcode +%type Type2IntegerOpcode +%type Type2Opcode +%type Type2StringOpcode +%type Type3Opcode +%type Type5Opcode +%type Type6Opcode + +%type AccessAsTerm +%type ExternalTerm +%type FieldUnit +%type FieldUnitEntry +%type FieldUnitList +%type IncludeCStyleTerm +%type IncludeTerm +%type LineTerm +%type OffsetTerm +%type OptionalAccessAttribTerm + +/* Named Objects */ + +%type BankFieldTerm +%type CreateBitFieldTerm +%type CreateByteFieldTerm +%type CreateDWordFieldTerm +%type CreateFieldTerm +%type CreateQWordFieldTerm +%type CreateWordFieldTerm +%type DataRegionTerm +%type DeviceTerm +%type EventTerm +%type FieldTerm +%type FunctionTerm +%type IndexFieldTerm +%type MethodTerm +%type MutexTerm +%type OpRegionTerm +%type OpRegionSpaceIdTerm +%type PowerResTerm +%type ProcessorTerm +%type ThermalZoneTerm + +/* Namespace modifiers */ + +%type AliasTerm +%type NameTerm +%type ScopeTerm + +/* Type 1 opcodes */ + +%type BreakPointTerm +%type BreakTerm +%type CaseDefaultTermList +%type CaseTerm +%type ContinueTerm +%type DefaultTerm +%type ElseTerm +%type FatalTerm +%type IfElseTerm +%type IfTerm +%type LoadTerm +%type NoOpTerm +%type NotifyTerm +%type ReleaseTerm +%type ResetTerm +%type ReturnTerm +%type SignalTerm +%type SleepTerm +%type StallTerm +%type SwitchTerm +%type UnloadTerm +%type WhileTerm +//%type CaseTermList + +/* Type 2 opcodes */ + +%type AcquireTerm +%type AddTerm +%type AndTerm +%type ConcatResTerm +%type ConcatTerm +%type CondRefOfTerm +%type CopyObjectTerm +%type DecTerm +%type DerefOfTerm +%type DivideTerm +%type FindSetLeftBitTerm +%type FindSetRightBitTerm +%type FromBCDTerm +%type IncTerm +%type IndexTerm +%type LAndTerm +%type LEqualTerm +%type LGreaterEqualTerm +%type LGreaterTerm +%type LLessEqualTerm +%type LLessTerm +%type LNotEqualTerm +%type LNotTerm +%type LoadTableTerm +%type LOrTerm +%type MatchTerm +%type MidTerm +%type ModTerm +%type MultiplyTerm +%type NAndTerm +%type NOrTerm +%type NotTerm +%type ObjectTypeTerm +%type OrTerm +%type RefOfTerm +%type ShiftLeftTerm +%type ShiftRightTerm +%type SizeOfTerm +%type StoreTerm +%type SubtractTerm +%type TimerTerm +%type ToBCDTerm +%type ToBufferTerm +%type ToDecimalStringTerm +%type ToHexStringTerm +%type ToIntegerTerm +%type ToStringTerm +%type WaitTerm +%type XOrTerm + +/* Keywords */ + +%type AccessAttribKeyword +%type AccessTypeKeyword +%type AddressingModeKeyword +%type AddressKeyword +%type AddressSpaceKeyword +%type BitsPerByteKeyword +%type ClockPhaseKeyword +%type ClockPolarityKeyword +%type DecodeKeyword +%type DevicePolarityKeyword +%type DMATypeKeyword +%type EndianKeyword +%type FlowControlKeyword +%type InterruptLevel +%type InterruptTypeKeyword +%type IODecodeKeyword +%type IoRestrictionKeyword +%type LockRuleKeyword +%type MatchOpKeyword +%type MaxKeyword +%type MemTypeKeyword +%type MinKeyword +%type ObjectTypeKeyword +%type OptionalBusMasterKeyword +%type OptionalReadWriteKeyword +%type ParityTypeKeyword +%type PinConfigByte +%type PinConfigKeyword +%type RangeTypeKeyword +%type RegionSpaceKeyword +%type ResourceTypeKeyword +%type SerializeRuleKeyword +%type ShareTypeKeyword +%type SlaveModeKeyword +%type StopBitsKeyword +%type TranslationKeyword +%type TypeKeyword +%type UpdateRuleKeyword +%type WireModeKeyword +%type XferSizeKeyword +%type XferTypeKeyword + +/* Types */ + +%type SuperName +%type ArgTerm +%type LocalTerm +%type DebugTerm + +%type Integer +%type ByteConst +%type WordConst +%type DWordConst +%type QWordConst +%type String + +%type ConstTerm +%type ConstExprTerm +%type ByteConstExpr +%type WordConstExpr +%type DWordConstExpr +%type QWordConstExpr + +%type DWordList +%type BufferTerm +%type ByteList + +%type PackageElement +%type PackageList +%type PackageTerm +%type VarPackageLengthTerm + +/* Macros */ + +%type EISAIDTerm +%type ResourceMacroList +%type ResourceMacroTerm +%type ResourceTemplateTerm +%type ToUUIDTerm +%type UnicodeTerm + +/* Resource Descriptors */ + +%type ConnectionTerm +%type DataBufferTerm +%type DMATerm +%type DWordIOTerm +%type DWordMemoryTerm +%type DWordSpaceTerm +%type EndDependentFnTerm +%type ExtendedIOTerm +%type ExtendedMemoryTerm +%type ExtendedSpaceTerm +%type FixedDmaTerm +%type FixedIOTerm +%type GpioIntTerm +%type GpioIoTerm +%type I2cSerialBusTerm +%type InterruptTerm +%type IOTerm +%type IRQNoFlagsTerm +%type IRQTerm +%type Memory24Term +%type Memory32FixedTerm +%type Memory32Term +%type NameSeg +%type NameString +%type QWordIOTerm +%type QWordMemoryTerm +%type QWordSpaceTerm +%type RegisterTerm +%type SpiSerialBusTerm +%type StartDependentFnNoPriTerm +%type StartDependentFnTerm +%type UartSerialBusTerm +%type VendorLongTerm +%type VendorShortTerm +%type WordBusNumberTerm +%type WordIOTerm +%type WordSpaceTerm + +/* Local types that help construct the AML, not in ACPI spec */ + +%type AmlPackageLengthTerm +%type IncludeEndTerm +%type NameStringItem +%type TermArgItem + +%type OptionalAccessSize +%type OptionalAddressingMode +%type OptionalAddressRange +%type OptionalBitsPerByte +%type OptionalBuffer_Last +%type OptionalByteConstExpr +%type OptionalCount +%type OptionalDecodeType +%type OptionalDevicePolarity +%type OptionalDWordConstExpr +%type OptionalEndian +%type OptionalFlowControl +%type OptionalIoRestriction +%type OptionalListString +%type OptionalMaxType +%type OptionalMemType +%type OptionalMinType +%type OptionalNameString +%type OptionalNameString_First +%type OptionalNameString_Last +%type OptionalObjectTypeKeyword +%type OptionalParameterTypePackage +%type OptionalParameterTypesPackage +%type OptionalParityType +%type OptionalQWordConstExpr +%type OptionalRangeType +%type OptionalReference +%type OptionalResourceType +%type OptionalResourceType_First +%type OptionalReturnArg +%type OptionalSerializeRuleKeyword +%type OptionalShareType +%type OptionalShareType_First +%type OptionalSlaveMode +%type OptionalStopBits +%type OptionalStringData +%type OptionalTermArg +%type OptionalTranslationType_Last +%type OptionalType +%type OptionalType_Last +%type OptionalWireMode +%type OptionalWordConst +%type OptionalWordConstExpr +%type OptionalXferSize + +%% +/******************************************************************************* + * + * Production rules start here + * + ******************************************************************************/ + +/* + * ASL Names + */ + + +/* + * Blocks, Data, and Opcodes + */ + +ASLCode + : DefinitionBlockTerm + | error {YYABORT; $$ = NULL;} + ; + +/* + * Note concerning support for "module-level code". + * + * ACPI 1.0 allowed Type1 and Type2 executable opcodes outside of control + * methods (the so-called module-level code.) This support was explicitly + * removed in ACPI 2.0, but this type of code continues to be created by + * BIOS vendors. In order to support the disassembly and recompilation of + * such code (and the porting of ASL code to iASL), iASL supports this + * code in violation of the current ACPI specification. + * + * The grammar change to support module-level code is to revert the + * {ObjectList} portion of the DefinitionBlockTerm in ACPI 2.0 to the + * original use of {TermList} instead (see below.) This allows the use + * of Type1 and Type2 opcodes at module level. + */ +DefinitionBlockTerm + : PARSEOP_DEFINITIONBLOCK '(' {$$ = TrCreateLeafNode (PARSEOP_DEFINITIONBLOCK);} + String ',' + String ',' + ByteConst ',' + String ',' + String ',' + DWordConst + ')' {TrSetEndLineNumber ($3);} + '{' TermList '}' {$$ = TrLinkChildren ($3,7,$4,$6,$8,$10,$12,$14,$18);} + ; + +/* ACPI 3.0 -- allow semicolons between terms */ + +TermList + : {$$ = NULL;} + | TermList Term {$$ = TrLinkPeerNode (TrSetNodeFlags ($1, NODE_RESULT_NOT_USED),$2);} + | TermList Term ';' {$$ = TrLinkPeerNode (TrSetNodeFlags ($1, NODE_RESULT_NOT_USED),$2);} + | TermList ';' Term {$$ = TrLinkPeerNode (TrSetNodeFlags ($1, NODE_RESULT_NOT_USED),$3);} + | TermList ';' Term ';' {$$ = TrLinkPeerNode (TrSetNodeFlags ($1, NODE_RESULT_NOT_USED),$3);} + ; + +Term + : Object {} + | Type1Opcode {} + | Type2Opcode {} + | Type2IntegerOpcode {} + | Type2StringOpcode {} + | Type2BufferOpcode {} + | Type2BufferOrStringOpcode {} + | error {$$ = AslDoError(); yyclearin;} + ; + +CompilerDirective + : IncludeTerm {} + | IncludeCStyleTerm {$$ = NULL;} + | LineTerm {$$ = NULL;} + | ExternalTerm {} + ; + +ObjectList + : {$$ = NULL;} + | ObjectList Object {$$ = TrLinkPeerNode ($1,$2);} + | error {$$ = AslDoError(); yyclearin;} + ; + +Object + : CompilerDirective {} + | NamedObject {} + | NameSpaceModifier {} + ; + +DataObject + : BufferData {} + | PackageData {} + | IntegerData {} + | StringData {} + ; + +BufferData + : Type5Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | Type2BufferOrStringOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | Type2BufferOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | BufferTerm {} + ; + +PackageData + : PackageTerm {} + ; + +IntegerData + : Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | Type3Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | Integer {} + | ConstTerm {} + ; + +StringData + : Type2StringOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST);} + | String {} + ; + +NamedObject + : BankFieldTerm {} + | CreateBitFieldTerm {} + | CreateByteFieldTerm {} + | CreateDWordFieldTerm {} + | CreateFieldTerm {} + | CreateQWordFieldTerm {} + | CreateWordFieldTerm {} + | DataRegionTerm {} + | DeviceTerm {} + | EventTerm {} + | FieldTerm {} + | FunctionTerm {} + | IndexFieldTerm {} + | MethodTerm {} + | MutexTerm {} + | OpRegionTerm {} + | PowerResTerm {} + | ProcessorTerm {} + | ThermalZoneTerm {} + ; + +NameSpaceModifier + : AliasTerm {} + | NameTerm {} + | ScopeTerm {} + ; + +UserTerm + : NameString '(' {TrUpdateNode (PARSEOP_METHODCALL, $1);} + ArgList ')' {$$ = TrLinkChildNode ($1,$4);} + ; + +ArgList + : {$$ = NULL;} + | TermArg + | ArgList ',' /* Allows a trailing comma at list end */ + | ArgList ',' + TermArg {$$ = TrLinkPeerNode ($1,$3);} + ; + +/* +Removed from TermArg due to reduce/reduce conflicts + | Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | Type2StringOpcode {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | Type2BufferOpcode {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | Type2BufferOrStringOpcode {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + +*/ + +TermArg + : Type2Opcode {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | DataObject {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | NameString {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | ArgTerm {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + | LocalTerm {$$ = TrSetNodeFlags ($1, NODE_IS_TERM_ARG);} + ; + +Target + : {$$ = TrSetNodeFlags (TrCreateLeafNode (PARSEOP_ZERO), NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);} /* Placeholder is a ZeroOp object */ + | ',' {$$ = TrSetNodeFlags (TrCreateLeafNode (PARSEOP_ZERO), NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);} /* Placeholder is a ZeroOp object */ + | ',' SuperName {$$ = TrSetNodeFlags ($2, NODE_IS_TARGET);} + ; + +RequiredTarget + : ',' SuperName {$$ = TrSetNodeFlags ($2, NODE_IS_TARGET);} + ; + +SimpleTarget + : NameString {} + | LocalTerm {} + | ArgTerm {} + ; + +/* Rules for specifying the type of one method argument or return value */ + +ParameterTypePackage + : {$$ = NULL;} + | ObjectTypeKeyword {$$ = $1;} + | ParameterTypePackage ',' + ObjectTypeKeyword {$$ = TrLinkPeerNodes (2,$1,$3);} + ; + +ParameterTypePackageList + : {$$ = NULL;} + | ObjectTypeKeyword {$$ = $1;} + | '{' ParameterTypePackage '}' {$$ = $2;} + ; + +OptionalParameterTypePackage + : {$$ = TrCreateLeafNode (PARSEOP_DEFAULT_ARG);} + | ',' ParameterTypePackageList {$$ = TrLinkChildren (TrCreateLeafNode (PARSEOP_DEFAULT_ARG),1,$2);} + ; + +/* Rules for specifying the types for method arguments */ + +ParameterTypesPackage + : ParameterTypePackageList {$$ = $1;} + | ParameterTypesPackage ',' + ParameterTypePackageList {$$ = TrLinkPeerNodes (2,$1,$3);} + ; + +ParameterTypesPackageList + : {$$ = NULL;} + | ObjectTypeKeyword {$$ = $1;} + | '{' ParameterTypesPackage '}' {$$ = $2;} + ; + +OptionalParameterTypesPackage + : {$$ = TrCreateLeafNode (PARSEOP_DEFAULT_ARG);} + | ',' ParameterTypesPackageList {$$ = TrLinkChildren (TrCreateLeafNode (PARSEOP_DEFAULT_ARG),1,$2);} + ; + + +/* Opcode types */ + +Type1Opcode + : BreakTerm {} + | BreakPointTerm {} + | ContinueTerm {} + | FatalTerm {} + | IfElseTerm {} + | LoadTerm {} + | NoOpTerm {} + | NotifyTerm {} + | ReleaseTerm {} + | ResetTerm {} + | ReturnTerm {} + | SignalTerm {} + | SleepTerm {} + | StallTerm {} + | SwitchTerm {} + | UnloadTerm {} + | WhileTerm {} + ; + +Type2Opcode + : AcquireTerm {} + | CondRefOfTerm {} + | CopyObjectTerm {} + | DerefOfTerm {} + | ObjectTypeTerm {} + | RefOfTerm {} + | SizeOfTerm {} + | StoreTerm {} + | TimerTerm {} + | WaitTerm {} + | UserTerm {} + ; + +/* + * Type 3/4/5 opcodes + */ + +Type2IntegerOpcode /* "Type3" opcodes */ + : AddTerm {} + | AndTerm {} + | DecTerm {} + | DivideTerm {} + | FindSetLeftBitTerm {} + | FindSetRightBitTerm {} + | FromBCDTerm {} + | IncTerm {} + | IndexTerm {} + | LAndTerm {} + | LEqualTerm {} + | LGreaterTerm {} + | LGreaterEqualTerm {} + | LLessTerm {} + | LLessEqualTerm {} + | LNotTerm {} + | LNotEqualTerm {} + | LoadTableTerm {} + | LOrTerm {} + | MatchTerm {} + | ModTerm {} + | MultiplyTerm {} + | NAndTerm {} + | NOrTerm {} + | NotTerm {} + | OrTerm {} + | ShiftLeftTerm {} + | ShiftRightTerm {} + | SubtractTerm {} + | ToBCDTerm {} + | ToIntegerTerm {} + | XOrTerm {} + ; + +Type2StringOpcode /* "Type4" Opcodes */ + : ToDecimalStringTerm {} + | ToHexStringTerm {} + | ToStringTerm {} + ; + +Type2BufferOpcode /* "Type5" Opcodes */ + : ToBufferTerm {} + | ConcatResTerm {} + ; + +Type2BufferOrStringOpcode + : ConcatTerm {} + | MidTerm {} + ; + +/* + * A type 3 opcode evaluates to an Integer and cannot have a destination operand + */ + +Type3Opcode + : EISAIDTerm {} + ; + +/* Obsolete +Type4Opcode + : ConcatTerm {} + | ToDecimalStringTerm {} + | ToHexStringTerm {} + | MidTerm {} + | ToStringTerm {} + ; +*/ + + +Type5Opcode + : ResourceTemplateTerm {} + | UnicodeTerm {} + | ToUUIDTerm {} + ; + +Type6Opcode + : RefOfTerm {} + | DerefOfTerm {} + | IndexTerm {} + | UserTerm {} + ; + +IncludeTerm + : PARSEOP_INCLUDE '(' {$$ = TrCreateLeafNode (PARSEOP_INCLUDE);} + String ')' {TrLinkChildren ($3,1,$4);FlOpenIncludeFile ($4);} + TermList + IncludeEndTerm {$$ = TrLinkPeerNodes (3,$3,$7,$8);} + ; + +IncludeEndTerm + : PARSEOP_INCLUDE_END {$$ = TrCreateLeafNode (PARSEOP_INCLUDE_END);} + ; + +IncludeCStyleTerm + : PARSEOP_INCLUDE_CSTYLE + String {FlOpenIncludeFile ($2);} + ; + +LineTerm + : PARSEOP_LINE_CSTYLE + Integer {FlSetLineNumber ($2);} + ; + +ExternalTerm + : PARSEOP_EXTERNAL '(' + NameString + OptionalObjectTypeKeyword + OptionalParameterTypePackage + OptionalParameterTypesPackage + ')' {$$ = TrCreateNode (PARSEOP_EXTERNAL,4,$3,$4,$5,$6);} + | PARSEOP_EXTERNAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Named Objects *******************************************************/ + + +BankFieldTerm + : PARSEOP_BANKFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_BANKFIELD);} + NameString + NameStringItem + TermArgItem + ',' AccessTypeKeyword + ',' LockRuleKeyword + ',' UpdateRuleKeyword + ')' '{' + FieldUnitList '}' {$$ = TrLinkChildren ($3,7,$4,$5,$6,$8,$10,$12,$15);} + | PARSEOP_BANKFIELD '(' + error ')' '{' error '}' {$$ = AslDoError(); yyclearin;} + ; + +FieldUnitList + : {$$ = NULL;} + | FieldUnit + | FieldUnitList ',' /* Allows a trailing comma at list end */ + | FieldUnitList ',' + FieldUnit {$$ = TrLinkPeerNode ($1,$3);} + ; + +FieldUnit + : FieldUnitEntry {} + | OffsetTerm {} + | AccessAsTerm {} + | ConnectionTerm {} + ; + +FieldUnitEntry + : ',' AmlPackageLengthTerm {$$ = TrCreateNode (PARSEOP_RESERVED_BYTES,1,$2);} + | NameSeg ',' + AmlPackageLengthTerm {$$ = TrLinkChildNode ($1,$3);} + ; + +OffsetTerm + : PARSEOP_OFFSET '(' + AmlPackageLengthTerm + ')' {$$ = TrCreateNode (PARSEOP_OFFSET,1,$3);} + | PARSEOP_OFFSET '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +AccessAsTerm + : PARSEOP_ACCESSAS '(' + AccessTypeKeyword + OptionalAccessAttribTerm + ')' {$$ = TrCreateNode (PARSEOP_ACCESSAS,2,$3,$4);} + | PARSEOP_ACCESSAS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ConnectionTerm + : PARSEOP_CONNECTION '(' + NameString + ')' {$$ = TrCreateNode (PARSEOP_CONNECTION,1,$3);} + | PARSEOP_CONNECTION '(' {$$ = TrCreateLeafNode (PARSEOP_CONNECTION);} + ResourceMacroTerm + ')' {$$ = TrLinkChildren ($3, 1, + TrLinkChildren (TrCreateLeafNode (PARSEOP_RESOURCETEMPLATE), 3, + TrCreateLeafNode (PARSEOP_DEFAULT_ARG), + TrCreateLeafNode (PARSEOP_DEFAULT_ARG), + $4));} + | PARSEOP_CONNECTION '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateBitFieldTerm + : PARSEOP_CREATEBITFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEBITFIELD);} + TermArg + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,3,$4,$5,TrSetNodeFlags ($6, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEBITFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateByteFieldTerm + : PARSEOP_CREATEBYTEFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEBYTEFIELD);} + TermArg + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,3,$4,$5,TrSetNodeFlags ($6, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEBYTEFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateDWordFieldTerm + : PARSEOP_CREATEDWORDFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEDWORDFIELD);} + TermArg + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,3,$4,$5,TrSetNodeFlags ($6, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEDWORDFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateFieldTerm + : PARSEOP_CREATEFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEFIELD);} + TermArg + TermArgItem + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,4,$4,$5,$6,TrSetNodeFlags ($7, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateQWordFieldTerm + : PARSEOP_CREATEQWORDFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEQWORDFIELD);} + TermArg + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,3,$4,$5,TrSetNodeFlags ($6, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEQWORDFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CreateWordFieldTerm + : PARSEOP_CREATEWORDFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_CREATEWORDFIELD);} + TermArg + TermArgItem + NameStringItem + ')' {$$ = TrLinkChildren ($3,3,$4,$5,TrSetNodeFlags ($6, NODE_IS_NAME_DECLARATION));} + | PARSEOP_CREATEWORDFIELD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DataRegionTerm + : PARSEOP_DATATABLEREGION '(' {$$ = TrCreateLeafNode (PARSEOP_DATATABLEREGION);} + NameString + TermArgItem + TermArgItem + TermArgItem + ')' {$$ = TrLinkChildren ($3,4,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$5,$6,$7);} + | PARSEOP_DATATABLEREGION '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DeviceTerm + : PARSEOP_DEVICE '(' {$$ = TrCreateLeafNode (PARSEOP_DEVICE);} + NameString + ')' '{' + ObjectList '}' {$$ = TrLinkChildren ($3,2,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$7);} + | PARSEOP_DEVICE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +EventTerm + : PARSEOP_EVENT '(' {$$ = TrCreateLeafNode (PARSEOP_EVENT);} + NameString + ')' {$$ = TrLinkChildren ($3,1,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION));} + | PARSEOP_EVENT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FieldTerm + : PARSEOP_FIELD '(' {$$ = TrCreateLeafNode (PARSEOP_FIELD);} + NameString + ',' AccessTypeKeyword + ',' LockRuleKeyword + ',' UpdateRuleKeyword + ')' '{' + FieldUnitList '}' {$$ = TrLinkChildren ($3,5,$4,$6,$8,$10,$13);} + | PARSEOP_FIELD '(' + error ')' '{' error '}' {$$ = AslDoError(); yyclearin;} + ; + +FunctionTerm + : PARSEOP_FUNCTION '(' {$$ = TrCreateLeafNode (PARSEOP_METHOD);} + NameString + OptionalParameterTypePackage + OptionalParameterTypesPackage + ')' '{' + TermList '}' {$$ = TrLinkChildren ($3,7,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION), + TrCreateValuedLeafNode (PARSEOP_BYTECONST, 0), + TrCreateLeafNode (PARSEOP_SERIALIZERULE_NOTSERIAL), + TrCreateValuedLeafNode (PARSEOP_BYTECONST, 0),$5,$6,$9);} + | PARSEOP_FUNCTION '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IndexFieldTerm + : PARSEOP_INDEXFIELD '(' {$$ = TrCreateLeafNode (PARSEOP_INDEXFIELD);} + NameString + NameStringItem + ',' AccessTypeKeyword + ',' LockRuleKeyword + ',' UpdateRuleKeyword + ')' '{' + FieldUnitList '}' {$$ = TrLinkChildren ($3,6,$4,$5,$7,$9,$11,$14);} + | PARSEOP_INDEXFIELD '(' + error ')' '{' error '}' {$$ = AslDoError(); yyclearin;} + ; + +MethodTerm + : PARSEOP_METHOD '(' {$$ = TrCreateLeafNode (PARSEOP_METHOD);} + NameString + OptionalByteConstExpr {UtCheckIntegerRange ($5, 0, 7);} + OptionalSerializeRuleKeyword + OptionalByteConstExpr + OptionalParameterTypePackage + OptionalParameterTypesPackage + ')' '{' + TermList '}' {$$ = TrLinkChildren ($3,7,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$5,$7,$8,$9,$10,$13);} + | PARSEOP_METHOD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +MutexTerm + : PARSEOP_MUTEX '(' {$$ = TrCreateLeafNode (PARSEOP_MUTEX);} + NameString + ',' ByteConstExpr + ')' {$$ = TrLinkChildren ($3,2,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$6);} + | PARSEOP_MUTEX '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +OpRegionTerm + : PARSEOP_OPERATIONREGION '(' {$$ = TrCreateLeafNode (PARSEOP_OPERATIONREGION);} + NameString + ',' OpRegionSpaceIdTerm + TermArgItem + TermArgItem + ')' {$$ = TrLinkChildren ($3,4,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$6,$7,$8);} + | PARSEOP_OPERATIONREGION '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +OpRegionSpaceIdTerm + : RegionSpaceKeyword {} + | ByteConst {$$ = UtCheckIntegerRange ($1, 0x80, 0xFF);} + ; + +PowerResTerm + : PARSEOP_POWERRESOURCE '(' {$$ = TrCreateLeafNode (PARSEOP_POWERRESOURCE);} + NameString + ',' ByteConstExpr + ',' WordConstExpr + ')' '{' + ObjectList '}' {$$ = TrLinkChildren ($3,4,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$6,$8,$11);} + | PARSEOP_POWERRESOURCE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ProcessorTerm + : PARSEOP_PROCESSOR '(' {$$ = TrCreateLeafNode (PARSEOP_PROCESSOR);} + NameString + ',' ByteConstExpr + OptionalDWordConstExpr + OptionalByteConstExpr + ')' '{' + ObjectList '}' {$$ = TrLinkChildren ($3,5,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$6,$7,$8,$11);} + | PARSEOP_PROCESSOR '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ThermalZoneTerm + : PARSEOP_THERMALZONE '(' {$$ = TrCreateLeafNode (PARSEOP_THERMALZONE);} + NameString + ')' '{' + ObjectList '}' {$$ = TrLinkChildren ($3,2,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$7);} + | PARSEOP_THERMALZONE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Namespace modifiers *************************************************/ + + +AliasTerm + : PARSEOP_ALIAS '(' {$$ = TrCreateLeafNode (PARSEOP_ALIAS);} + NameString + NameStringItem + ')' {$$ = TrLinkChildren ($3,2,$4,TrSetNodeFlags ($5, NODE_IS_NAME_DECLARATION));} + | PARSEOP_ALIAS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +NameTerm + : PARSEOP_NAME '(' {$$ = TrCreateLeafNode (PARSEOP_NAME);} + NameString + ',' DataObject + ')' {$$ = TrLinkChildren ($3,2,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$6);} + | PARSEOP_NAME '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ScopeTerm + : PARSEOP_SCOPE '(' {$$ = TrCreateLeafNode (PARSEOP_SCOPE);} + NameString + ')' '{' + ObjectList '}' {$$ = TrLinkChildren ($3,2,TrSetNodeFlags ($4, NODE_IS_NAME_DECLARATION),$7);} + | PARSEOP_SCOPE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Type 1 opcodes *******************************************************/ + + +BreakTerm + : PARSEOP_BREAK {$$ = TrCreateNode (PARSEOP_BREAK, 0);} + ; + +BreakPointTerm + : PARSEOP_BREAKPOINT {$$ = TrCreateNode (PARSEOP_BREAKPOINT, 0);} + ; + +ContinueTerm + : PARSEOP_CONTINUE {$$ = TrCreateNode (PARSEOP_CONTINUE, 0);} + ; + +FatalTerm + : PARSEOP_FATAL '(' {$$ = TrCreateLeafNode (PARSEOP_FATAL);} + ByteConstExpr + ',' DWordConstExpr + TermArgItem + ')' {$$ = TrLinkChildren ($3,3,$4,$6,$7);} + | PARSEOP_FATAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IfElseTerm + : IfTerm ElseTerm {$$ = TrLinkPeerNode ($1,$2);} + ; + +IfTerm + : PARSEOP_IF '(' {$$ = TrCreateLeafNode (PARSEOP_IF);} + TermArg + ')' '{' + TermList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + + | PARSEOP_IF '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ElseTerm + : {$$ = NULL;} + | PARSEOP_ELSE '{' {$$ = TrCreateLeafNode (PARSEOP_ELSE);} + TermList '}' {$$ = TrLinkChildren ($3,1,$4);} + + | PARSEOP_ELSE '{' + error '}' {$$ = AslDoError(); yyclearin;} + + | PARSEOP_ELSE + error {$$ = AslDoError(); yyclearin;} + + | PARSEOP_ELSEIF '(' {$$ = TrCreateLeafNode (PARSEOP_ELSE);} + TermArg {$$ = TrCreateLeafNode (PARSEOP_IF);} + ')' '{' + TermList '}' {TrLinkChildren ($5,2,$4,$8);} + ElseTerm {TrLinkPeerNode ($5,$11);} + {$$ = TrLinkChildren ($3,1,$5);} + + | PARSEOP_ELSEIF '(' + error ')' {$$ = AslDoError(); yyclearin;} + + | PARSEOP_ELSEIF + error {$$ = AslDoError(); yyclearin;} + ; + +LoadTerm + : PARSEOP_LOAD '(' {$$ = TrCreateLeafNode (PARSEOP_LOAD);} + NameString + RequiredTarget + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LOAD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +NoOpTerm + : PARSEOP_NOOP {$$ = TrCreateNode (PARSEOP_NOOP, 0);} + ; + +NotifyTerm + : PARSEOP_NOTIFY '(' {$$ = TrCreateLeafNode (PARSEOP_NOTIFY);} + SuperName + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_NOTIFY '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ReleaseTerm + : PARSEOP_RELEASE '(' {$$ = TrCreateLeafNode (PARSEOP_RELEASE);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_RELEASE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ResetTerm + : PARSEOP_RESET '(' {$$ = TrCreateLeafNode (PARSEOP_RESET);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_RESET '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ReturnTerm + : PARSEOP_RETURN '(' {$$ = TrCreateLeafNode (PARSEOP_RETURN);} + OptionalReturnArg + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_RETURN {$$ = TrLinkChildren (TrCreateLeafNode (PARSEOP_RETURN),1,TrSetNodeFlags (TrCreateLeafNode (PARSEOP_ZERO), NODE_IS_NULL_RETURN));} + | PARSEOP_RETURN '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SignalTerm + : PARSEOP_SIGNAL '(' {$$ = TrCreateLeafNode (PARSEOP_SIGNAL);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_SIGNAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SleepTerm + : PARSEOP_SLEEP '(' {$$ = TrCreateLeafNode (PARSEOP_SLEEP);} + TermArg + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_SLEEP '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +StallTerm + : PARSEOP_STALL '(' {$$ = TrCreateLeafNode (PARSEOP_STALL);} + TermArg + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_STALL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SwitchTerm + : PARSEOP_SWITCH '(' {$$ = TrCreateLeafNode (PARSEOP_SWITCH);} + TermArg + ')' '{' + CaseDefaultTermList '}' + {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_SWITCH '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +/* + * Case-Default list; allow only one Default term and unlimited Case terms + */ + +CaseDefaultTermList + : {$$ = NULL;} + | CaseTerm {} + | DefaultTerm {} + | CaseDefaultTermList + CaseTerm {$$ = TrLinkPeerNode ($1,$2);} + | CaseDefaultTermList + DefaultTerm {$$ = TrLinkPeerNode ($1,$2);} + +/* Original - attempts to force zero or one default term within the switch */ + +/* +CaseDefaultTermList + : {$$ = NULL;} + | CaseTermList + DefaultTerm + CaseTermList {$$ = TrLinkPeerNode ($1,TrLinkPeerNode ($2, $3));} + | CaseTermList + CaseTerm {$$ = TrLinkPeerNode ($1,$2);} + ; + +CaseTermList + : {$$ = NULL;} + | CaseTerm {} + | CaseTermList + CaseTerm {$$ = TrLinkPeerNode ($1,$2);} + ; +*/ + +CaseTerm + : PARSEOP_CASE '(' {$$ = TrCreateLeafNode (PARSEOP_CASE);} + DataObject + ')' '{' + TermList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_CASE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DefaultTerm + : PARSEOP_DEFAULT '{' {$$ = TrCreateLeafNode (PARSEOP_DEFAULT);} + TermList '}' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_DEFAULT '{' + error '}' {$$ = AslDoError(); yyclearin;} + ; + +UnloadTerm + : PARSEOP_UNLOAD '(' {$$ = TrCreateLeafNode (PARSEOP_UNLOAD);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_UNLOAD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +WhileTerm + : PARSEOP_WHILE '(' {$$ = TrCreateLeafNode (PARSEOP_WHILE);} + TermArg + ')' '{' TermList '}' + {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_WHILE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Type 2 opcodes *******************************************************/ + +AcquireTerm + : PARSEOP_ACQUIRE '(' {$$ = TrCreateLeafNode (PARSEOP_ACQUIRE);} + SuperName + ',' WordConstExpr + ')' {$$ = TrLinkChildren ($3,2,$4,$6);} + | PARSEOP_ACQUIRE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +AddTerm + : PARSEOP_ADD '(' {$$ = TrCreateLeafNode (PARSEOP_ADD);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_ADD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +AndTerm + : PARSEOP_AND '(' {$$ = TrCreateLeafNode (PARSEOP_AND);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_AND '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ConcatTerm + : PARSEOP_CONCATENATE '(' {$$ = TrCreateLeafNode (PARSEOP_CONCATENATE);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_CONCATENATE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ConcatResTerm + : PARSEOP_CONCATENATERESTEMPLATE '(' {$$ = TrCreateLeafNode (PARSEOP_CONCATENATERESTEMPLATE);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_CONCATENATERESTEMPLATE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CondRefOfTerm + : PARSEOP_CONDREFOF '(' {$$ = TrCreateLeafNode (PARSEOP_CONDREFOF);} + SuperName + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_CONDREFOF '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +CopyObjectTerm + : PARSEOP_COPYOBJECT '(' {$$ = TrCreateLeafNode (PARSEOP_COPYOBJECT);} + TermArg + ',' SimpleTarget + ')' {$$ = TrLinkChildren ($3,2,$4,TrSetNodeFlags ($6, NODE_IS_TARGET));} + | PARSEOP_COPYOBJECT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DecTerm + : PARSEOP_DECREMENT '(' {$$ = TrCreateLeafNode (PARSEOP_DECREMENT);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_DECREMENT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DerefOfTerm + : PARSEOP_DEREFOF '(' {$$ = TrCreateLeafNode (PARSEOP_DEREFOF);} + TermArg + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_DEREFOF '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DivideTerm + : PARSEOP_DIVIDE '(' {$$ = TrCreateLeafNode (PARSEOP_DIVIDE);} + TermArg + TermArgItem + Target + Target + ')' {$$ = TrLinkChildren ($3,4,$4,$5,$6,$7);} + | PARSEOP_DIVIDE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FindSetLeftBitTerm + : PARSEOP_FINDSETLEFTBIT '(' {$$ = TrCreateLeafNode (PARSEOP_FINDSETLEFTBIT);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_FINDSETLEFTBIT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FindSetRightBitTerm + : PARSEOP_FINDSETRIGHTBIT '(' {$$ = TrCreateLeafNode (PARSEOP_FINDSETRIGHTBIT);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_FINDSETRIGHTBIT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FromBCDTerm + : PARSEOP_FROMBCD '(' {$$ = TrCreateLeafNode (PARSEOP_FROMBCD);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_FROMBCD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IncTerm + : PARSEOP_INCREMENT '(' {$$ = TrCreateLeafNode (PARSEOP_INCREMENT);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_INCREMENT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IndexTerm + : PARSEOP_INDEX '(' {$$ = TrCreateLeafNode (PARSEOP_INDEX);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_INDEX '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LAndTerm + : PARSEOP_LAND '(' {$$ = TrCreateLeafNode (PARSEOP_LAND);} + TermArg + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LAND '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LEqualTerm + : PARSEOP_LEQUAL '(' {$$ = TrCreateLeafNode (PARSEOP_LEQUAL);} + TermArg + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LEQUAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LGreaterTerm + : PARSEOP_LGREATER '(' {$$ = TrCreateLeafNode (PARSEOP_LGREATER);} + TermArg + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LGREATER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LGreaterEqualTerm + : PARSEOP_LGREATEREQUAL '(' {$$ = TrCreateLeafNode (PARSEOP_LLESS);} + TermArg + TermArgItem + ')' {$$ = TrCreateNode (PARSEOP_LNOT, 1, TrLinkChildren ($3,2,$4,$5));} + | PARSEOP_LGREATEREQUAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LLessTerm + : PARSEOP_LLESS '(' {$$ = TrCreateLeafNode (PARSEOP_LLESS);} + TermArg + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LLESS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LLessEqualTerm + : PARSEOP_LLESSEQUAL '(' {$$ = TrCreateLeafNode (PARSEOP_LGREATER);} + TermArg + TermArgItem + ')' {$$ = TrCreateNode (PARSEOP_LNOT, 1, TrLinkChildren ($3,2,$4,$5));} + | PARSEOP_LLESSEQUAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LNotTerm + : PARSEOP_LNOT '(' {$$ = TrCreateLeafNode (PARSEOP_LNOT);} + TermArg + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_LNOT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LNotEqualTerm + : PARSEOP_LNOTEQUAL '(' {$$ = TrCreateLeafNode (PARSEOP_LEQUAL);} + TermArg + TermArgItem + ')' {$$ = TrCreateNode (PARSEOP_LNOT, 1, TrLinkChildren ($3,2,$4,$5));} + | PARSEOP_LNOTEQUAL '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LoadTableTerm + : PARSEOP_LOADTABLE '(' {$$ = TrCreateLeafNode (PARSEOP_LOADTABLE);} + TermArg + TermArgItem + TermArgItem + OptionalListString + OptionalListString + OptionalReference + ')' {$$ = TrLinkChildren ($3,6,$4,$5,$6,$7,$8,$9);} + | PARSEOP_LOADTABLE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +LOrTerm + : PARSEOP_LOR '(' {$$ = TrCreateLeafNode (PARSEOP_LOR);} + TermArg + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_LOR '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +MatchTerm + : PARSEOP_MATCH '(' {$$ = TrCreateLeafNode (PARSEOP_MATCH);} + TermArg + ',' MatchOpKeyword + TermArgItem + ',' MatchOpKeyword + TermArgItem + TermArgItem + ')' {$$ = TrLinkChildren ($3,6,$4,$6,$7,$9,$10,$11);} + | PARSEOP_MATCH '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +MidTerm + : PARSEOP_MID '(' {$$ = TrCreateLeafNode (PARSEOP_MID);} + TermArg + TermArgItem + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,4,$4,$5,$6,$7);} + | PARSEOP_MID '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ModTerm + : PARSEOP_MOD '(' {$$ = TrCreateLeafNode (PARSEOP_MOD);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_MOD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +MultiplyTerm + : PARSEOP_MULTIPLY '(' {$$ = TrCreateLeafNode (PARSEOP_MULTIPLY);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_MULTIPLY '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +NAndTerm + : PARSEOP_NAND '(' {$$ = TrCreateLeafNode (PARSEOP_NAND);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_NAND '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +NOrTerm + : PARSEOP_NOR '(' {$$ = TrCreateLeafNode (PARSEOP_NOR);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_NOR '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +NotTerm + : PARSEOP_NOT '(' {$$ = TrCreateLeafNode (PARSEOP_NOT);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_NOT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ObjectTypeTerm + : PARSEOP_OBJECTTYPE '(' {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_OBJECTTYPE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +OrTerm + : PARSEOP_OR '(' {$$ = TrCreateLeafNode (PARSEOP_OR);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_OR '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +/* + * In RefOf, the node isn't really a target, but we can't keep track of it after + * we've taken a pointer to it. (hard to tell if a local becomes initialized this way.) + */ +RefOfTerm + : PARSEOP_REFOF '(' {$$ = TrCreateLeafNode (PARSEOP_REFOF);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,TrSetNodeFlags ($4, NODE_IS_TARGET));} + | PARSEOP_REFOF '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ShiftLeftTerm + : PARSEOP_SHIFTLEFT '(' {$$ = TrCreateLeafNode (PARSEOP_SHIFTLEFT);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_SHIFTLEFT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ShiftRightTerm + : PARSEOP_SHIFTRIGHT '(' {$$ = TrCreateLeafNode (PARSEOP_SHIFTRIGHT);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_SHIFTRIGHT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SizeOfTerm + : PARSEOP_SIZEOF '(' {$$ = TrCreateLeafNode (PARSEOP_SIZEOF);} + SuperName + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_SIZEOF '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +StoreTerm + : PARSEOP_STORE '(' {$$ = TrCreateLeafNode (PARSEOP_STORE);} + TermArg + ',' SuperName + ')' {$$ = TrLinkChildren ($3,2,$4,TrSetNodeFlags ($6, NODE_IS_TARGET));} + | PARSEOP_STORE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SubtractTerm + : PARSEOP_SUBTRACT '(' {$$ = TrCreateLeafNode (PARSEOP_SUBTRACT);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_SUBTRACT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +TimerTerm + : PARSEOP_TIMER '(' {$$ = TrCreateLeafNode (PARSEOP_TIMER);} + ')' {$$ = TrLinkChildren ($3,0);} + | PARSEOP_TIMER {$$ = TrLinkChildren (TrCreateLeafNode (PARSEOP_TIMER),0);} + | PARSEOP_TIMER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToBCDTerm + : PARSEOP_TOBCD '(' {$$ = TrCreateLeafNode (PARSEOP_TOBCD);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_TOBCD '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToBufferTerm + : PARSEOP_TOBUFFER '(' {$$ = TrCreateLeafNode (PARSEOP_TOBUFFER);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_TOBUFFER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToDecimalStringTerm + : PARSEOP_TODECIMALSTRING '(' {$$ = TrCreateLeafNode (PARSEOP_TODECIMALSTRING);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_TODECIMALSTRING '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToHexStringTerm + : PARSEOP_TOHEXSTRING '(' {$$ = TrCreateLeafNode (PARSEOP_TOHEXSTRING);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_TOHEXSTRING '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToIntegerTerm + : PARSEOP_TOINTEGER '(' {$$ = TrCreateLeafNode (PARSEOP_TOINTEGER);} + TermArg + Target + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_TOINTEGER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToStringTerm + : PARSEOP_TOSTRING '(' {$$ = TrCreateLeafNode (PARSEOP_TOSTRING);} + TermArg + OptionalCount + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_TOSTRING '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ToUUIDTerm + : PARSEOP_TOUUID '(' + StringData ')' {$$ = TrUpdateNode (PARSEOP_TOUUID, $3);} + | PARSEOP_TOUUID '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +WaitTerm + : PARSEOP_WAIT '(' {$$ = TrCreateLeafNode (PARSEOP_WAIT);} + SuperName + TermArgItem + ')' {$$ = TrLinkChildren ($3,2,$4,$5);} + | PARSEOP_WAIT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +XOrTerm + : PARSEOP_XOR '(' {$$ = TrCreateLeafNode (PARSEOP_XOR);} + TermArg + TermArgItem + Target + ')' {$$ = TrLinkChildren ($3,3,$4,$5,$6);} + | PARSEOP_XOR '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Keywords *************************************************************/ + + +AccessAttribKeyword + : PARSEOP_ACCESSATTRIB_BLOCK {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_BLOCK);} + | PARSEOP_ACCESSATTRIB_BLOCK_CALL {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_BLOCK_CALL);} + | PARSEOP_ACCESSATTRIB_BYTE {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_BYTE);} + | PARSEOP_ACCESSATTRIB_QUICK {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_QUICK );} + | PARSEOP_ACCESSATTRIB_SND_RCV {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_SND_RCV);} + | PARSEOP_ACCESSATTRIB_WORD {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_WORD);} + | PARSEOP_ACCESSATTRIB_WORD_CALL {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_WORD_CALL);} + | PARSEOP_ACCESSATTRIB_MULTIBYTE '(' {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_MULTIBYTE);} + ByteConst + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_ACCESSATTRIB_RAW_BYTES '(' {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_RAW_BYTES);} + ByteConst + ')' {$$ = TrLinkChildren ($3,1,$4);} + | PARSEOP_ACCESSATTRIB_RAW_PROCESS '(' {$$ = TrCreateLeafNode (PARSEOP_ACCESSATTRIB_RAW_PROCESS);} + ByteConst + ')' {$$ = TrLinkChildren ($3,1,$4);} + ; + +AccessTypeKeyword + : PARSEOP_ACCESSTYPE_ANY {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_ANY);} + | PARSEOP_ACCESSTYPE_BYTE {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_BYTE);} + | PARSEOP_ACCESSTYPE_WORD {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_WORD);} + | PARSEOP_ACCESSTYPE_DWORD {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_DWORD);} + | PARSEOP_ACCESSTYPE_QWORD {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_QWORD);} + | PARSEOP_ACCESSTYPE_BUF {$$ = TrCreateLeafNode (PARSEOP_ACCESSTYPE_BUF);} + ; + +AddressingModeKeyword + : PARSEOP_ADDRESSINGMODE_7BIT {$$ = TrCreateLeafNode (PARSEOP_ADDRESSINGMODE_7BIT);} + | PARSEOP_ADDRESSINGMODE_10BIT {$$ = TrCreateLeafNode (PARSEOP_ADDRESSINGMODE_10BIT);} + ; + +AddressKeyword + : PARSEOP_ADDRESSTYPE_MEMORY {$$ = TrCreateLeafNode (PARSEOP_ADDRESSTYPE_MEMORY);} + | PARSEOP_ADDRESSTYPE_RESERVED {$$ = TrCreateLeafNode (PARSEOP_ADDRESSTYPE_RESERVED);} + | PARSEOP_ADDRESSTYPE_NVS {$$ = TrCreateLeafNode (PARSEOP_ADDRESSTYPE_NVS);} + | PARSEOP_ADDRESSTYPE_ACPI {$$ = TrCreateLeafNode (PARSEOP_ADDRESSTYPE_ACPI);} + ; + +AddressSpaceKeyword + : ByteConst {$$ = UtCheckIntegerRange ($1, 0x80, 0xFF);} + | RegionSpaceKeyword {} + ; + +BitsPerByteKeyword + : PARSEOP_BITSPERBYTE_FIVE {$$ = TrCreateLeafNode (PARSEOP_BITSPERBYTE_FIVE);} + | PARSEOP_BITSPERBYTE_SIX {$$ = TrCreateLeafNode (PARSEOP_BITSPERBYTE_SIX);} + | PARSEOP_BITSPERBYTE_SEVEN {$$ = TrCreateLeafNode (PARSEOP_BITSPERBYTE_SEVEN);} + | PARSEOP_BITSPERBYTE_EIGHT {$$ = TrCreateLeafNode (PARSEOP_BITSPERBYTE_EIGHT);} + | PARSEOP_BITSPERBYTE_NINE {$$ = TrCreateLeafNode (PARSEOP_BITSPERBYTE_NINE);} + ; + +ClockPhaseKeyword + : PARSEOP_CLOCKPHASE_FIRST {$$ = TrCreateLeafNode (PARSEOP_CLOCKPHASE_FIRST);} + | PARSEOP_CLOCKPHASE_SECOND {$$ = TrCreateLeafNode (PARSEOP_CLOCKPHASE_SECOND);} + ; + +ClockPolarityKeyword + : PARSEOP_CLOCKPOLARITY_LOW {$$ = TrCreateLeafNode (PARSEOP_CLOCKPOLARITY_LOW);} + | PARSEOP_CLOCKPOLARITY_HIGH {$$ = TrCreateLeafNode (PARSEOP_CLOCKPOLARITY_HIGH);} + ; + +DecodeKeyword + : PARSEOP_DECODETYPE_POS {$$ = TrCreateLeafNode (PARSEOP_DECODETYPE_POS);} + | PARSEOP_DECODETYPE_SUB {$$ = TrCreateLeafNode (PARSEOP_DECODETYPE_SUB);} + ; + +DevicePolarityKeyword + : PARSEOP_DEVICEPOLARITY_LOW {$$ = TrCreateLeafNode (PARSEOP_DEVICEPOLARITY_LOW);} + | PARSEOP_DEVICEPOLARITY_HIGH {$$ = TrCreateLeafNode (PARSEOP_DEVICEPOLARITY_HIGH);} + ; + +DMATypeKeyword + : PARSEOP_DMATYPE_A {$$ = TrCreateLeafNode (PARSEOP_DMATYPE_A);} + | PARSEOP_DMATYPE_COMPATIBILITY {$$ = TrCreateLeafNode (PARSEOP_DMATYPE_COMPATIBILITY);} + | PARSEOP_DMATYPE_B {$$ = TrCreateLeafNode (PARSEOP_DMATYPE_B);} + | PARSEOP_DMATYPE_F {$$ = TrCreateLeafNode (PARSEOP_DMATYPE_F);} + ; + +EndianKeyword + : PARSEOP_ENDIAN_LITTLE {$$ = TrCreateLeafNode (PARSEOP_ENDIAN_LITTLE);} + | PARSEOP_ENDIAN_BIG {$$ = TrCreateLeafNode (PARSEOP_ENDIAN_BIG);} + ; + +FlowControlKeyword + : PARSEOP_FLOWCONTROL_HW {$$ = TrCreateLeafNode (PARSEOP_FLOWCONTROL_HW);} + | PARSEOP_FLOWCONTROL_NONE {$$ = TrCreateLeafNode (PARSEOP_FLOWCONTROL_NONE);} + | PARSEOP_FLOWCONTROL_SW {$$ = TrCreateLeafNode (PARSEOP_FLOWCONTROL_SW);} + ; + +InterruptLevel + : PARSEOP_INTLEVEL_ACTIVEBOTH {$$ = TrCreateLeafNode (PARSEOP_INTLEVEL_ACTIVEBOTH);} + | PARSEOP_INTLEVEL_ACTIVEHIGH {$$ = TrCreateLeafNode (PARSEOP_INTLEVEL_ACTIVEHIGH);} + | PARSEOP_INTLEVEL_ACTIVELOW {$$ = TrCreateLeafNode (PARSEOP_INTLEVEL_ACTIVELOW);} + ; + +InterruptTypeKeyword + : PARSEOP_INTTYPE_EDGE {$$ = TrCreateLeafNode (PARSEOP_INTTYPE_EDGE);} + | PARSEOP_INTTYPE_LEVEL {$$ = TrCreateLeafNode (PARSEOP_INTTYPE_LEVEL);} + ; + +IODecodeKeyword + : PARSEOP_IODECODETYPE_16 {$$ = TrCreateLeafNode (PARSEOP_IODECODETYPE_16);} + | PARSEOP_IODECODETYPE_10 {$$ = TrCreateLeafNode (PARSEOP_IODECODETYPE_10);} + ; + +IoRestrictionKeyword + : PARSEOP_IORESTRICT_IN {$$ = TrCreateLeafNode (PARSEOP_IORESTRICT_IN);} + | PARSEOP_IORESTRICT_OUT {$$ = TrCreateLeafNode (PARSEOP_IORESTRICT_OUT);} + | PARSEOP_IORESTRICT_NONE {$$ = TrCreateLeafNode (PARSEOP_IORESTRICT_NONE);} + | PARSEOP_IORESTRICT_PRESERVE {$$ = TrCreateLeafNode (PARSEOP_IORESTRICT_PRESERVE);} + ; + +LockRuleKeyword + : PARSEOP_LOCKRULE_LOCK {$$ = TrCreateLeafNode (PARSEOP_LOCKRULE_LOCK);} + | PARSEOP_LOCKRULE_NOLOCK {$$ = TrCreateLeafNode (PARSEOP_LOCKRULE_NOLOCK);} + ; + +MatchOpKeyword + : PARSEOP_MATCHTYPE_MTR {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR);} + | PARSEOP_MATCHTYPE_MEQ {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ);} + | PARSEOP_MATCHTYPE_MLE {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MLE);} + | PARSEOP_MATCHTYPE_MLT {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MLT);} + | PARSEOP_MATCHTYPE_MGE {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MGE);} + | PARSEOP_MATCHTYPE_MGT {$$ = TrCreateLeafNode (PARSEOP_MATCHTYPE_MGT);} + ; + +MaxKeyword + : PARSEOP_MAXTYPE_FIXED {$$ = TrCreateLeafNode (PARSEOP_MAXTYPE_FIXED);} + | PARSEOP_MAXTYPE_NOTFIXED {$$ = TrCreateLeafNode (PARSEOP_MAXTYPE_NOTFIXED);} + ; + +MemTypeKeyword + : PARSEOP_MEMTYPE_CACHEABLE {$$ = TrCreateLeafNode (PARSEOP_MEMTYPE_CACHEABLE);} + | PARSEOP_MEMTYPE_WRITECOMBINING {$$ = TrCreateLeafNode (PARSEOP_MEMTYPE_WRITECOMBINING);} + | PARSEOP_MEMTYPE_PREFETCHABLE {$$ = TrCreateLeafNode (PARSEOP_MEMTYPE_PREFETCHABLE);} + | PARSEOP_MEMTYPE_NONCACHEABLE {$$ = TrCreateLeafNode (PARSEOP_MEMTYPE_NONCACHEABLE);} + ; + +MinKeyword + : PARSEOP_MINTYPE_FIXED {$$ = TrCreateLeafNode (PARSEOP_MINTYPE_FIXED);} + | PARSEOP_MINTYPE_NOTFIXED {$$ = TrCreateLeafNode (PARSEOP_MINTYPE_NOTFIXED);} + ; + +ObjectTypeKeyword + : PARSEOP_OBJECTTYPE_UNK {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_UNK);} + | PARSEOP_OBJECTTYPE_INT {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_INT);} + | PARSEOP_OBJECTTYPE_STR {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_STR);} + | PARSEOP_OBJECTTYPE_BUF {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_BUF);} + | PARSEOP_OBJECTTYPE_PKG {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_PKG);} + | PARSEOP_OBJECTTYPE_FLD {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_FLD);} + | PARSEOP_OBJECTTYPE_DEV {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_DEV);} + | PARSEOP_OBJECTTYPE_EVT {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_EVT);} + | PARSEOP_OBJECTTYPE_MTH {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_MTH);} + | PARSEOP_OBJECTTYPE_MTX {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_MTX);} + | PARSEOP_OBJECTTYPE_OPR {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_OPR);} + | PARSEOP_OBJECTTYPE_POW {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_POW);} + | PARSEOP_OBJECTTYPE_PRO {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_PRO);} + | PARSEOP_OBJECTTYPE_THZ {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_THZ);} + | PARSEOP_OBJECTTYPE_BFF {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_BFF);} + | PARSEOP_OBJECTTYPE_DDB {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_DDB);} + ; + +ParityTypeKeyword + : PARSEOP_PARITYTYPE_SPACE {$$ = TrCreateLeafNode (PARSEOP_PARITYTYPE_SPACE);} + | PARSEOP_PARITYTYPE_MARK {$$ = TrCreateLeafNode (PARSEOP_PARITYTYPE_MARK);} + | PARSEOP_PARITYTYPE_ODD {$$ = TrCreateLeafNode (PARSEOP_PARITYTYPE_ODD);} + | PARSEOP_PARITYTYPE_EVEN {$$ = TrCreateLeafNode (PARSEOP_PARITYTYPE_EVEN);} + | PARSEOP_PARITYTYPE_NONE {$$ = TrCreateLeafNode (PARSEOP_PARITYTYPE_NONE);} + ; + +PinConfigByte + : PinConfigKeyword {$$ = $1;} + | ByteConstExpr {$$ = UtCheckIntegerRange ($1, 0x80, 0xFF);} + ; + +PinConfigKeyword + : PARSEOP_PIN_NOPULL {$$ = TrCreateLeafNode (PARSEOP_PIN_NOPULL);} + | PARSEOP_PIN_PULLDOWN {$$ = TrCreateLeafNode (PARSEOP_PIN_PULLDOWN);} + | PARSEOP_PIN_PULLUP {$$ = TrCreateLeafNode (PARSEOP_PIN_PULLUP);} + | PARSEOP_PIN_PULLDEFAULT {$$ = TrCreateLeafNode (PARSEOP_PIN_PULLDEFAULT);} + ; + +RangeTypeKeyword + : PARSEOP_RANGETYPE_ISAONLY {$$ = TrCreateLeafNode (PARSEOP_RANGETYPE_ISAONLY);} + | PARSEOP_RANGETYPE_NONISAONLY {$$ = TrCreateLeafNode (PARSEOP_RANGETYPE_NONISAONLY);} + | PARSEOP_RANGETYPE_ENTIRE {$$ = TrCreateLeafNode (PARSEOP_RANGETYPE_ENTIRE);} + ; + +RegionSpaceKeyword + : PARSEOP_REGIONSPACE_IO {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_IO);} + | PARSEOP_REGIONSPACE_MEM {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_MEM);} + | PARSEOP_REGIONSPACE_PCI {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_PCI);} + | PARSEOP_REGIONSPACE_EC {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_EC);} + | PARSEOP_REGIONSPACE_SMBUS {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_SMBUS);} + | PARSEOP_REGIONSPACE_CMOS {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_CMOS);} + | PARSEOP_REGIONSPACE_PCIBAR {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_PCIBAR);} + | PARSEOP_REGIONSPACE_IPMI {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_IPMI);} + | PARSEOP_REGIONSPACE_GPIO {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_GPIO);} + | PARSEOP_REGIONSPACE_GSBUS {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_GSBUS);} + | PARSEOP_REGIONSPACE_FFIXEDHW {$$ = TrCreateLeafNode (PARSEOP_REGIONSPACE_FFIXEDHW);} + ; + +ResourceTypeKeyword + : PARSEOP_RESOURCETYPE_CONSUMER {$$ = TrCreateLeafNode (PARSEOP_RESOURCETYPE_CONSUMER);} + | PARSEOP_RESOURCETYPE_PRODUCER {$$ = TrCreateLeafNode (PARSEOP_RESOURCETYPE_PRODUCER);} + ; + +SerializeRuleKeyword + : PARSEOP_SERIALIZERULE_SERIAL {$$ = TrCreateLeafNode (PARSEOP_SERIALIZERULE_SERIAL);} + | PARSEOP_SERIALIZERULE_NOTSERIAL {$$ = TrCreateLeafNode (PARSEOP_SERIALIZERULE_NOTSERIAL);} + ; + +ShareTypeKeyword + : PARSEOP_SHARETYPE_SHARED {$$ = TrCreateLeafNode (PARSEOP_SHARETYPE_SHARED);} + | PARSEOP_SHARETYPE_EXCLUSIVE {$$ = TrCreateLeafNode (PARSEOP_SHARETYPE_EXCLUSIVE);} + | PARSEOP_SHARETYPE_SHAREDWAKE {$$ = TrCreateLeafNode (PARSEOP_SHARETYPE_SHAREDWAKE);} + | PARSEOP_SHARETYPE_EXCLUSIVEWAKE {$$ = TrCreateLeafNode (PARSEOP_SHARETYPE_EXCLUSIVEWAKE);} + ; + +SlaveModeKeyword + : PARSEOP_SLAVEMODE_CONTROLLERINIT {$$ = TrCreateLeafNode (PARSEOP_SLAVEMODE_CONTROLLERINIT);} + | PARSEOP_SLAVEMODE_DEVICEINIT {$$ = TrCreateLeafNode (PARSEOP_SLAVEMODE_DEVICEINIT);} + ; + +StopBitsKeyword + : PARSEOP_STOPBITS_TWO {$$ = TrCreateLeafNode (PARSEOP_STOPBITS_TWO);} + | PARSEOP_STOPBITS_ONEPLUSHALF {$$ = TrCreateLeafNode (PARSEOP_STOPBITS_ONEPLUSHALF);} + | PARSEOP_STOPBITS_ONE {$$ = TrCreateLeafNode (PARSEOP_STOPBITS_ONE);} + | PARSEOP_STOPBITS_ZERO {$$ = TrCreateLeafNode (PARSEOP_STOPBITS_ZERO);} + ; + +TranslationKeyword + : PARSEOP_TRANSLATIONTYPE_SPARSE {$$ = TrCreateLeafNode (PARSEOP_TRANSLATIONTYPE_SPARSE);} + | PARSEOP_TRANSLATIONTYPE_DENSE {$$ = TrCreateLeafNode (PARSEOP_TRANSLATIONTYPE_DENSE);} + ; + +TypeKeyword + : PARSEOP_TYPE_TRANSLATION {$$ = TrCreateLeafNode (PARSEOP_TYPE_TRANSLATION);} + | PARSEOP_TYPE_STATIC {$$ = TrCreateLeafNode (PARSEOP_TYPE_STATIC);} + ; + +UpdateRuleKeyword + : PARSEOP_UPDATERULE_PRESERVE {$$ = TrCreateLeafNode (PARSEOP_UPDATERULE_PRESERVE);} + | PARSEOP_UPDATERULE_ONES {$$ = TrCreateLeafNode (PARSEOP_UPDATERULE_ONES);} + | PARSEOP_UPDATERULE_ZEROS {$$ = TrCreateLeafNode (PARSEOP_UPDATERULE_ZEROS);} + ; + +WireModeKeyword + : PARSEOP_WIREMODE_FOUR {$$ = TrCreateLeafNode (PARSEOP_WIREMODE_FOUR);} + | PARSEOP_WIREMODE_THREE {$$ = TrCreateLeafNode (PARSEOP_WIREMODE_THREE);} + ; + +XferSizeKeyword + : PARSEOP_XFERSIZE_8 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_8, 0);} + | PARSEOP_XFERSIZE_16 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_16, 1);} + | PARSEOP_XFERSIZE_32 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_32, 2);} + | PARSEOP_XFERSIZE_64 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_64, 3);} + | PARSEOP_XFERSIZE_128 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_128, 4);} + | PARSEOP_XFERSIZE_256 {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_256, 5);} + ; + +XferTypeKeyword + : PARSEOP_XFERTYPE_8 {$$ = TrCreateLeafNode (PARSEOP_XFERTYPE_8);} + | PARSEOP_XFERTYPE_8_16 {$$ = TrCreateLeafNode (PARSEOP_XFERTYPE_8_16);} + | PARSEOP_XFERTYPE_16 {$$ = TrCreateLeafNode (PARSEOP_XFERTYPE_16);} + ; + + +/******* Miscellaneous Types **************************************************/ + + +SuperName + : NameString {} + | ArgTerm {} + | LocalTerm {} + | DebugTerm {} + | Type6Opcode {} +/* | UserTerm {} */ /* Caused reduce/reduce with Type6Opcode->UserTerm */ + ; + +ArgTerm + : PARSEOP_ARG0 {$$ = TrCreateLeafNode (PARSEOP_ARG0);} + | PARSEOP_ARG1 {$$ = TrCreateLeafNode (PARSEOP_ARG1);} + | PARSEOP_ARG2 {$$ = TrCreateLeafNode (PARSEOP_ARG2);} + | PARSEOP_ARG3 {$$ = TrCreateLeafNode (PARSEOP_ARG3);} + | PARSEOP_ARG4 {$$ = TrCreateLeafNode (PARSEOP_ARG4);} + | PARSEOP_ARG5 {$$ = TrCreateLeafNode (PARSEOP_ARG5);} + | PARSEOP_ARG6 {$$ = TrCreateLeafNode (PARSEOP_ARG6);} + ; + +LocalTerm + : PARSEOP_LOCAL0 {$$ = TrCreateLeafNode (PARSEOP_LOCAL0);} + | PARSEOP_LOCAL1 {$$ = TrCreateLeafNode (PARSEOP_LOCAL1);} + | PARSEOP_LOCAL2 {$$ = TrCreateLeafNode (PARSEOP_LOCAL2);} + | PARSEOP_LOCAL3 {$$ = TrCreateLeafNode (PARSEOP_LOCAL3);} + | PARSEOP_LOCAL4 {$$ = TrCreateLeafNode (PARSEOP_LOCAL4);} + | PARSEOP_LOCAL5 {$$ = TrCreateLeafNode (PARSEOP_LOCAL5);} + | PARSEOP_LOCAL6 {$$ = TrCreateLeafNode (PARSEOP_LOCAL6);} + | PARSEOP_LOCAL7 {$$ = TrCreateLeafNode (PARSEOP_LOCAL7);} + ; + +DebugTerm + : PARSEOP_DEBUG {$$ = TrCreateLeafNode (PARSEOP_DEBUG);} + ; + + +ByteConst + : Integer {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);} + ; + +WordConst + : Integer {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);} + ; + +DWordConst + : Integer {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);} + ; + +QWordConst + : Integer {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);} + ; + +Integer + : PARSEOP_INTEGER {$$ = TrCreateValuedLeafNode (PARSEOP_INTEGER, AslCompilerlval.i);} + ; + +String + : PARSEOP_STRING_LITERAL {$$ = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, (ACPI_NATIVE_INT) AslCompilerlval.s);} + ; + +ConstTerm + : ConstExprTerm {} + | PARSEOP_REVISION {$$ = TrCreateLeafNode (PARSEOP_REVISION);} + ; + +ConstExprTerm + : PARSEOP_ZERO {$$ = TrCreateValuedLeafNode (PARSEOP_ZERO, 0);} + | PARSEOP_ONE {$$ = TrCreateValuedLeafNode (PARSEOP_ONE, 1);} + | PARSEOP_ONES {$$ = TrCreateValuedLeafNode (PARSEOP_ONES, ACPI_UINT64_MAX);} + | PARSEOP___DATE__ {$$ = TrCreateConstantLeafNode (PARSEOP___DATE__);} + | PARSEOP___FILE__ {$$ = TrCreateConstantLeafNode (PARSEOP___FILE__);} + | PARSEOP___LINE__ {$$ = TrCreateConstantLeafNode (PARSEOP___LINE__);} + | PARSEOP___PATH__ {$$ = TrCreateConstantLeafNode (PARSEOP___PATH__);} + ; + +ByteConstExpr + : Type3Opcode {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);} + | Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);} + | ConstExprTerm {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);} + | ByteConst {} + ; + +WordConstExpr + : Type3Opcode {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);} + | Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);} + | ConstExprTerm {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);} + | WordConst {} + ; + +DWordConstExpr + : Type3Opcode {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);} + | Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);} + | ConstExprTerm {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);} + | DWordConst {} + ; + +QWordConstExpr + : Type3Opcode {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);} + | Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);} + | ConstExprTerm {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);} + | QWordConst {} + ; + +/* OptionalCount must appear before ByteList or an incorrect reduction will result */ + +OptionalCount + : {$$ = TrCreateLeafNode (PARSEOP_ONES);} /* Placeholder is a OnesOp object */ + | ',' {$$ = TrCreateLeafNode (PARSEOP_ONES);} /* Placeholder is a OnesOp object */ + | ',' TermArg {$$ = $2;} + ; + +BufferTerm + : PARSEOP_BUFFER '(' {$$ = TrCreateLeafNode (PARSEOP_BUFFER);} + OptionalTermArg + ')' '{' + BufferTermData '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_BUFFER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +BufferTermData + : ByteList {} + | StringData {} + ; + +ByteList + : {$$ = NULL;} + | ByteConstExpr + | ByteList ',' /* Allows a trailing comma at list end */ + | ByteList ',' + ByteConstExpr {$$ = TrLinkPeerNode ($1,$3);} + ; + +DataBufferTerm + : PARSEOP_DATABUFFER '(' {$$ = TrCreateLeafNode (PARSEOP_DATABUFFER);} + OptionalWordConst + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_DATABUFFER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DWordList + : {$$ = NULL;} + | DWordConstExpr + | DWordList ',' /* Allows a trailing comma at list end */ + | DWordList ',' + DWordConstExpr {$$ = TrLinkPeerNode ($1,$3);} + ; + +PackageTerm + : PARSEOP_PACKAGE '(' {$$ = TrCreateLeafNode (PARSEOP_VAR_PACKAGE);} + VarPackageLengthTerm + ')' '{' + PackageList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_PACKAGE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +PackageList + : {$$ = NULL;} + | PackageElement + | PackageList ',' /* Allows a trailing comma at list end */ + | PackageList ',' + PackageElement {$$ = TrLinkPeerNode ($1,$3);} + ; + +PackageElement + : DataObject {} + | NameString {} + ; + +VarPackageLengthTerm + : {$$ = TrCreateLeafNode (PARSEOP_DEFAULT_ARG);} + | TermArg {$$ = $1;} + ; + + +/******* Macros ***********************************************/ + + +EISAIDTerm + : PARSEOP_EISAID '(' + StringData ')' {$$ = TrUpdateNode (PARSEOP_EISAID, $3);} + | PARSEOP_EISAID '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +UnicodeTerm + : PARSEOP_UNICODE '(' {$$ = TrCreateLeafNode (PARSEOP_UNICODE);} + StringData + ')' {$$ = TrLinkChildren ($3,2,0,$4);} + | PARSEOP_UNICODE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Resources and Memory ***********************************************/ + + +/* + * Note: Create two default nodes to allow conversion to a Buffer AML opcode + * Also, insert the EndTag at the end of the template. + */ +ResourceTemplateTerm + : PARSEOP_RESOURCETEMPLATE '(' ')' + '{' + ResourceMacroList '}' {$$ = TrCreateNode (PARSEOP_RESOURCETEMPLATE,4, + TrCreateLeafNode (PARSEOP_DEFAULT_ARG), + TrCreateLeafNode (PARSEOP_DEFAULT_ARG), + $5, + TrCreateLeafNode (PARSEOP_ENDTAG));} + ; + +ResourceMacroList + : {$$ = NULL;} + | ResourceMacroList + ResourceMacroTerm {$$ = TrLinkPeerNode ($1,$2);} + ; + +ResourceMacroTerm + : DMATerm {} + | DWordIOTerm {} + | DWordMemoryTerm {} + | DWordSpaceTerm {} + | EndDependentFnTerm {} + | ExtendedIOTerm {} + | ExtendedMemoryTerm {} + | ExtendedSpaceTerm {} + | FixedDmaTerm {} + | FixedIOTerm {} + | GpioIntTerm {} + | GpioIoTerm {} + | I2cSerialBusTerm {} + | InterruptTerm {} + | IOTerm {} + | IRQNoFlagsTerm {} + | IRQTerm {} + | Memory24Term {} + | Memory32FixedTerm {} + | Memory32Term {} + | QWordIOTerm {} + | QWordMemoryTerm {} + | QWordSpaceTerm {} + | RegisterTerm {} + | SpiSerialBusTerm {} + | StartDependentFnNoPriTerm {} + | StartDependentFnTerm {} + | UartSerialBusTerm {} + | VendorLongTerm {} + | VendorShortTerm {} + | WordBusNumberTerm {} + | WordIOTerm {} + | WordSpaceTerm {} + ; + +DMATerm + : PARSEOP_DMA '(' {$$ = TrCreateLeafNode (PARSEOP_DMA);} + DMATypeKeyword + OptionalBusMasterKeyword + ',' XferTypeKeyword + OptionalNameString_Last + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,5,$4,$5,$7,$8,$11);} + | PARSEOP_DMA '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DWordIOTerm + : PARSEOP_DWORDIO '(' {$$ = TrCreateLeafNode (PARSEOP_DWORDIO);} + OptionalResourceType_First + OptionalMinType + OptionalMaxType + OptionalDecodeType + OptionalRangeType + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString + OptionalType + OptionalTranslationType_Last + ')' {$$ = TrLinkChildren ($3,15,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$19,$20,$21,$22,$23);} + | PARSEOP_DWORDIO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DWordMemoryTerm + : PARSEOP_DWORDMEMORY '(' {$$ = TrCreateLeafNode (PARSEOP_DWORDMEMORY);} + OptionalResourceType_First + OptionalDecodeType + OptionalMinType + OptionalMaxType + OptionalMemType + ',' OptionalReadWriteKeyword + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString + OptionalAddressRange + OptionalType_Last + ')' {$$ = TrLinkChildren ($3,16,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$20,$21,$22,$23,$24,$25);} + | PARSEOP_DWORDMEMORY '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +DWordSpaceTerm + : PARSEOP_DWORDSPACE '(' {$$ = TrCreateLeafNode (PARSEOP_DWORDSPACE);} + ByteConstExpr {UtCheckIntegerRange ($4, 0xC0, 0xFF);} + OptionalResourceType + OptionalDecodeType + OptionalMinType + OptionalMaxType + ',' ByteConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,14,$4,$6,$7,$8,$9,$11,$13,$15,$17,$19,$21,$22,$23,$24);} + | PARSEOP_DWORDSPACE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +EndDependentFnTerm + : PARSEOP_ENDDEPENDENTFN '(' + ')' {$$ = TrCreateLeafNode (PARSEOP_ENDDEPENDENTFN);} + | PARSEOP_ENDDEPENDENTFN '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ExtendedIOTerm + : PARSEOP_EXTENDEDIO '(' {$$ = TrCreateLeafNode (PARSEOP_EXTENDEDIO);} + OptionalResourceType_First + OptionalMinType + OptionalMaxType + OptionalDecodeType + OptionalRangeType + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalQWordConstExpr + OptionalNameString + OptionalType + OptionalTranslationType_Last + ')' {$$ = TrLinkChildren ($3,14,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$19,$20,$21,$22);} + | PARSEOP_EXTENDEDIO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ExtendedMemoryTerm + : PARSEOP_EXTENDEDMEMORY '(' {$$ = TrCreateLeafNode (PARSEOP_EXTENDEDMEMORY);} + OptionalResourceType_First + OptionalDecodeType + OptionalMinType + OptionalMaxType + OptionalMemType + ',' OptionalReadWriteKeyword + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalQWordConstExpr + OptionalNameString + OptionalAddressRange + OptionalType_Last + ')' {$$ = TrLinkChildren ($3,15,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$20,$21,$22,$23,$24);} + | PARSEOP_EXTENDEDMEMORY '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +ExtendedSpaceTerm + : PARSEOP_EXTENDEDSPACE '(' {$$ = TrCreateLeafNode (PARSEOP_EXTENDEDSPACE);} + ByteConstExpr {UtCheckIntegerRange ($4, 0xC0, 0xFF);} + OptionalResourceType + OptionalDecodeType + OptionalMinType + OptionalMaxType + ',' ByteConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalQWordConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,13,$4,$6,$7,$8,$9,$11,$13,$15,$17,$19,$21,$22,$23);} + | PARSEOP_EXTENDEDSPACE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FixedDmaTerm + : PARSEOP_FIXEDDMA '(' {$$ = TrCreateLeafNode (PARSEOP_FIXEDDMA);} + WordConstExpr // 04: DMA RequestLines + ',' WordConstExpr // 06: DMA Channels + OptionalXferSize // 07: DMA TransferSize + OptionalNameString // 08: DescriptorName + ')' {$$ = TrLinkChildren ($3,4,$4,$6,$7,$8);} + | PARSEOP_FIXEDDMA '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +FixedIOTerm + : PARSEOP_FIXEDIO '(' {$$ = TrCreateLeafNode (PARSEOP_FIXEDIO);} + WordConstExpr + ',' ByteConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,3,$4,$6,$7);} + | PARSEOP_FIXEDIO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +GpioIntTerm + : PARSEOP_GPIO_INT '(' {$$ = TrCreateLeafNode (PARSEOP_GPIO_INT);} + InterruptTypeKeyword // 04: InterruptType + ',' InterruptLevel // 06: InterruptLevel + OptionalShareType // 07: SharedType + ',' PinConfigByte // 09: PinConfig + OptionalWordConstExpr // 10: DebounceTimeout + ',' StringData // 12: ResourceSource + OptionalByteConstExpr // 13: ResourceSourceIndex + OptionalResourceType // 14: ResourceType + OptionalNameString // 15: DescriptorName + OptionalBuffer_Last // 16: VendorData + ')' '{' + DWordConstExpr '}' {$$ = TrLinkChildren ($3,11,$4,$6,$7,$9,$10,$12,$13,$14,$15,$16,$19);} + | PARSEOP_GPIO_INT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +GpioIoTerm + : PARSEOP_GPIO_IO '(' {$$ = TrCreateLeafNode (PARSEOP_GPIO_IO);} + OptionalShareType_First // 04: SharedType + ',' PinConfigByte // 06: PinConfig + OptionalWordConstExpr // 07: DebounceTimeout + OptionalWordConstExpr // 08: DriveStrength + OptionalIoRestriction // 09: IoRestriction + ',' StringData // 11: ResourceSource + OptionalByteConstExpr // 12: ResourceSourceIndex + OptionalResourceType // 13: ResourceType + OptionalNameString // 14: DescriptorName + OptionalBuffer_Last // 15: VendorData + ')' '{' + DWordList '}' {$$ = TrLinkChildren ($3,11,$4,$6,$7,$8,$9,$11,$12,$13,$14,$15,$18);} + | PARSEOP_GPIO_IO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +I2cSerialBusTerm + : PARSEOP_I2C_SERIALBUS '(' {$$ = TrCreateLeafNode (PARSEOP_I2C_SERIALBUS);} + WordConstExpr // 04: SlaveAddress + OptionalSlaveMode // 05: SlaveMode + ',' DWordConstExpr // 07: ConnectionSpeed + OptionalAddressingMode // 08: AddressingMode + ',' StringData // 10: ResourceSource + OptionalByteConstExpr // 11: ResourceSourceIndex + OptionalResourceType // 12: ResourceType + OptionalNameString // 13: DescriptorName + OptionalBuffer_Last // 14: VendorData + ')' {$$ = TrLinkChildren ($3,9,$4,$5,$7,$8,$10,$11,$12,$13,$14);} + | PARSEOP_I2C_SERIALBUS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +InterruptTerm + : PARSEOP_INTERRUPT '(' {$$ = TrCreateLeafNode (PARSEOP_INTERRUPT);} + OptionalResourceType_First + ',' InterruptTypeKeyword + ',' InterruptLevel + OptionalShareType + OptionalByteConstExpr + OptionalStringData + OptionalNameString_Last + ')' '{' + DWordList '}' {$$ = TrLinkChildren ($3,8,$4,$6,$8,$9,$10,$11,$12,$15);} + | PARSEOP_INTERRUPT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IOTerm + : PARSEOP_IO '(' {$$ = TrCreateLeafNode (PARSEOP_IO);} + IODecodeKeyword + ',' WordConstExpr + ',' WordConstExpr + ',' ByteConstExpr + ',' ByteConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,6,$4,$6,$8,$10,$12,$13);} + | PARSEOP_IO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IRQNoFlagsTerm + : PARSEOP_IRQNOFLAGS '(' {$$ = TrCreateLeafNode (PARSEOP_IRQNOFLAGS);} + OptionalNameString_First + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_IRQNOFLAGS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +IRQTerm + : PARSEOP_IRQ '(' {$$ = TrCreateLeafNode (PARSEOP_IRQ);} + InterruptTypeKeyword + ',' InterruptLevel + OptionalShareType + OptionalNameString_Last + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,5,$4,$6,$7,$8,$11);} + | PARSEOP_IRQ '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +Memory24Term + : PARSEOP_MEMORY24 '(' {$$ = TrCreateLeafNode (PARSEOP_MEMORY24);} + OptionalReadWriteKeyword + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,6,$4,$6,$8,$10,$12,$13);} + | PARSEOP_MEMORY24 '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +Memory32FixedTerm + : PARSEOP_MEMORY32FIXED '(' {$$ = TrCreateLeafNode (PARSEOP_MEMORY32FIXED);} + OptionalReadWriteKeyword + ',' DWordConstExpr + ',' DWordConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,4,$4,$6,$8,$9);} + | PARSEOP_MEMORY32FIXED '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +Memory32Term + : PARSEOP_MEMORY32 '(' {$$ = TrCreateLeafNode (PARSEOP_MEMORY32);} + OptionalReadWriteKeyword + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + ',' DWordConstExpr + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,6,$4,$6,$8,$10,$12,$13);} + | PARSEOP_MEMORY32 '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +QWordIOTerm + : PARSEOP_QWORDIO '(' {$$ = TrCreateLeafNode (PARSEOP_QWORDIO);} + OptionalResourceType_First + OptionalMinType + OptionalMaxType + OptionalDecodeType + OptionalRangeType + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString + OptionalType + OptionalTranslationType_Last + ')' {$$ = TrLinkChildren ($3,15,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$19,$20,$21,$22,$23);} + | PARSEOP_QWORDIO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +QWordMemoryTerm + : PARSEOP_QWORDMEMORY '(' {$$ = TrCreateLeafNode (PARSEOP_QWORDMEMORY);} + OptionalResourceType_First + OptionalDecodeType + OptionalMinType + OptionalMaxType + OptionalMemType + ',' OptionalReadWriteKeyword + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString + OptionalAddressRange + OptionalType_Last + ')' {$$ = TrLinkChildren ($3,16,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$20,$21,$22,$23,$24,$25);} + | PARSEOP_QWORDMEMORY '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +QWordSpaceTerm + : PARSEOP_QWORDSPACE '(' {$$ = TrCreateLeafNode (PARSEOP_QWORDSPACE);} + ByteConstExpr {UtCheckIntegerRange ($4, 0xC0, 0xFF);} + OptionalResourceType + OptionalDecodeType + OptionalMinType + OptionalMaxType + ',' ByteConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + ',' QWordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,14,$4,$6,$7,$8,$9,$11,$13,$15,$17,$19,$21,$22,$23,$24);} + | PARSEOP_QWORDSPACE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +RegisterTerm + : PARSEOP_REGISTER '(' {$$ = TrCreateLeafNode (PARSEOP_REGISTER);} + AddressSpaceKeyword + ',' ByteConstExpr + ',' ByteConstExpr + ',' QWordConstExpr + OptionalAccessSize + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,6,$4,$6,$8,$10,$11,$12);} + | PARSEOP_REGISTER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +SpiSerialBusTerm + : PARSEOP_SPI_SERIALBUS '(' {$$ = TrCreateLeafNode (PARSEOP_SPI_SERIALBUS);} + WordConstExpr // 04: DeviceSelection + OptionalDevicePolarity // 05: DevicePolarity + OptionalWireMode // 06: WireMode + ',' ByteConstExpr // 08: DataBitLength + OptionalSlaveMode // 09: SlaveMode + ',' DWordConstExpr // 11: ConnectionSpeed + ',' ClockPolarityKeyword // 13: ClockPolarity + ',' ClockPhaseKeyword // 15: ClockPhase + ',' StringData // 17: ResourceSource + OptionalByteConstExpr // 18: ResourceSourceIndex + OptionalResourceType // 19: ResourceType + OptionalNameString // 20: DescriptorName + OptionalBuffer_Last // 21: VendorData + ')' {$$ = TrLinkChildren ($3,13,$4,$5,$6,$8,$9,$11,$13,$15,$17,$18,$19,$20,$21);} + | PARSEOP_SPI_SERIALBUS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +StartDependentFnNoPriTerm + : PARSEOP_STARTDEPENDENTFN_NOPRI '(' {$$ = TrCreateLeafNode (PARSEOP_STARTDEPENDENTFN_NOPRI);} + ')' '{' + ResourceMacroList '}' {$$ = TrLinkChildren ($3,1,$6);} + | PARSEOP_STARTDEPENDENTFN_NOPRI '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +StartDependentFnTerm + : PARSEOP_STARTDEPENDENTFN '(' {$$ = TrCreateLeafNode (PARSEOP_STARTDEPENDENTFN);} + ByteConstExpr + ',' ByteConstExpr + ')' '{' + ResourceMacroList '}' {$$ = TrLinkChildren ($3,3,$4,$6,$9);} + | PARSEOP_STARTDEPENDENTFN '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +UartSerialBusTerm + : PARSEOP_UART_SERIALBUS '(' {$$ = TrCreateLeafNode (PARSEOP_UART_SERIALBUS);} + DWordConstExpr // 04: ConnectionSpeed + OptionalBitsPerByte // 05: BitsPerByte + OptionalStopBits // 06: StopBits + ',' ByteConstExpr // 08: LinesInUse + OptionalEndian // 09: Endianess + OptionalParityType // 10: Parity + OptionalFlowControl // 11: FlowControl + ',' WordConstExpr // 13: Rx BufferSize + ',' WordConstExpr // 15: Tx BufferSize + ',' StringData // 17: ResourceSource + OptionalByteConstExpr // 18: ResourceSourceIndex + OptionalResourceType // 19: ResourceType + OptionalNameString // 20: DescriptorName + OptionalBuffer_Last // 21: VendorData + ')' {$$ = TrLinkChildren ($3,14,$4,$5,$6,$8,$9,$10,$11,$13,$15,$17,$18,$19,$20,$21);} + | PARSEOP_UART_SERIALBUS '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +VendorLongTerm + : PARSEOP_VENDORLONG '(' {$$ = TrCreateLeafNode (PARSEOP_VENDORLONG);} + OptionalNameString_First + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_VENDORLONG '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +VendorShortTerm + : PARSEOP_VENDORSHORT '(' {$$ = TrCreateLeafNode (PARSEOP_VENDORSHORT);} + OptionalNameString_First + ')' '{' + ByteList '}' {$$ = TrLinkChildren ($3,2,$4,$7);} + | PARSEOP_VENDORSHORT '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +WordBusNumberTerm + : PARSEOP_WORDBUSNUMBER '(' {$$ = TrCreateLeafNode (PARSEOP_WORDBUSNUMBER);} + OptionalResourceType_First + OptionalMinType + OptionalMaxType + OptionalDecodeType + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,12,$4,$5,$6,$7,$9,$11,$13,$15,$17,$18,$19,$20);} + | PARSEOP_WORDBUSNUMBER '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +WordIOTerm + : PARSEOP_WORDIO '(' {$$ = TrCreateLeafNode (PARSEOP_WORDIO);} + OptionalResourceType_First + OptionalMinType + OptionalMaxType + OptionalDecodeType + OptionalRangeType + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString + OptionalType + OptionalTranslationType_Last + ')' {$$ = TrLinkChildren ($3,15,$4,$5,$6,$7,$8,$10,$12,$14,$16,$18,$19,$20,$21,$22,$23);} + | PARSEOP_WORDIO '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + +WordSpaceTerm + : PARSEOP_WORDSPACE '(' {$$ = TrCreateLeafNode (PARSEOP_WORDSPACE);} + ByteConstExpr {UtCheckIntegerRange ($4, 0xC0, 0xFF);} + OptionalResourceType + OptionalDecodeType + OptionalMinType + OptionalMaxType + ',' ByteConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + ',' WordConstExpr + OptionalByteConstExpr + OptionalStringData + OptionalNameString_Last + ')' {$$ = TrLinkChildren ($3,14,$4,$6,$7,$8,$9,$11,$13,$15,$17,$19,$21,$22,$23,$24);} + | PARSEOP_WORDSPACE '(' + error ')' {$$ = AslDoError(); yyclearin;} + ; + + +/******* Object References ***********************************************/ + +/* Allow IO, DMA, IRQ Resource macro names to also be used as identifiers */ + +NameString + : NameSeg {} + | PARSEOP_NAMESTRING {$$ = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, (ACPI_NATIVE_INT) AslCompilerlval.s);} + | PARSEOP_IO {$$ = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, (ACPI_NATIVE_INT) "IO");} + | PARSEOP_DMA {$$ = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, (ACPI_NATIVE_INT) "DMA");} + | PARSEOP_IRQ {$$ = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, (ACPI_NATIVE_INT) "IRQ");} + ; + +NameSeg + : PARSEOP_NAMESEG {$$ = TrCreateValuedLeafNode (PARSEOP_NAMESEG, (ACPI_NATIVE_INT) AslCompilerlval.s);} + ; + + +/******* Helper rules ****************************************************/ + + +AmlPackageLengthTerm + : Integer {$$ = TrUpdateNode (PARSEOP_PACKAGE_LENGTH,(ACPI_PARSE_OBJECT *) $1);} + ; + +NameStringItem + : ',' NameString {$$ = $2;} + | ',' error {$$ = AslDoError (); yyclearin;} + ; + +TermArgItem + : ',' TermArg {$$ = $2;} + | ',' error {$$ = AslDoError (); yyclearin;} + ; + +OptionalBusMasterKeyword + : ',' {$$ = TrCreateLeafNode (PARSEOP_BUSMASTERTYPE_MASTER);} + | ',' PARSEOP_BUSMASTERTYPE_MASTER {$$ = TrCreateLeafNode (PARSEOP_BUSMASTERTYPE_MASTER);} + | ',' PARSEOP_BUSMASTERTYPE_NOTMASTER {$$ = TrCreateLeafNode (PARSEOP_BUSMASTERTYPE_NOTMASTER);} + ; + +OptionalAccessAttribTerm + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' ByteConstExpr {$$ = $2;} + | ',' AccessAttribKeyword {$$ = $2;} + ; + +OptionalAccessSize + : {$$ = TrCreateValuedLeafNode (PARSEOP_BYTECONST, 0);} + | ',' {$$ = TrCreateValuedLeafNode (PARSEOP_BYTECONST, 0);} + | ',' ByteConstExpr {$$ = $2;} + ; + +OptionalAddressingMode + : ',' {$$ = NULL;} + | ',' AddressingModeKeyword {$$ = $2;} + ; + +OptionalAddressRange + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' AddressKeyword {$$ = $2;} + ; + +OptionalBitsPerByte + : ',' {$$ = NULL;} + | ',' BitsPerByteKeyword {$$ = $2;} + ; + +OptionalBuffer_Last + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' DataBufferTerm {$$ = $2;} + ; + +OptionalByteConstExpr + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' ByteConstExpr {$$ = $2;} + ; + +OptionalDecodeType + : ',' {$$ = NULL;} + | ',' DecodeKeyword {$$ = $2;} + ; + +OptionalDevicePolarity + : ',' {$$ = NULL;} + | ',' DevicePolarityKeyword {$$ = $2;} + ; + +OptionalDWordConstExpr + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' DWordConstExpr {$$ = $2;} + ; + +OptionalEndian + : ',' {$$ = NULL;} + | ',' EndianKeyword {$$ = $2;} + ; + +OptionalFlowControl + : ',' {$$ = NULL;} + | ',' FlowControlKeyword {$$ = $2;} + ; + +OptionalIoRestriction + : ',' {$$ = NULL;} + | ',' IoRestrictionKeyword {$$ = $2;} + ; + +OptionalListString + : {$$ = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, ACPI_TO_INTEGER (""));} /* Placeholder is a NULL string */ + | ',' {$$ = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, ACPI_TO_INTEGER (""));} /* Placeholder is a NULL string */ + | ',' TermArg {$$ = $2;} + ; + +OptionalMaxType + : ',' {$$ = NULL;} + | ',' MaxKeyword {$$ = $2;} + ; + +OptionalMemType + : ',' {$$ = NULL;} + | ',' MemTypeKeyword {$$ = $2;} + ; + +OptionalMinType + : ',' {$$ = NULL;} + | ',' MinKeyword {$$ = $2;} + ; + +OptionalNameString + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' NameString {$$ = $2;} + ; + +OptionalNameString_Last + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' NameString {$$ = $2;} + ; + +OptionalNameString_First + : {$$ = TrCreateLeafNode (PARSEOP_ZERO);} + | NameString {$$ = $1;} + ; + +OptionalObjectTypeKeyword + : {$$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE_UNK);} + | ',' ObjectTypeKeyword {$$ = $2;} + ; + +OptionalParityType + : ',' {$$ = NULL;} + | ',' ParityTypeKeyword {$$ = $2;} + ; + +OptionalQWordConstExpr + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' QWordConstExpr {$$ = $2;} + ; + +OptionalRangeType + : ',' {$$ = NULL;} + | ',' RangeTypeKeyword {$$ = $2;} + ; + +OptionalReadWriteKeyword + : {$$ = TrCreateLeafNode (PARSEOP_READWRITETYPE_BOTH);} + | PARSEOP_READWRITETYPE_BOTH {$$ = TrCreateLeafNode (PARSEOP_READWRITETYPE_BOTH);} + | PARSEOP_READWRITETYPE_READONLY {$$ = TrCreateLeafNode (PARSEOP_READWRITETYPE_READONLY);} + ; + +OptionalReference + : {$$ = TrCreateLeafNode (PARSEOP_ZERO);} /* Placeholder is a ZeroOp object */ + | ',' {$$ = TrCreateLeafNode (PARSEOP_ZERO);} /* Placeholder is a ZeroOp object */ + | ',' TermArg {$$ = $2;} + ; + +OptionalResourceType_First + : {$$ = TrCreateLeafNode (PARSEOP_RESOURCETYPE_CONSUMER);} + | ResourceTypeKeyword {$$ = $1;} + ; + +OptionalResourceType + : {$$ = TrCreateLeafNode (PARSEOP_RESOURCETYPE_CONSUMER);} + | ',' {$$ = TrCreateLeafNode (PARSEOP_RESOURCETYPE_CONSUMER);} + | ',' ResourceTypeKeyword {$$ = $2;} + ; + +OptionalReturnArg + : {$$ = TrSetNodeFlags (TrCreateLeafNode (PARSEOP_ZERO), NODE_IS_NULL_RETURN);} /* Placeholder is a ZeroOp object */ + | TermArg {$$ = $1;} + ; + +OptionalSerializeRuleKeyword + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' SerializeRuleKeyword {$$ = $2;} + ; + +OptionalSlaveMode + : ',' {$$ = NULL;} + | ',' SlaveModeKeyword {$$ = $2;} + ; + +OptionalShareType + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' ShareTypeKeyword {$$ = $2;} + ; + +OptionalShareType_First + : {$$ = NULL;} + | ShareTypeKeyword {$$ = $1;} + ; + +OptionalStopBits + : ',' {$$ = NULL;} + | ',' StopBitsKeyword {$$ = $2;} + ; + +OptionalStringData + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' StringData {$$ = $2;} + ; + +OptionalTermArg + : {$$ = NULL;} + | TermArg {$$ = $1;} + ; + +OptionalType + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' TypeKeyword {$$ = $2;} + ; + +OptionalType_Last + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' TypeKeyword {$$ = $2;} + ; + +OptionalTranslationType_Last + : {$$ = NULL;} + | ',' {$$ = NULL;} + | ',' TranslationKeyword {$$ = $2;} + ; + +OptionalWireMode + : ',' {$$ = NULL;} + | ',' WireModeKeyword {$$ = $2;} + ; + +OptionalWordConst + : {$$ = NULL;} + | WordConst {$$ = $1;} + ; + +OptionalWordConstExpr + : ',' {$$ = NULL;} + | ',' WordConstExpr {$$ = $2;} + ; + +OptionalXferSize + : {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_32, 2);} + | ',' {$$ = TrCreateValuedLeafNode (PARSEOP_XFERSIZE_32, 2);} + | ',' XferSizeKeyword {$$ = $2;} + ; + +%% +/****************************************************************************** + * + * Local support functions + * + *****************************************************************************/ + +int +AslCompilerwrap(void) +{ + return 1; +} + +/*! [End] no source code translation !*/ + +void * +AslLocalAllocate (unsigned int Size) +{ + void *Mem; + + + DbgPrint (ASL_PARSE_OUTPUT, "\nAslLocalAllocate: Expanding Stack to %u\n\n", Size); + + Mem = ACPI_ALLOCATE_ZEROED (Size); + if (!Mem) + { + AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_InputByteCount, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + exit (1); + } + + return (Mem); +} + +ACPI_PARSE_OBJECT * +AslDoError (void) +{ + + + return (TrCreateLeafNode (PARSEOP_ERRORNODE)); + +} + + +/******************************************************************************* + * + * FUNCTION: UtGetOpName + * + * PARAMETERS: ParseOpcode - Parser keyword ID + * + * RETURN: Pointer to the opcode name + * + * DESCRIPTION: Get the ascii name of the parse opcode + * + ******************************************************************************/ + +char * +UtGetOpName ( + UINT32 ParseOpcode) +{ +#ifdef ASL_YYTNAME_START + /* + * First entries (ASL_YYTNAME_START) in yytname are special reserved names. + * Ignore first 8 characters of the name + */ + return ((char *) yytname + [(ParseOpcode - ASL_FIRST_PARSE_OPCODE) + ASL_YYTNAME_START] + 8); +#else + return ("[Unknown parser generator]"); +#endif +} diff --git a/source/compiler/asldefine.h b/source/compiler/asldefine.h new file mode 100644 index 000000000000..a83a021bfec9 --- /dev/null +++ b/source/compiler/asldefine.h @@ -0,0 +1,177 @@ + +/****************************************************************************** + * + * Module Name: asldefine.h - Common defines for the iASL compiler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ASLDEFINE_H +#define __ASLDEFINE_H + + +/* + * Compiler versions and names + */ +#define ASL_REVISION ACPI_CA_VERSION +#define ASL_COMPILER_NAME "ASL Optimizing Compiler" +#define AML_DISASSEMBLER_NAME "AML Disassembler" +#define ASL_INVOCATION_NAME "iasl" +#define ASL_CREATOR_ID "INTL" + +#define ASL_COMPLIANCE "Supports ACPI Specification Revision 5.0" + + +/* Configuration constants */ + +#define ASL_MAX_ERROR_COUNT 200 +#define ASL_NODE_CACHE_SIZE 1024 +#define ASL_STRING_CACHE_SIZE 32768 + +#define ASL_FIRST_PARSE_OPCODE PARSEOP_ACCESSAS +#define ASL_PARSE_OPCODE_BASE PARSEOP_ACCESSAS /* First Lex type */ + + +/* + * Per-parser-generator configuration. These values are used to cheat and + * directly access the bison/yacc token name table (yyname or yytname). + * Note: These values are the index in yyname for the first lex token + * (PARSEOP_ACCCESSAS). + */ +#if defined (YYBISON) +#define ASL_YYTNAME_START 3 /* Bison */ +#elif defined (YYBYACC) +#define ASL_YYTNAME_START 257 /* Berkeley yacc */ +#endif + + +/* + * Macros + */ +#define ASL_RESDESC_OFFSET(m) ACPI_OFFSET (AML_RESOURCE, m) +#define ASL_PTR_DIFF(a,b) ((UINT8 *)(b) - (UINT8 *)(a)) +#define ASL_PTR_ADD(a,b) ((UINT8 *)(a) = ((UINT8 *)(a) + (b))) +#define ASL_GET_CHILD_NODE(a) (a)->Asl.Child +#define ASL_GET_PEER_NODE(a) (a)->Asl.Next +#define OP_TABLE_ENTRY(a,b,c,d) {b,d,a,c} + + +/* Internal AML opcodes */ + +#define AML_RAW_DATA_BYTE (UINT16) 0xAA01 /* write one raw byte */ +#define AML_RAW_DATA_WORD (UINT16) 0xAA02 /* write 2 raw bytes */ +#define AML_RAW_DATA_DWORD (UINT16) 0xAA04 /* write 4 raw bytes */ +#define AML_RAW_DATA_QWORD (UINT16) 0xAA08 /* write 8 raw bytes */ +#define AML_RAW_DATA_BUFFER (UINT16) 0xAA0B /* raw buffer with length */ +#define AML_RAW_DATA_CHAIN (UINT16) 0xAA0C /* chain of raw buffers */ +#define AML_PACKAGE_LENGTH (UINT16) 0xAA10 +#define AML_UNASSIGNED_OPCODE (UINT16) 0xEEEE +#define AML_DEFAULT_ARG_OP (UINT16) 0xDDDD + + +/* filename suffixes for output files */ + +#define FILE_SUFFIX_PREPROCESSOR "i" +#define FILE_SUFFIX_AML_CODE "aml" +#define FILE_SUFFIX_LISTING "lst" +#define FILE_SUFFIX_HEX_DUMP "hex" +#define FILE_SUFFIX_DEBUG "txt" +#define FILE_SUFFIX_SOURCE "src" +#define FILE_SUFFIX_NAMESPACE "nsp" +#define FILE_SUFFIX_ASM_SOURCE "asm" +#define FILE_SUFFIX_C_SOURCE "c" +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define FILE_SUFFIX_ASM_INCLUDE "inc" +#define FILE_SUFFIX_C_INCLUDE "h" +#define FILE_SUFFIX_ASL_CODE "asl" + + +/* Types for input files */ + +#define ASL_INPUT_TYPE_BINARY 0 +#define ASL_INPUT_TYPE_ASCII_ASL 1 +#define ASL_INPUT_TYPE_ASCII_DATA 2 + + +/* Misc */ + +#define ASL_EXTERNAL_METHOD 255 +#define ASL_ABORT TRUE +#define ASL_NO_ABORT FALSE +#define ASL_EOF ACPI_UINT32_MAX + + +/* Support for reserved method names */ + +#define ACPI_VALID_RESERVED_NAME_MAX 0x80000000 +#define ACPI_NOT_RESERVED_NAME ACPI_UINT32_MAX +#define ACPI_PREDEFINED_NAME (ACPI_UINT32_MAX - 1) +#define ACPI_EVENT_RESERVED_NAME (ACPI_UINT32_MAX - 2) +#define ACPI_COMPILER_RESERVED_NAME (ACPI_UINT32_MAX - 3) + + +/* String to Integer conversion */ + +#define NEGATIVE 1 +#define POSITIVE 0 + + +/* Helper macros for resource tag creation */ + +#define RsCreateMultiBitField \ + RsCreateResourceField + +#define RsCreateBitField(Op, Name, ByteOffset, BitOffset) \ + RsCreateResourceField (Op, Name, ByteOffset, BitOffset, 1) + +#define RsCreateByteField(Op, Name, ByteOffset) \ + RsCreateResourceField (Op, Name, ByteOffset, 0, 8); + +#define RsCreateWordField(Op, Name, ByteOffset) \ + RsCreateResourceField (Op, Name, ByteOffset, 0, 16); + +#define RsCreateDwordField(Op, Name, ByteOffset) \ + RsCreateResourceField (Op, Name, ByteOffset, 0, 32); + +#define RsCreateQwordField(Op, Name, ByteOffset) \ + RsCreateResourceField (Op, Name, ByteOffset, 0, 64); + +#endif /* ASLDEFINE.H */ + diff --git a/source/compiler/aslerror.c b/source/compiler/aslerror.c new file mode 100644 index 000000000000..e02e234a151b --- /dev/null +++ b/source/compiler/aslerror.c @@ -0,0 +1,647 @@ + +/****************************************************************************** + * + * Module Name: aslerror - Error handling and statistics + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define ASL_EXCEPTIONS +#include "aslcompiler.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslerror") + +/* Local prototypes */ + +static void +AeAddToErrorLog ( + ASL_ERROR_MSG *Enode); + + +void +AeClearErrorLog ( + void) +{ + ASL_ERROR_MSG *Enode = Gbl_ErrorLog; + ASL_ERROR_MSG *Next; + + /* Walk the error node list */ + + while (Enode) + { + Next = Enode->Next; + ACPI_FREE (Enode); + Enode = Next; + } + + Gbl_ErrorLog = NULL; +} + + +/******************************************************************************* + * + * FUNCTION: AeAddToErrorLog + * + * PARAMETERS: Enode - An error node to add to the log + * + * RETURN: None + * + * DESCRIPTION: Add a new error node to the error log. The error log is + * ordered by the "logical" line number (cumulative line number + * including all include files.) + * + ******************************************************************************/ + +static void +AeAddToErrorLog ( + ASL_ERROR_MSG *Enode) +{ + ASL_ERROR_MSG *Next; + ASL_ERROR_MSG *Prev; + + + /* If Gbl_ErrorLog is null, this is the first error node */ + + if (!Gbl_ErrorLog) + { + Gbl_ErrorLog = Enode; + return; + } + + /* + * Walk error list until we find a line number greater than ours. + * List is sorted according to line number. + */ + Prev = NULL; + Next = Gbl_ErrorLog; + + while ((Next) && + (Next->LogicalLineNumber <= Enode->LogicalLineNumber)) + { + Prev = Next; + Next = Next->Next; + } + + /* Found our place in the list */ + + Enode->Next = Next; + + if (Prev) + { + Prev->Next = Enode; + } + else + { + Gbl_ErrorLog = Enode; + } +} + + +/******************************************************************************* + * + * FUNCTION: AePrintException + * + * PARAMETERS: FileId - ID of output file + * Enode - Error node to print + * Header - Additional text before each message + * + * RETURN: None + * + * DESCRIPTION: Print the contents of an error node. + * + * NOTE: We don't use the FlxxxFile I/O functions here because on error + * they abort the compiler and call this function! Since we + * are reporting errors here, we ignore most output errors and + * just try to get out as much as we can. + * + ******************************************************************************/ + +void +AePrintException ( + UINT32 FileId, + ASL_ERROR_MSG *Enode, + char *Header) +{ + UINT8 SourceByte; + int Actual; + size_t RActual; + UINT32 MsgLength; + char *MainMessage; + char *ExtraMessage; + UINT32 SourceColumn; + UINT32 ErrorColumn; + FILE *OutputFile; + FILE *SourceFile; + long FileSize; + BOOLEAN PrematureEOF = FALSE; + + + if (Gbl_NoErrors) + { + return; + } + + /* + * Only listing files have a header, and remarks/optimizations + * are always output + */ + if (!Header) + { + /* Ignore remarks if requested */ + + switch (Enode->Level) + { + case ASL_REMARK: + if (!Gbl_DisplayRemarks) + { + return; + } + break; + + case ASL_OPTIMIZATION: + if (!Gbl_DisplayOptimizations) + { + return; + } + break; + + default: + break; + } + } + + /* Get the file handles */ + + OutputFile = Gbl_Files[FileId].Handle; + + /* Use the merged header/source file if present, otherwise use input file */ + + SourceFile = Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle; + if (!SourceFile) + { + SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle; + } + + if (SourceFile) + { + /* Determine if the error occurred at source file EOF */ + + fseek (SourceFile, 0, SEEK_END); + FileSize = ftell (SourceFile); + + if ((long) Enode->LogicalByteOffset >= FileSize) + { + PrematureEOF = TRUE; + } + } + + if (Header) + { + fprintf (OutputFile, "%s", Header); + } + + /* Print filename and line number if present and valid */ + + if (Enode->Filename) + { + if (Gbl_VerboseErrors) + { + fprintf (OutputFile, "%6s", Enode->Filename); + + if (Enode->LineNumber) + { + fprintf (OutputFile, " %6u: ", Enode->LineNumber); + + /* + * If not at EOF, get the corresponding source code line and + * display it. Don't attempt this if we have a premature EOF + * condition. + */ + if (!PrematureEOF) + { + /* + * Seek to the offset in the combined source file, read + * the source line, and write it to the output. + */ + Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset, + (int) SEEK_SET); + if (Actual) + { + fprintf (OutputFile, + "[*** iASL: Seek error on source code temp file %s ***]", + Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); + } + else + { + RActual = fread (&SourceByte, 1, 1, SourceFile); + if (!RActual) + { + fprintf (OutputFile, + "[*** iASL: Read error on source code temp file %s ***]", + Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); + } + + else while (RActual && SourceByte && (SourceByte != '\n')) + { + fwrite (&SourceByte, 1, 1, OutputFile); + RActual = fread (&SourceByte, 1, 1, SourceFile); + } + } + } + + fprintf (OutputFile, "\n"); + } + } + else + { + fprintf (OutputFile, "%s", Enode->Filename); + + if (Enode->LineNumber) + { + fprintf (OutputFile, "(%u) : ", Enode->LineNumber); + } + } + } + + /* NULL message ID, just print the raw message */ + + if (Enode->MessageId == 0) + { + fprintf (OutputFile, "%s\n", Enode->Message); + } + else + { + /* Decode the message ID */ + + fprintf (OutputFile, "%s %4.4d - ", + AslErrorLevel[Enode->Level], + Enode->MessageId + ((Enode->Level+1) * 1000)); + + MainMessage = AslMessages[Enode->MessageId]; + ExtraMessage = Enode->Message; + + if (Enode->LineNumber) + { + /* Main message: try to use string from AslMessages first */ + + if (!MainMessage) + { + MainMessage = ""; + } + + MsgLength = strlen (MainMessage); + if (MsgLength == 0) + { + /* Use the secondary/extra message as main message */ + + MainMessage = Enode->Message; + if (!MainMessage) + { + MainMessage = ""; + } + + MsgLength = strlen (MainMessage); + ExtraMessage = NULL; + } + + if (Gbl_VerboseErrors && !PrematureEOF) + { + SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2; + ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1; + + if ((MsgLength + ErrorColumn) < (SourceColumn - 1)) + { + fprintf (OutputFile, "%*s%s", + (int) ((SourceColumn - 1) - ErrorColumn), + MainMessage, " ^ "); + } + else + { + fprintf (OutputFile, "%*s %s", + (int) ((SourceColumn - ErrorColumn) + 1), "^", + MainMessage); + } + } + else + { + fprintf (OutputFile, " %s", MainMessage); + } + + /* Print the extra info message if present */ + + if (ExtraMessage) + { + fprintf (OutputFile, " (%s)", ExtraMessage); + } + + if (PrematureEOF) + { + fprintf (OutputFile, " and premature End-Of-File"); + } + + fprintf (OutputFile, "\n"); + if (Gbl_VerboseErrors) + { + fprintf (OutputFile, "\n"); + } + } + else + { + fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AePrintErrorLog + * + * PARAMETERS: FileId - Where to output the error log + * + * RETURN: None + * + * DESCRIPTION: Print the entire contents of the error log + * + ******************************************************************************/ + +void +AePrintErrorLog ( + UINT32 FileId) +{ + ASL_ERROR_MSG *Enode = Gbl_ErrorLog; + + + /* Walk the error node list */ + + while (Enode) + { + AePrintException (FileId, Enode, NULL); + Enode = Enode->Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: AslCommonError + * + * PARAMETERS: Level - Seriousness (Warning/error, etc.) + * MessageId - Index into global message buffer + * CurrentLineNumber - Actual file line number + * LogicalLineNumber - Cumulative line number + * LogicalByteOffset - Byte offset in source file + * Column - Column in current line + * Filename - source filename + * ExtraMessage - additional error message + * + * RETURN: None + * + * DESCRIPTION: Create a new error node and add it to the error log + * + ******************************************************************************/ + +void +AslCommonError ( + UINT8 Level, + UINT8 MessageId, + UINT32 CurrentLineNumber, + UINT32 LogicalLineNumber, + UINT32 LogicalByteOffset, + UINT32 Column, + char *Filename, + char *ExtraMessage) +{ + UINT32 MessageSize; + char *MessageBuffer = NULL; + ASL_ERROR_MSG *Enode; + + + Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); + + if (ExtraMessage) + { + /* Allocate a buffer for the message and a new error node */ + + MessageSize = strlen (ExtraMessage) + 1; + MessageBuffer = UtLocalCalloc (MessageSize); + + /* Keep a copy of the extra message */ + + ACPI_STRCPY (MessageBuffer, ExtraMessage); + } + + /* Initialize the error node */ + + if (Filename) + { + Enode->Filename = Filename; + Enode->FilenameLength = strlen (Filename); + if (Enode->FilenameLength < 6) + { + Enode->FilenameLength = 6; + } + } + + Enode->MessageId = MessageId; + Enode->Level = Level; + Enode->LineNumber = CurrentLineNumber; + Enode->LogicalLineNumber = LogicalLineNumber; + Enode->LogicalByteOffset = LogicalByteOffset; + Enode->Column = Column; + Enode->Message = MessageBuffer; + + /* Add the new node to the error node list */ + + AeAddToErrorLog (Enode); + + if (Gbl_DebugFlag) + { + /* stderr is a file, send error to it immediately */ + + AePrintException (ASL_FILE_STDERR, Enode, NULL); + } + + Gbl_ExceptionCount[Level]++; + if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) + { + printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT); + + Gbl_SourceLine = 0; + Gbl_NextError = Gbl_ErrorLog; + CmDoOutputFiles (); + CmCleanupAndExit (); + exit(1); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AslError + * + * PARAMETERS: Level - Seriousness (Warning/error, etc.) + * MessageId - Index into global message buffer + * Op - Parse node where error happened + * ExtraMessage - additional error message + * + * RETURN: None + * + * DESCRIPTION: Main error reporting routine for the ASL compiler (all code + * except the parser.) + * + ******************************************************************************/ + +void +AslError ( + UINT8 Level, + UINT8 MessageId, + ACPI_PARSE_OBJECT *Op, + char *ExtraMessage) +{ + + switch (Level) + { + case ASL_WARNING2: + case ASL_WARNING3: + if (Gbl_WarningLevel < Level) + { + return; + } + break; + + default: + break; + } + + + if (Op) + { + AslCommonError (Level, MessageId, Op->Asl.LineNumber, + Op->Asl.LogicalLineNumber, + Op->Asl.LogicalByteOffset, + Op->Asl.Column, + Op->Asl.Filename, ExtraMessage); + } + else + { + AslCommonError (Level, MessageId, 0, + 0, 0, 0, NULL, ExtraMessage); + } +} + + +/******************************************************************************* + * + * FUNCTION: AslCoreSubsystemError + * + * PARAMETERS: Op - Parse node where error happened + * Status - The ACPI CA Exception + * ExtraMessage - additional error message + * Abort - TRUE -> Abort compilation + * + * RETURN: None + * + * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI + * CA core subsystem. + * + ******************************************************************************/ + +void +AslCoreSubsystemError ( + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status, + char *ExtraMessage, + BOOLEAN Abort) +{ + + sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage); + + if (Op) + { + AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber, + Op->Asl.LogicalLineNumber, + Op->Asl.LogicalByteOffset, + Op->Asl.Column, + Op->Asl.Filename, MsgBuffer); + } + else + { + AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0, + 0, 0, 0, NULL, MsgBuffer); + } + + if (Abort) + { + AslAbort (); + } +} + + +/******************************************************************************* + * + * FUNCTION: AslCompilererror + * + * PARAMETERS: CompilerMessage - Error message from the parser + * + * RETURN: Status (0 for now) + * + * DESCRIPTION: Report an error situation discovered in a production + * NOTE: don't change the name of this function, it is called + * from the auto-generated parser. + * + ******************************************************************************/ + +int +AslCompilererror ( + const char *CompilerMessage) +{ + + AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, + Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, + Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, + ACPI_CAST_PTR (char, CompilerMessage)); + + return 0; +} + + diff --git a/source/compiler/aslfiles.c b/source/compiler/aslfiles.c new file mode 100644 index 000000000000..ada383d91c92 --- /dev/null +++ b/source/compiler/aslfiles.c @@ -0,0 +1,962 @@ + +/****************************************************************************** + * + * Module Name: aslfiles - file I/O suppoert + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "acapps.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslfiles") + +/* Local prototypes */ + +static FILE * +FlOpenIncludeWithPrefix ( + char *PrefixDir, + char *Filename); + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +ACPI_STATUS +FlParseInputPathname ( + char *InputFilename); +#endif + + +/******************************************************************************* + * + * FUNCTION: AslAbort + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump the error log and abort the compiler. Used for serious + * I/O errors + * + ******************************************************************************/ + +void +AslAbort ( + void) +{ + + AePrintErrorLog (ASL_FILE_STDOUT); + if (Gbl_DebugFlag) + { + /* Print error summary to the debug file */ + + AePrintErrorLog (ASL_FILE_STDERR); + } + + exit (1); +} + + +/******************************************************************************* + * + * FUNCTION: FlFileError + * + * PARAMETERS: FileId - Index into file info array + * ErrorId - Index into error message array + * + * RETURN: None + * + * DESCRIPTION: Decode errno to an error message and add the entire error + * to the error log. + * + ******************************************************************************/ + +void +FlFileError ( + UINT32 FileId, + UINT8 ErrorId) +{ + + sprintf (MsgBuffer, "\"%s\" (%s)", Gbl_Files[FileId].Filename, + strerror (errno)); + AslCommonError (ASL_ERROR, ErrorId, 0, 0, 0, 0, NULL, MsgBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenFile + * + * PARAMETERS: FileId - Index into file info array + * Filename - file pathname to open + * Mode - Open mode for fopen + * + * RETURN: None + * + * DESCRIPTION: Open a file. + * NOTE: Aborts compiler on any error. + * + ******************************************************************************/ + +void +FlOpenFile ( + UINT32 FileId, + char *Filename, + char *Mode) +{ + FILE *File; + + + File = fopen (Filename, Mode); + + Gbl_Files[FileId].Filename = Filename; + Gbl_Files[FileId].Handle = File; + + if (!File) + { + FlFileError (FileId, ASL_MSG_OPEN); + AslAbort (); + } +} + + +/******************************************************************************* + * + * FUNCTION: FlGetFileSize + * + * PARAMETERS: FileId - Index into file info array + * + * RETURN: File Size + * + * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open. + * + ******************************************************************************/ + +UINT32 +FlGetFileSize ( + UINT32 FileId) +{ + FILE *fp; + UINT32 FileSize; + long Offset; + + + fp = Gbl_Files[FileId].Handle; + Offset = ftell (fp); + + fseek (fp, 0, SEEK_END); + FileSize = (UINT32) ftell (fp); + + /* Restore file pointer */ + + fseek (fp, Offset, SEEK_SET); + return (FileSize); +} + + +/******************************************************************************* + * + * FUNCTION: FlReadFile + * + * PARAMETERS: FileId - Index into file info array + * Buffer - Where to place the data + * Length - Amount to read + * + * RETURN: Status. AE_ERROR indicates EOF. + * + * DESCRIPTION: Read data from an open file. + * NOTE: Aborts compiler on any error. + * + ******************************************************************************/ + +ACPI_STATUS +FlReadFile ( + UINT32 FileId, + void *Buffer, + UINT32 Length) +{ + UINT32 Actual; + + + /* Read and check for error */ + + Actual = fread (Buffer, 1, Length, Gbl_Files[FileId].Handle); + if (Actual != Length) + { + if (feof (Gbl_Files[FileId].Handle)) + { + /* End-of-file, just return error */ + + return (AE_ERROR); + } + + FlFileError (FileId, ASL_MSG_READ); + AslAbort (); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: FlWriteFile + * + * PARAMETERS: FileId - Index into file info array + * Buffer - Data to write + * Length - Amount of data to write + * + * RETURN: None + * + * DESCRIPTION: Write data to an open file. + * NOTE: Aborts compiler on any error. + * + ******************************************************************************/ + +void +FlWriteFile ( + UINT32 FileId, + void *Buffer, + UINT32 Length) +{ + UINT32 Actual; + + + /* Write and check for error */ + + Actual = fwrite ((char *) Buffer, 1, Length, Gbl_Files[FileId].Handle); + if (Actual != Length) + { + FlFileError (FileId, ASL_MSG_WRITE); + AslAbort (); + } +} + + +/******************************************************************************* + * + * FUNCTION: FlPrintFile + * + * PARAMETERS: FileId - Index into file info array + * Format - Printf format string + * ... - Printf arguments + * + * RETURN: None + * + * DESCRIPTION: Formatted write to an open file. + * NOTE: Aborts compiler on any error. + * + ******************************************************************************/ + +void +FlPrintFile ( + UINT32 FileId, + char *Format, + ...) +{ + INT32 Actual; + va_list Args; + + + va_start (Args, Format); + + Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args); + va_end (Args); + + if (Actual == -1) + { + FlFileError (FileId, ASL_MSG_WRITE); + AslAbort (); + } +} + + +/******************************************************************************* + * + * FUNCTION: FlSeekFile + * + * PARAMETERS: FileId - Index into file info array + * Offset - Absolute byte offset in file + * + * RETURN: None + * + * DESCRIPTION: Seek to absolute offset + * NOTE: Aborts compiler on any error. + * + ******************************************************************************/ + +void +FlSeekFile ( + UINT32 FileId, + long Offset) +{ + int Error; + + + Error = fseek (Gbl_Files[FileId].Handle, Offset, SEEK_SET); + if (Error) + { + FlFileError (FileId, ASL_MSG_SEEK); + AslAbort (); + } +} + + +/******************************************************************************* + * + * FUNCTION: FlCloseFile + * + * PARAMETERS: FileId - Index into file info array + * + * RETURN: None + * + * DESCRIPTION: Close an open file. Aborts compiler on error + * + ******************************************************************************/ + +void +FlCloseFile ( + UINT32 FileId) +{ + int Error; + + + if (!Gbl_Files[FileId].Handle) + { + return; + } + + Error = fclose (Gbl_Files[FileId].Handle); + Gbl_Files[FileId].Handle = NULL; + + if (Error) + { + FlFileError (FileId, ASL_MSG_CLOSE); + AslAbort (); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: FlSetLineNumber + * + * PARAMETERS: Op - Parse node for the LINE asl statement + * + * RETURN: None. + * + * DESCRIPTION: Set the current line number + * + ******************************************************************************/ + +void +FlSetLineNumber ( + ACPI_PARSE_OBJECT *Op) +{ + + Gbl_CurrentLineNumber = (UINT32) Op->Asl.Value.Integer; + Gbl_LogicalLineNumber = (UINT32) Op->Asl.Value.Integer; +} + + +/******************************************************************************* + * + * FUNCTION: FlAddIncludeDirectory + * + * PARAMETERS: Dir - Directory pathname string + * + * RETURN: None + * + * DESCRIPTION: Add a directory the list of include prefix directories. + * + ******************************************************************************/ + +void +FlAddIncludeDirectory ( + char *Dir) +{ + ASL_INCLUDE_DIR *NewDir; + ASL_INCLUDE_DIR *NextDir; + ASL_INCLUDE_DIR *PrevDir = NULL; + UINT32 NeedsSeparator = 0; + size_t DirLength; + + + DirLength = strlen (Dir); + if (!DirLength) + { + return; + } + + /* Make sure that the pathname ends with a path separator */ + + if ((Dir[DirLength-1] != '/') && + (Dir[DirLength-1] != '\\')) + { + NeedsSeparator = 1; + } + + NewDir = ACPI_ALLOCATE_ZEROED (sizeof (ASL_INCLUDE_DIR)); + NewDir->Dir = ACPI_ALLOCATE (DirLength + 1 + NeedsSeparator); + strcpy (NewDir->Dir, Dir); + if (NeedsSeparator) + { + strcat (NewDir->Dir, "/"); + } + + /* + * Preserve command line ordering of -I options by adding new elements + * at the end of the list + */ + NextDir = Gbl_IncludeDirList; + while (NextDir) + { + PrevDir = NextDir; + NextDir = NextDir->Next; + } + + if (PrevDir) + { + PrevDir->Next = NewDir; + } + else + { + Gbl_IncludeDirList = NewDir; + } +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenIncludeWithPrefix + * + * PARAMETERS: PrefixDir - Prefix directory pathname. Can be a zero + * length string. + * Filename - The include filename from the source ASL. + * + * RETURN: Valid file descriptor if successful. Null otherwise. + * + * DESCRIPTION: Open an include file and push it on the input file stack. + * + ******************************************************************************/ + +static FILE * +FlOpenIncludeWithPrefix ( + char *PrefixDir, + char *Filename) +{ + FILE *IncludeFile; + char *Pathname; + + + /* Build the full pathname to the file */ + + Pathname = ACPI_ALLOCATE (strlen (PrefixDir) + strlen (Filename) + 1); + + strcpy (Pathname, PrefixDir); + strcat (Pathname, Filename); + + DbgPrint (ASL_PARSE_OUTPUT, "\nAttempt to open include file: path %s\n\n", + Pathname); + + /* Attempt to open the file, push if successful */ + + IncludeFile = fopen (Pathname, "r"); + if (IncludeFile) + { + /* Push the include file on the open input file stack */ + + AslPushInputFileStack (IncludeFile, Pathname); + return (IncludeFile); + } + + ACPI_FREE (Pathname); + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenIncludeFile + * + * PARAMETERS: Op - Parse node for the INCLUDE ASL statement + * + * RETURN: None. + * + * DESCRIPTION: Open an include file and push it on the input file stack. + * + ******************************************************************************/ + +void +FlOpenIncludeFile ( + ACPI_PARSE_OBJECT *Op) +{ + FILE *IncludeFile; + ASL_INCLUDE_DIR *NextDir; + + + /* Op must be valid */ + + if (!Op) + { + AslCommonError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_InputByteCount, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, " - Null parse node"); + + return; + } + + /* + * Flush out the "include ()" statement on this line, start + * the actual include file on the next line + */ + ResetCurrentLineBuffer (); + FlPrintFile (ASL_FILE_SOURCE_OUTPUT, "\n"); + Gbl_CurrentLineOffset++; + + + /* Attempt to open the include file */ + + /* If the file specifies an absolute path, just open it */ + + if ((Op->Asl.Value.String[0] == '/') || + (Op->Asl.Value.String[0] == '\\') || + (Op->Asl.Value.String[1] == ':')) + { + IncludeFile = FlOpenIncludeWithPrefix ("", Op->Asl.Value.String); + if (!IncludeFile) + { + goto ErrorExit; + } + return; + } + + /* + * The include filename is not an absolute path. + * + * First, search for the file within the "local" directory -- meaning + * the same directory that contains the source file. + * + * Construct the file pathname from the global directory name. + */ + IncludeFile = FlOpenIncludeWithPrefix (Gbl_DirectoryPath, Op->Asl.Value.String); + if (IncludeFile) + { + return; + } + + /* + * Second, search for the file within the (possibly multiple) directories + * specified by the -I option on the command line. + */ + NextDir = Gbl_IncludeDirList; + while (NextDir) + { + IncludeFile = FlOpenIncludeWithPrefix (NextDir->Dir, Op->Asl.Value.String); + if (IncludeFile) + { + return; + } + + NextDir = NextDir->Next; + } + + /* We could not open the include file after trying very hard */ + +ErrorExit: + sprintf (MsgBuffer, "%s, %s", Op->Asl.Value.String, strerror (errno)); + AslError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, Op, MsgBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenInputFile + * + * PARAMETERS: InputFilename - The user-specified ASL source file to be + * compiled + * + * RETURN: Status + * + * DESCRIPTION: Open the specified input file, and save the directory path to + * the file so that include files can be opened in + * the same directory. + * + ******************************************************************************/ + +ACPI_STATUS +FlOpenInputFile ( + char *InputFilename) +{ + + /* Open the input ASL file, text mode */ + + FlOpenFile (ASL_FILE_INPUT, InputFilename, "r"); + AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenAmlOutputFile + * + * PARAMETERS: FilenamePrefix - The user-specified ASL source file + * + * RETURN: Status + * + * DESCRIPTION: Create the output filename (*.AML) and open the file. The file + * is created in the same directory as the parent input file. + * + ******************************************************************************/ + +ACPI_STATUS +FlOpenAmlOutputFile ( + char *FilenamePrefix) +{ + char *Filename; + + + /* Output filename usually comes from the ASL itself */ + + Filename = Gbl_Files[ASL_FILE_AML_OUTPUT].Filename; + if (!Filename) + { + /* Create the output AML filename */ + + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_AML_CODE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_OUTPUT_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + } + + /* Open the output AML file in binary mode */ + + FlOpenFile (ASL_FILE_AML_OUTPUT, Filename, "w+b"); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: FlOpenMiscOutputFiles + * + * PARAMETERS: FilenamePrefix - The user-specified ASL source file + * + * RETURN: Status + * + * DESCRIPTION: Create and open the various output files needed, depending on + * the command line options + * + ******************************************************************************/ + +ACPI_STATUS +FlOpenMiscOutputFiles ( + char *FilenamePrefix) +{ + char *Filename; + + + /* Create/Open a hex output file if asked */ + + if (Gbl_HexOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_HEX_DUMP); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the hex file, text mode */ + + FlOpenFile (ASL_FILE_HEX_OUTPUT, Filename, "w+"); + + AslCompilerSignon (ASL_FILE_HEX_OUTPUT); + AslCompilerFileHeader (ASL_FILE_HEX_OUTPUT); + } + + /* Create/Open a debug output file if asked */ + + if (Gbl_DebugFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_DEBUG); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_DEBUG_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the debug file as STDERR, text mode */ + + /* TBD: hide this behind a FlReopenFile function */ + + Gbl_Files[ASL_FILE_DEBUG_OUTPUT].Filename = Filename; + Gbl_Files[ASL_FILE_DEBUG_OUTPUT].Handle = + freopen (Filename, "w+t", stderr); + + AslCompilerSignon (ASL_FILE_DEBUG_OUTPUT); + AslCompilerFileHeader (ASL_FILE_DEBUG_OUTPUT); + } + + /* Create/Open a listing output file if asked */ + + if (Gbl_ListingFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_LISTING); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the listing file, text mode */ + + FlOpenFile (ASL_FILE_LISTING_OUTPUT, Filename, "w+"); + + AslCompilerSignon (ASL_FILE_LISTING_OUTPUT); + AslCompilerFileHeader (ASL_FILE_LISTING_OUTPUT); + } + + if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) + { + return (AE_OK); + } + + /* Create/Open a combined source output file */ + + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_SOURCE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* + * Open the source output file, binary mode (so that LF does not get + * expanded to CR/LF on some systems, messing up our seek + * calculations.) + */ + FlOpenFile (ASL_FILE_SOURCE_OUTPUT, Filename, "w+b"); + + /* Create/Open a assembly code source output file if asked */ + + if (Gbl_AsmOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_ASM_SOURCE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the assembly code source file, text mode */ + + FlOpenFile (ASL_FILE_ASM_SOURCE_OUTPUT, Filename, "w+"); + + AslCompilerSignon (ASL_FILE_ASM_SOURCE_OUTPUT); + AslCompilerFileHeader (ASL_FILE_ASM_SOURCE_OUTPUT); + } + + /* Create/Open a C code source output file if asked */ + + if (Gbl_C_OutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_C_SOURCE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the C code source file, text mode */ + + FlOpenFile (ASL_FILE_C_SOURCE_OUTPUT, Filename, "w+"); + + FlPrintFile (ASL_FILE_C_SOURCE_OUTPUT, "/*\n"); + AslCompilerSignon (ASL_FILE_C_SOURCE_OUTPUT); + AslCompilerFileHeader (ASL_FILE_C_SOURCE_OUTPUT); + } + + /* Create/Open a assembly include output file if asked */ + + if (Gbl_AsmIncludeOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_ASM_INCLUDE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the assembly include file, text mode */ + + FlOpenFile (ASL_FILE_ASM_INCLUDE_OUTPUT, Filename, "w+"); + + AslCompilerSignon (ASL_FILE_ASM_INCLUDE_OUTPUT); + AslCompilerFileHeader (ASL_FILE_ASM_INCLUDE_OUTPUT); + } + + /* Create/Open a C include output file if asked */ + + if (Gbl_C_IncludeOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_C_INCLUDE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the C include file, text mode */ + + FlOpenFile (ASL_FILE_C_INCLUDE_OUTPUT, Filename, "w+"); + + FlPrintFile (ASL_FILE_C_INCLUDE_OUTPUT, "/*\n"); + AslCompilerSignon (ASL_FILE_C_INCLUDE_OUTPUT); + AslCompilerFileHeader (ASL_FILE_C_INCLUDE_OUTPUT); + } + + /* Create a namespace output file if asked */ + + if (Gbl_NsOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_NAMESPACE); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the namespace file, text mode */ + + FlOpenFile (ASL_FILE_NAMESPACE_OUTPUT, Filename, "w+"); + + AslCompilerSignon (ASL_FILE_NAMESPACE_OUTPUT); + AslCompilerFileHeader (ASL_FILE_NAMESPACE_OUTPUT); + } + + return (AE_OK); +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: FlParseInputPathname + * + * PARAMETERS: InputFilename - The user-specified ASL source file to be + * compiled + * + * RETURN: Status + * + * DESCRIPTION: Split the input path into a directory and filename part + * 1) Directory part used to open include files + * 2) Filename part used to generate output filenames + * + ******************************************************************************/ + +ACPI_STATUS +FlParseInputPathname ( + char *InputFilename) +{ + char *Substring; + + + if (!InputFilename) + { + return (AE_OK); + } + + /* Get the path to the input filename's directory */ + + Gbl_DirectoryPath = strdup (InputFilename); + if (!Gbl_DirectoryPath) + { + return (AE_NO_MEMORY); + } + + Substring = strrchr (Gbl_DirectoryPath, '\\'); + if (!Substring) + { + Substring = strrchr (Gbl_DirectoryPath, '/'); + if (!Substring) + { + Substring = strrchr (Gbl_DirectoryPath, ':'); + } + } + + if (!Substring) + { + Gbl_DirectoryPath[0] = 0; + if (Gbl_UseDefaultAmlFilename) + { + Gbl_OutputFilenamePrefix = strdup (InputFilename); + } + } + else + { + if (Gbl_UseDefaultAmlFilename) + { + Gbl_OutputFilenamePrefix = strdup (Substring + 1); + } + *(Substring+1) = 0; + } + + return (AE_OK); +} +#endif + + diff --git a/source/compiler/aslfold.c b/source/compiler/aslfold.c new file mode 100644 index 000000000000..c1fd2717bbd9 --- /dev/null +++ b/source/compiler/aslfold.c @@ -0,0 +1,491 @@ + +/****************************************************************************** + * + * Module Name: aslfold - Constant folding + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#include "acdispat.h" +#include "acparser.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslfold") + +/* Local prototypes */ + +static ACPI_STATUS +OpcAmlEvaluationWalk1 ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +OpcAmlEvaluationWalk2 ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +OpcAmlCheckForConstant ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: OpcAmlEvaluationWalk1 + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback for AML execution of constant subtrees + * + ******************************************************************************/ + +static ACPI_STATUS +OpcAmlEvaluationWalk1 ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = Context; + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *OutOp; + + + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + /* Copy child pointer to Arg for compatibility with Interpreter */ + + if (Op->Asl.Child) + { + Op->Common.Value.Arg = Op->Asl.Child; + } + + /* Call AML dispatcher */ + + Status = AcpiDsExecBeginOp (WalkState, &OutOp); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Constant interpretation failed - %s\n", + AcpiFormatException (Status)); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: OpcAmlEvaluationWalk2 + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback for AML execution of constant subtrees + * + ******************************************************************************/ + +static ACPI_STATUS +OpcAmlEvaluationWalk2 ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = Context; + ACPI_STATUS Status; + + + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + /* Copy child pointer to Arg for compatibility with Interpreter */ + + if (Op->Asl.Child) + { + Op->Common.Value.Arg = Op->Asl.Child; + } + + /* Call AML dispatcher */ + + Status = AcpiDsExecEndOp (WalkState); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Constant interpretation failed - %s\n", + AcpiFormatException (Status)); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: OpcAmlCheckForConstant + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Check one Op for a type 3/4/5 AML opcode + * + ******************************************************************************/ + +static ACPI_STATUS +OpcAmlCheckForConstant ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = Context; + + + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ", + Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName); + + if (!(WalkState->OpInfo->Flags & AML_CONSTANT)) + { + /* The opcode is not a Type 3/4/5 opcode */ + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + DbgPrint (ASL_PARSE_OUTPUT, + "**** Valid Target, cannot reduce ****\n"); + } + else + { + DbgPrint (ASL_PARSE_OUTPUT, + "**** Not a Type 3/4/5 opcode ****\n"); + } + + if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL) + { + /* + * We are looking at at normal expression to see if it can be + * reduced. It can't. No error + */ + return (AE_TYPE); + } + + /* + * This is an expression that MUST reduce to a constant, and it + * can't be reduced. This is an error + */ + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, + Op->Asl.ParseOpName); + } + else + { + AslError (ASL_ERROR, ASL_MSG_INVALID_CONSTANT_OP, Op, + Op->Asl.ParseOpName); + } + + return (AE_TYPE); + } + + /* Debug output */ + + DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345"); + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + DbgPrint (ASL_PARSE_OUTPUT, " TARGET"); + } + if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) + { + DbgPrint (ASL_PARSE_OUTPUT, " TERMARG"); + } + DbgPrint (ASL_PARSE_OUTPUT, "\n"); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: OpcAmlConstantWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Reduce an Op and its subtree to a constant if possible + * + ******************************************************************************/ + +ACPI_STATUS +OpcAmlConstantWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState; + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PARSE_OBJECT *RootOp; + ACPI_PARSE_OBJECT *OriginalParentOp; + UINT8 WalkType; + + + /* + * Only interested in subtrees that could possibly contain + * expressions that can be evaluated at this time + */ + if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) || + (Op->Asl.CompileFlags & NODE_IS_TARGET)) + { + return (AE_OK); + } + + /* Set the walk type based on the reduction used for this op */ + + if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) + { + /* Op is a TermArg, constant folding is merely optional */ + + if (!Gbl_FoldConstants) + { + return (AE_CTRL_DEPTH); + } + + WalkType = ACPI_WALK_CONST_OPTIONAL; + } + else + { + /* Op is a DataObject, the expression MUST reduced to a constant */ + + WalkType = ACPI_WALK_CONST_REQUIRED; + } + + /* Create a new walk state */ + + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + return AE_NO_MEMORY; + } + + WalkState->NextOp = NULL; + WalkState->Params = NULL; + WalkState->CallerReturnDesc = &ObjDesc; + WalkState->WalkType = WalkType; + + /* + * Examine the entire subtree -- all nodes must be constants + * or type 3/4/5 opcodes + */ + Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, + OpcAmlCheckForConstant, NULL, WalkState); + + /* + * Did we find an entire subtree that contains all constants and type 3/4/5 + * opcodes? (Only AE_OK or AE_TYPE returned from above) + */ + if (Status == AE_TYPE) + { + /* Subtree cannot be reduced to a constant */ + + if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL) + { + AcpiDsDeleteWalkState (WalkState); + return (AE_OK); + } + + /* Don't descend any further, and use a default "constant" value */ + + Status = AE_CTRL_DEPTH; + } + else + { + /* Subtree can be reduced */ + + /* Allocate a new temporary root for this subtree */ + + RootOp = TrAllocateNode (PARSEOP_INTEGER); + if (!RootOp) + { + return (AE_NO_MEMORY); + } + + RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; + + OriginalParentOp = Op->Common.Parent; + Op->Common.Parent = RootOp; + + /* Hand off the subtree to the AML interpreter */ + + Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, + OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); + Op->Common.Parent = OriginalParentOp; + + /* TBD: we really *should* release the RootOp node */ + + if (ACPI_SUCCESS (Status)) + { + TotalFolds++; + + /* Get the final result */ + + Status = AcpiDsResultPop (&ObjDesc, WalkState); + } + } + + if (ACPI_FAILURE (Status)) + { + /* We could not resolve the subtree for some reason */ + + AslCoreSubsystemError (Op, Status, + "Failure during constant evaluation", FALSE); + AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op, + Op->Asl.ParseOpName); + + /* Set the subtree value to ZERO anyway. Eliminates further errors */ + + Op->Asl.ParseOpcode = PARSEOP_INTEGER; + Op->Common.Value.Integer = 0; + OpcSetOptimalIntegerSize (Op); + } + else + { + AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op, + Op->Asl.ParseOpName); + + /* + * Because we know we executed type 3/4/5 opcodes above, we know that + * the result must be either an Integer, String, or Buffer. + */ + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + Op->Asl.ParseOpcode = PARSEOP_INTEGER; + Op->Common.Value.Integer = ObjDesc->Integer.Value; + OpcSetOptimalIntegerSize (Op); + + DbgPrint (ASL_PARSE_OUTPUT, + "Constant expression reduced to (INTEGER) %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_STRING: + + Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; + Op->Common.AmlOpcode = AML_STRING_OP; + Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1; + Op->Common.Value.String = ObjDesc->String.Pointer; + + DbgPrint (ASL_PARSE_OUTPUT, + "Constant expression reduced to (STRING) %s\n", + Op->Common.Value.String); + + break; + + + case ACPI_TYPE_BUFFER: + + Op->Asl.ParseOpcode = PARSEOP_BUFFER; + Op->Common.AmlOpcode = AML_BUFFER_OP; + Op->Asl.CompileFlags = NODE_AML_PACKAGE; + UtSetParseOpName (Op); + + /* Child node is the buffer length */ + + RootOp = TrAllocateNode (PARSEOP_INTEGER); + + RootOp->Asl.AmlOpcode = AML_DWORD_OP; + RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length; + RootOp->Asl.Parent = Op; + + (void) OpcSetOptimalIntegerSize (RootOp); + + Op->Asl.Child = RootOp; + Op = RootOp; + UtSetParseOpName (Op); + + /* Peer to the child is the raw buffer data */ + + RootOp = TrAllocateNode (PARSEOP_RAW_DATA); + RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; + RootOp->Asl.AmlLength = ObjDesc->Buffer.Length; + RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; + RootOp->Asl.Parent = Op->Asl.Parent; + + Op->Asl.Next = RootOp; + Op = RootOp; + + DbgPrint (ASL_PARSE_OUTPUT, + "Constant expression reduced to (BUFFER) length %X\n", + ObjDesc->Buffer.Length); + break; + + + default: + printf ("Unsupported return type: %s\n", + AcpiUtGetObjectTypeName (ObjDesc)); + break; + } + } + + UtSetParseOpName (Op); + Op->Asl.Child = NULL; + + AcpiDsDeleteWalkState (WalkState); + + return (AE_CTRL_DEPTH); +} + diff --git a/source/compiler/aslglobal.h b/source/compiler/aslglobal.h new file mode 100644 index 000000000000..08b4b6988f80 --- /dev/null +++ b/source/compiler/aslglobal.h @@ -0,0 +1,226 @@ + + +/****************************************************************************** + * + * Module Name: aslglobal.h - Global variable definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ASLGLOBAL_H +#define __ASLGLOBAL_H + + +/* + * Global variables. Defined in aslmain.c only, externed in all other files + */ + +#undef ASL_EXTERN + +#ifdef _DECLARE_GLOBALS +#define ASL_EXTERN +#define ASL_INIT_GLOBAL(a,b) (a)=(b) +#else +#define ASL_EXTERN extern +#define ASL_INIT_GLOBAL(a,b) (a) +#endif + + +/* + * Parser and other externals + */ +extern int yydebug; +extern FILE *AslCompilerin; +extern int AslCompilerdebug; +extern int DtParserdebug; +extern const ASL_MAPPING_ENTRY AslKeywordMapping[]; +extern char *AslCompilertext; + +#define ASL_LINE_BUFFER_SIZE 1024 +#define ASL_MSG_BUFFER_SIZE 4096 +#define HEX_TABLE_LINE_SIZE 8 +#define HEX_LISTING_LINE_SIZE 8 + + +/* Source code buffers and pointers for error reporting */ + +ASL_EXTERN char Gbl_CurrentLineBuffer[ASL_LINE_BUFFER_SIZE]; +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentColumn, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentLineNumber, 1); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_LogicalLineNumber, 1); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentLineOffset, 0); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_LineBufPtr, Gbl_CurrentLineBuffer); + + +/* Exception reporting */ + +ASL_EXTERN ASL_ERROR_MSG ASL_INIT_GLOBAL (*Gbl_ErrorLog,NULL); +ASL_EXTERN ASL_ERROR_MSG ASL_INIT_GLOBAL (*Gbl_NextError,NULL); + + +/* Option flags */ + +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DoCompile, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DoSignon, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisassembleAll, FALSE); + +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_Acpi2, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_UseDefaultAmlFilename, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NsOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DebugFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_AsmOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_C_OutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_AsmIncludeOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_C_IncludeOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_ListingFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_IgnoreErrors, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_SourceOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_ParseOnlyFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_CompileTimesFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_FoldConstants, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_VerboseErrors, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoErrors, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoResourceChecking, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisasmFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_GetAllTables, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_IntegerOptimizationFlag, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_ReferenceOptimizationFlag, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisplayRemarks, TRUE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisplayOptimizations, FALSE); +ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_WarningLevel, ASL_WARNING); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_UseOriginalCompilerId, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_VerboseTemplates, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DoTemplates, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_CompileGeneric, FALSE); + + +#define HEX_OUTPUT_NONE 0 +#define HEX_OUTPUT_C 1 +#define HEX_OUTPUT_ASM 2 +#define HEX_OUTPUT_ASL 3 + +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HexOutputFlag, HEX_OUTPUT_NONE); + + +/* Files */ + +ASL_EXTERN ASL_FILE_INFO Gbl_Files [ASL_NUM_FILES]; + +ASL_EXTERN char *Gbl_DirectoryPath; +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_IncludeFilename, NULL); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_OutputFilenamePrefix, NULL); +ASL_EXTERN ASL_INCLUDE_DIR ASL_INIT_GLOBAL (*Gbl_IncludeDirList, NULL); +ASL_EXTERN char *Gbl_CurrentInputFilename; + +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HasIncludeFiles, FALSE); + + +/* Statistics */ + +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_InputByteCount, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_InputFieldCount, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_NsLookupCount, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalKeywords, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalNamedObjects, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalExecutableOpcodes, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalParseNodes, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalMethods, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalAllocations, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalAllocated, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (TotalFolds, 0); + + +/* Misc */ + +ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_RevisionOverride, 0); +ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_TempCount, 0); +ASL_EXTERN ACPI_PARSE_OBJECT ASL_INIT_GLOBAL (*RootNode, NULL); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_TableLength, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_SourceLine, 0); +ASL_EXTERN ASL_LISTING_NODE ASL_INIT_GLOBAL (*Gbl_ListingNode, NULL); +ASL_EXTERN ACPI_PARSE_OBJECT ASL_INIT_GLOBAL (*Gbl_NodeCacheNext, NULL); +ASL_EXTERN ACPI_PARSE_OBJECT ASL_INIT_GLOBAL (*Gbl_NodeCacheLast, NULL); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_StringCacheNext, NULL); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_StringCacheLast, NULL); +ASL_EXTERN ACPI_PARSE_OBJECT *Gbl_FirstLevelInsertionNode; +ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_FileType, 0); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_Signature, NULL); +ASL_EXTERN char *Gbl_TemplateSignature; + +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentHexColumn, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentAmlOffset, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentLine, 0); +ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_HexBytesWereWritten, FALSE); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_NumNamespaceObjects, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_ReservedMethods, 0); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_TableSignature, "NO_SIG"); +ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_TableId, "NO_ID"); +ASL_EXTERN FILE *AcpiGbl_DebugFile; /* Placeholder for oswinxf only */ + + +/* Static structures */ + +ASL_EXTERN ASL_ANALYSIS_WALK_INFO AnalysisWalkInfo; +ASL_EXTERN ACPI_TABLE_HEADER TableHeader; +extern char AslHexLookup[]; + +/* Event timing */ + +#define ASL_NUM_EVENTS 19 +ASL_EXTERN ASL_EVENT_INFO AslGbl_Events[ASL_NUM_EVENTS]; +ASL_EXTERN UINT8 AslGbl_NextEvent; +ASL_EXTERN UINT8 AslGbl_NamespaceEvent; + +/* Scratch buffers */ + +ASL_EXTERN UINT8 Gbl_AmlBuffer[HEX_LISTING_LINE_SIZE]; +ASL_EXTERN char MsgBuffer[ASL_MSG_BUFFER_SIZE]; +ASL_EXTERN char StringBuffer[ASL_MSG_BUFFER_SIZE]; +ASL_EXTERN char StringBuffer2[ASL_MSG_BUFFER_SIZE]; + + +#ifdef _DECLARE_GLOBALS +UINT32 Gbl_ExceptionCount[ASL_NUM_REPORT_LEVELS] = {0,0,0,0,0,0}; +#else +extern UINT32 Gbl_ExceptionCount[ASL_NUM_REPORT_LEVELS]; +#endif + +#endif /* __ASLGLOBAL_H */ + diff --git a/source/compiler/asllength.c b/source/compiler/asllength.c new file mode 100644 index 000000000000..ed88de9847fd --- /dev/null +++ b/source/compiler/asllength.c @@ -0,0 +1,458 @@ + +/****************************************************************************** + * + * Module Name: asllength - Tree walk to determine package and opcode lengths + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asllength") + +/* Local prototypes */ + +static UINT8 +CgGetPackageLenByteCount ( + ACPI_PARSE_OBJECT *Op, + UINT32 PackageLength); + +static void +CgGenerateAmlOpcodeLength ( + ACPI_PARSE_OBJECT *Op); + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +void +LnAdjustLengthToRoot ( + ACPI_PARSE_OBJECT *Op, + UINT32 LengthDelta); +#endif + + +/******************************************************************************* + * + * FUNCTION: LnInitLengthsWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Walk callback to initialize (and re-initialize) the node + * subtree length(s) to zero. The Subtree lengths are bubbled + * up to the root node in order to get a total AML length. + * + ******************************************************************************/ + +ACPI_STATUS +LnInitLengthsWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + Op->Asl.AmlSubtreeLength = 0; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LnPackageLengthWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Walk callback to calculate the total AML length. + * 1) Calculate the AML lengths (opcode, package length, etc.) for + * THIS node. + * 2) Bubbble up all of these lengths to the parent node by summing + * them all into the parent subtree length. + * + * Note: The SubtreeLength represents the total AML length of all child nodes + * in all subtrees under a given node. Therefore, once this walk is + * complete, the Root Node subtree length is the AML length of the entire + * tree (and thus, the entire ACPI table) + * + ******************************************************************************/ + +ACPI_STATUS +LnPackageLengthWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + /* Generate the AML lengths for this node */ + + CgGenerateAmlLengths (Op); + + /* Bubble up all lengths (this node and all below it) to the parent */ + + if ((Op->Asl.Parent) && + (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) + { + Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength + + Op->Asl.AmlOpcodeLength + + Op->Asl.AmlPkgLenBytes + + Op->Asl.AmlSubtreeLength); + } + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: CgGetPackageLenByteCount + * + * PARAMETERS: Op - Parse node + * PackageLength - Length to be encoded + * + * RETURN: Required length of the package length encoding + * + * DESCRIPTION: Calculate the number of bytes required to encode the given + * package length. + * + ******************************************************************************/ + +static UINT8 +CgGetPackageLenByteCount ( + ACPI_PARSE_OBJECT *Op, + UINT32 PackageLength) +{ + + /* + * Determine the number of bytes required to encode the package length + * Note: the package length includes the number of bytes used to encode + * the package length, so we must account for this also. + */ + if (PackageLength <= (0x0000003F - 1)) + { + return (1); + } + else if (PackageLength <= (0x00000FFF - 2)) + { + return (2); + } + else if (PackageLength <= (0x000FFFFF - 3)) + { + return (3); + } + else if (PackageLength <= (0x0FFFFFFF - 4)) + { + return (4); + } + else + { + /* Fatal error - the package length is too large to encode */ + + AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL); + } + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: CgGenerateAmlOpcodeLength + * + * PARAMETERS: Op - Parse node whose AML opcode lengths will be + * calculated + * + * RETURN: None. + * + * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength + * fields for this node. + * + ******************************************************************************/ + +static void +CgGenerateAmlOpcodeLength ( + ACPI_PARSE_OBJECT *Op) +{ + + /* Check for two-byte opcode */ + + if (Op->Asl.AmlOpcode > 0x00FF) + { + Op->Asl.AmlOpcodeLength = 2; + } + else + { + Op->Asl.AmlOpcodeLength = 1; + } + + /* Does this opcode have an associated "PackageLength" field? */ + + Op->Asl.AmlPkgLenBytes = 0; + if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) + { + Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount ( + Op, Op->Asl.AmlSubtreeLength); + } + + /* Data opcode lengths are easy */ + + switch (Op->Asl.AmlOpcode) + { + case AML_BYTE_OP: + + Op->Asl.AmlLength = 1; + break; + + case AML_WORD_OP: + + Op->Asl.AmlLength = 2; + break; + + case AML_DWORD_OP: + + Op->Asl.AmlLength = 4; + break; + + case AML_QWORD_OP: + + Op->Asl.AmlLength = 8; + break; + + default: + /* All data opcodes must be above */ + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: CgGenerateAmlLengths + * + * PARAMETERS: Op - Parse node + * + * RETURN: None. + * + * DESCRIPTION: Generate internal length fields based on the AML opcode or + * parse opcode. + * + ******************************************************************************/ + +void +CgGenerateAmlLengths ( + ACPI_PARSE_OBJECT *Op) +{ + char *Buffer; + ACPI_STATUS Status; + + + switch (Op->Asl.AmlOpcode) + { + case AML_RAW_DATA_BYTE: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlLength = 1; + return; + + case AML_RAW_DATA_WORD: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlLength = 2; + return; + + case AML_RAW_DATA_DWORD: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlLength = 4; + return; + + case AML_RAW_DATA_QWORD: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlLength = 8; + return; + + case AML_RAW_DATA_BUFFER: + + /* Aml length is/was set by creator */ + + Op->Asl.AmlOpcodeLength = 0; + return; + + case AML_RAW_DATA_CHAIN: + + /* Aml length is/was set by creator */ + + Op->Asl.AmlOpcodeLength = 0; + return; + + default: + break; + } + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + + Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + + Op->Asl.AmlSubtreeLength; + break; + + case PARSEOP_NAMESEG: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlLength = 4; + Op->Asl.ExternalName = Op->Asl.Value.String; + break; + + case PARSEOP_NAMESTRING: + case PARSEOP_METHODCALL: + + if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED) + { + break; + } + + Op->Asl.AmlOpcodeLength = 0; + Status = UtInternalizeName (Op->Asl.Value.String, &Buffer); + if (ACPI_FAILURE (Status)) + { + DbgPrint (ASL_DEBUG_OUTPUT, + "Failure from internalize name %X\n", Status); + break; + } + + Op->Asl.ExternalName = Op->Asl.Value.String; + Op->Asl.Value.String = Buffer; + Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED; + + Op->Asl.AmlLength = strlen (Buffer); + + /* + * Check for single backslash reference to root, + * make it a null terminated string in the AML + */ + if (Op->Asl.AmlLength == 1) + { + Op->Asl.AmlLength = 2; + } + break; + + case PARSEOP_STRING_LITERAL: + + Op->Asl.AmlOpcodeLength = 1; + + /* Get null terminator */ + + Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1; + break; + + case PARSEOP_PACKAGE_LENGTH: + + Op->Asl.AmlOpcodeLength = 0; + Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op, + (UINT32) Op->Asl.Value.Integer); + break; + + case PARSEOP_RAW_DATA: + + Op->Asl.AmlOpcodeLength = 0; + break; + + case PARSEOP_DEFAULT_ARG: + case PARSEOP_EXTERNAL: + case PARSEOP_INCLUDE: + case PARSEOP_INCLUDE_END: + + /* Ignore the "default arg" nodes, they are extraneous at this point */ + + break; + + default: + + CgGenerateAmlOpcodeLength (Op); + break; + } +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: LnAdjustLengthToRoot + * + * PARAMETERS: Op - Node whose Length was changed + * + * RETURN: None. + * + * DESCRIPTION: Change the Subtree length of the given node, and bubble the + * change all the way up to the root node. This allows for + * last second changes to a package length (for example, if the + * package length encoding gets shorter or longer.) + * + ******************************************************************************/ + +void +LnAdjustLengthToRoot ( + ACPI_PARSE_OBJECT *SubtreeOp, + UINT32 LengthDelta) +{ + ACPI_PARSE_OBJECT *Op; + + + /* Adjust all subtree lengths up to the root */ + + Op = SubtreeOp->Asl.Parent; + while (Op) + { + Op->Asl.AmlSubtreeLength -= LengthDelta; + Op = Op->Asl.Parent; + } + + /* Adjust the global table length */ + + Gbl_TableLength -= LengthDelta; +} +#endif + + diff --git a/source/compiler/asllisting.c b/source/compiler/asllisting.c new file mode 100644 index 000000000000..c865df6d0f1d --- /dev/null +++ b/source/compiler/asllisting.c @@ -0,0 +1,1542 @@ + +/****************************************************************************** + * + * Module Name: asllisting - Listing file generation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" +#include "acparser.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslisting") + +/* Local prototypes */ + +static void +LsDumpAscii ( + UINT32 FileId, + UINT32 Count, + UINT8 *Buffer); + +static void +LsDumpAsciiInComment ( + UINT32 FileId, + UINT32 Count, + UINT8 *Buffer); + +static ACPI_STATUS +LsAmlListingWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static void +LsGenerateListing ( + UINT32 FileId); + +static void +LsPushNode ( + char *Filename); + +static ASL_LISTING_NODE * +LsPopNode ( + void); + +static void +LsCheckException ( + UINT32 LineNumber, + UINT32 FileId); + +static void +LsFlushListingBuffer ( + UINT32 FileId); + +static void +LsWriteListingHexBytes ( + UINT8 *Buffer, + UINT32 Length, + UINT32 FileId); + +static UINT32 +LsWriteOneSourceLine ( + UINT32 FileId); + +static void +LsFinishSourceListing ( + UINT32 FileId); + +static void +LsWriteSourceLines ( + UINT32 ToLineNumber, + UINT32 ToLogicalLineNumber, + UINT32 FileId); + +static void +LsWriteNodeToListing ( + ACPI_PARSE_OBJECT *Op, + UINT32 FileId); + +static void +LsDoHexOutputC ( + void); + +static void +LsDoHexOutputAsm ( + void); + +static void +LsDoHexOutputAsl ( + void); + +static ACPI_STATUS +LsTreeWriteWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: LsTreeWriteWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * + * RETURN: None. + * + * DESCRIPTION: Dump entire parse tree, for compiler debug only + * + ******************************************************************************/ + +static ACPI_STATUS +LsTreeWriteWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + /* Debug output */ + + DbgPrint (ASL_TREE_OUTPUT, + "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level); + UtPrintFormattedName (Op->Asl.ParseOpcode, Level); + + + DbgPrint (ASL_TREE_OUTPUT, "\n"); + return (AE_OK); +} + + +void +LsDumpParseTree ( + void) +{ + + if (!Gbl_DebugFlag) + { + return; + } + + DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, + LsTreeWriteWalk, NULL, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: LsDumpAscii + * + * PARAMETERS: FileId - ID of current listing file + * Count - Number of bytes to convert + * Buffer - Buffer of bytes to convert + * + * RETURN: None. + * + * DESCRIPTION: Convert hex bytes to ascii + * + ******************************************************************************/ + +static void +LsDumpAscii ( + UINT32 FileId, + UINT32 Count, + UINT8 *Buffer) +{ + UINT8 BufChar; + UINT32 i; + + + FlPrintFile (FileId, " \""); + for (i = 0; i < Count; i++) + { + BufChar = Buffer[i]; + if (isprint (BufChar)) + { + FlPrintFile (FileId, "%c", BufChar); + } + else + { + /* Not a printable character, just put out a dot */ + + FlPrintFile (FileId, "."); + } + } + FlPrintFile (FileId, "\""); +} + + +/******************************************************************************* + * + * FUNCTION: LsDumpAsciiInComment + * + * PARAMETERS: FileId - ID of current listing file + * Count - Number of bytes to convert + * Buffer - Buffer of bytes to convert + * + * RETURN: None. + * + * DESCRIPTION: Convert hex bytes to ascii + * + ******************************************************************************/ + +static void +LsDumpAsciiInComment ( + UINT32 FileId, + UINT32 Count, + UINT8 *Buffer) +{ + UINT8 BufChar = 0; + UINT8 LastChar; + UINT32 i; + + + FlPrintFile (FileId, " \""); + for (i = 0; i < Count; i++) + { + LastChar = BufChar; + BufChar = Buffer[i]; + + if (isprint (BufChar)) + { + /* Handle embedded C comment sequences */ + + if (((LastChar == '*') && (BufChar == '/')) || + ((LastChar == '/') && (BufChar == '*'))) + { + /* Insert a space to break the sequence */ + + FlPrintFile (FileId, ".", BufChar); + } + + FlPrintFile (FileId, "%c", BufChar); + } + else + { + /* Not a printable character, just put out a dot */ + + FlPrintFile (FileId, "."); + } + } + FlPrintFile (FileId, "\""); +} + + +/******************************************************************************* + * + * FUNCTION: LsAmlListingWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Process one node during a listing file generation. + * + ******************************************************************************/ + +static ACPI_STATUS +LsAmlListingWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + UINT8 FileByte; + UINT32 i; + UINT32 FileId = (UINT32) ACPI_TO_INTEGER (Context); + + + LsWriteNodeToListing (Op, FileId); + + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA) + { + /* Buffer is a resource template, don't dump the data all at once */ + + return (AE_OK); + } + + /* Write the hex bytes to the listing file(s) (if requested) */ + + for (i = 0; i < Op->Asl.FinalAmlLength; i++) + { + if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1))) + { + FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ); + AslAbort (); + } + LsWriteListingHexBytes (&FileByte, 1, FileId); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LsGenerateListing + * + * PARAMETERS: FileId - ID of listing file + * + * RETURN: None + * + * DESCRIPTION: Generate a listing file. This can be one of the several types + * of "listings" supported. + * + ******************************************************************************/ + +static void +LsGenerateListing ( + UINT32 FileId) +{ + + /* Start at the beginning of both the source and AML files */ + + FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + Gbl_SourceLine = 0; + Gbl_CurrentHexColumn = 0; + LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename); + + /* Process all parse nodes */ + + TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk, + NULL, (void *) ACPI_TO_POINTER (FileId)); + + /* Final processing */ + + LsFinishSourceListing (FileId); +} + + +/******************************************************************************* + * + * FUNCTION: LsDoListings + * + * PARAMETERS: None. + * + * RETURN: None + * + * DESCRIPTION: Generate all requested listing files. + * + ******************************************************************************/ + +void +LsDoListings ( + void) +{ + + if (Gbl_C_OutputFlag) + { + LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT); + } + + if (Gbl_ListingFlag) + { + LsGenerateListing (ASL_FILE_LISTING_OUTPUT); + } + + if (Gbl_AsmOutputFlag) + { + LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT); + } + + if (Gbl_C_IncludeOutputFlag) + { + LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT); + } + + if (Gbl_AsmIncludeOutputFlag) + { + LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT); + } +} + + +/******************************************************************************* + * + * FUNCTION: LsPushNode + * + * PARAMETERS: Filename - Pointer to the include filename + * + * RETURN: None + * + * DESCRIPTION: Push a listing node on the listing/include file stack. This + * stack enables tracking of include files (infinitely nested) + * and resumption of the listing of the parent file when the + * include file is finished. + * + ******************************************************************************/ + +static void +LsPushNode ( + char *Filename) +{ + ASL_LISTING_NODE *Lnode; + + + /* Create a new node */ + + Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE)); + + /* Initialize */ + + Lnode->Filename = Filename; + Lnode->LineNumber = 0; + + /* Link (push) */ + + Lnode->Next = Gbl_ListingNode; + Gbl_ListingNode = Lnode; +} + + +/******************************************************************************* + * + * FUNCTION: LsPopNode + * + * PARAMETERS: None + * + * RETURN: List head after current head is popped off + * + * DESCRIPTION: Pop the current head of the list, free it, and return the + * next node on the stack (the new current node). + * + ******************************************************************************/ + +static ASL_LISTING_NODE * +LsPopNode ( + void) +{ + ASL_LISTING_NODE *Lnode; + + + /* Just grab the node at the head of the list */ + + Lnode = Gbl_ListingNode; + if ((!Lnode) || + (!Lnode->Next)) + { + AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL, + "Could not pop empty listing stack"); + return Gbl_ListingNode; + } + + Gbl_ListingNode = Lnode->Next; + ACPI_FREE (Lnode); + + /* New "Current" node is the new head */ + + return (Gbl_ListingNode); +} + + +/******************************************************************************* + * + * FUNCTION: LsCheckException + * + * PARAMETERS: LineNumber - Current logical (cumulative) line # + * FileId - ID of output listing file + * + * RETURN: None + * + * DESCRIPTION: Check if there is an exception for this line, and if there is, + * put it in the listing immediately. Handles multiple errors + * per line. Gbl_NextError points to the next error in the + * sorted (by line #) list of compile errors/warnings. + * + ******************************************************************************/ + +static void +LsCheckException ( + UINT32 LineNumber, + UINT32 FileId) +{ + + if ((!Gbl_NextError) || + (LineNumber < Gbl_NextError->LogicalLineNumber )) + { + return; + } + + /* Handle multiple errors per line */ + + if (FileId == ASL_FILE_LISTING_OUTPUT) + { + while (Gbl_NextError && + (LineNumber >= Gbl_NextError->LogicalLineNumber)) + { + AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n"); + + Gbl_NextError = Gbl_NextError->Next; + } + + FlPrintFile (FileId, "\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: LsFlushListingBuffer + * + * PARAMETERS: FileId - ID of the listing file + * + * RETURN: None + * + * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code + * buffer. Usually called at the termination of a single line + * of source code or when the buffer is full. + * + ******************************************************************************/ + +static void +LsFlushListingBuffer ( + UINT32 FileId) +{ + UINT32 i; + + + if (Gbl_CurrentHexColumn == 0) + { + return; + } + + /* Write the hex bytes */ + + switch (FileId) + { + case ASL_FILE_LISTING_OUTPUT: + + for (i = 0; i < Gbl_CurrentHexColumn; i++) + { + FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]); + } + + for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++) + { + FlWriteFile (FileId, ".", 1); + } + + /* Write the ASCII character associated with each of the bytes */ + + LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); + break; + + + case ASL_FILE_ASM_SOURCE_OUTPUT: + + for (i = 0; i < Gbl_CurrentHexColumn; i++) + { + if (i > 0) + { + FlPrintFile (FileId, ","); + } + FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]); + } + + for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) + { + FlWriteFile (FileId, " ", 1); + } + + FlPrintFile (FileId, " ;%8.8X", + Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); + + /* Write the ASCII character associated with each of the bytes */ + + LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); + break; + + + case ASL_FILE_C_SOURCE_OUTPUT: + + for (i = 0; i < Gbl_CurrentHexColumn; i++) + { + FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]); + } + + for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) + { + FlWriteFile (FileId, " ", 1); + } + + FlPrintFile (FileId, " /* %8.8X", + Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); + + /* Write the ASCII character associated with each of the bytes */ + + LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); + FlPrintFile (FileId, " */"); + break; + + default: + /* No other types supported */ + return; + } + + FlPrintFile (FileId, "\n"); + + Gbl_CurrentHexColumn = 0; + Gbl_HexBytesWereWritten = TRUE; +} + + +/******************************************************************************* + * + * FUNCTION: LsWriteListingHexBytes + * + * PARAMETERS: Buffer - AML code buffer + * Length - Number of AML bytes to write + * FileId - ID of current listing file. + * + * RETURN: None + * + * DESCRIPTION: Write the contents of the AML buffer to the listing file via + * the listing buffer. The listing buffer is flushed every 16 + * AML bytes. + * + ******************************************************************************/ + +static void +LsWriteListingHexBytes ( + UINT8 *Buffer, + UINT32 Length, + UINT32 FileId) +{ + UINT32 i; + + + /* Transfer all requested bytes */ + + for (i = 0; i < Length; i++) + { + /* Print line header when buffer is empty */ + + if (Gbl_CurrentHexColumn == 0) + { + if (Gbl_HasIncludeFiles) + { + FlPrintFile (FileId, "%*s", 10, " "); + } + + switch (FileId) + { + case ASL_FILE_LISTING_OUTPUT: + + FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset); + break; + + case ASL_FILE_ASM_SOURCE_OUTPUT: + + FlPrintFile (FileId, " db "); + break; + + case ASL_FILE_C_SOURCE_OUTPUT: + + FlPrintFile (FileId, " "); + break; + + default: + /* No other types supported */ + return; + } + } + + /* Transfer AML byte and update counts */ + + Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i]; + + Gbl_CurrentHexColumn++; + Gbl_CurrentAmlOffset++; + + /* Flush buffer when it is full */ + + if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE) + { + LsFlushListingBuffer (FileId); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: LsWriteOneSourceLine + * + * PARAMETERS: FileID - ID of current listing file + * + * RETURN: FALSE on EOF (input source file), TRUE otherwise + * + * DESCRIPTION: Read one line from the input source file and echo it to the + * listing file, prefixed with the line number, and if the source + * file contains include files, prefixed with the current filename + * + ******************************************************************************/ + +static UINT32 +LsWriteOneSourceLine ( + UINT32 FileId) +{ + UINT8 FileByte; + + + Gbl_SourceLine++; + Gbl_ListingNode->LineNumber++; + + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, " *"); + } + if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) + { + FlPrintFile (FileId, "; "); + } + + if (Gbl_HasIncludeFiles) + { + /* + * This file contains "include" statements, print the current + * filename and line number within the current file + */ + FlPrintFile (FileId, "%12s %5d....", + Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber); + } + else + { + /* No include files, just print the line number */ + + FlPrintFile (FileId, "%8d....", Gbl_SourceLine); + } + + /* Read one line (up to a newline or EOF) */ + + while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK) + { + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + if (FileByte == '/') + { + FileByte = '*'; + } + } + + FlWriteFile (FileId, &FileByte, 1); + if (FileByte == '\n') + { + /* + * Check if an error occurred on this source line during the compile. + * If so, we print the error message after the source line. + */ + LsCheckException (Gbl_SourceLine, FileId); + return (1); + } + } + + /* EOF on the input file was reached */ + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: LsFinishSourceListing + * + * PARAMETERS: FileId - ID of current listing file. + * + * RETURN: None + * + * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML + * listing buffer, and flush out any remaining lines in the + * source input file. + * + ******************************************************************************/ + +static void +LsFinishSourceListing ( + UINT32 FileId) +{ + + if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || + (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) + { + return; + } + + LsFlushListingBuffer (FileId); + Gbl_CurrentAmlOffset = 0; + + /* Flush any remaining text in the source file */ + + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, " /*\n"); + } + + while (LsWriteOneSourceLine (FileId)) + { ; } + + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, "\n */\n };\n"); + } + + FlPrintFile (FileId, "\n"); + + if (FileId == ASL_FILE_LISTING_OUTPUT) + { + /* Print a summary of the compile exceptions */ + + FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n"); + AePrintErrorLog (FileId); + FlPrintFile (FileId, "\n"); + UtDisplaySummary (FileId); + FlPrintFile (FileId, "\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: LsWriteSourceLines + * + * PARAMETERS: ToLineNumber - + * ToLogicalLineNumber - Write up to this source line number + * FileId - ID of current listing file + * + * RETURN: None + * + * DESCRIPTION: Read then write source lines to the listing file until we have + * reached the specified logical (cumulative) line number. This + * automatically echos out comment blocks and other non-AML + * generating text until we get to the actual AML-generating line + * of ASL code specified by the logical line number. + * + ******************************************************************************/ + +static void +LsWriteSourceLines ( + UINT32 ToLineNumber, + UINT32 ToLogicalLineNumber, + UINT32 FileId) +{ + + if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || + (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) + { + return; + } + + Gbl_CurrentLine = ToLogicalLineNumber; + + /* Flush any hex bytes remaining from the last opcode */ + + LsFlushListingBuffer (FileId); + + /* Read lines and write them as long as we are not caught up */ + + if (Gbl_SourceLine < Gbl_CurrentLine) + { + /* + * If we just completed writing some AML hex bytes, output a linefeed + * to add some whitespace for readability. + */ + if (Gbl_HexBytesWereWritten) + { + FlPrintFile (FileId, "\n"); + Gbl_HexBytesWereWritten = FALSE; + } + + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, " /*\n"); + } + + /* Write one line at a time until we have reached the target line # */ + + while ((Gbl_SourceLine < Gbl_CurrentLine) && + LsWriteOneSourceLine (FileId)) + { ; } + + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, " */"); + } + FlPrintFile (FileId, "\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: LsWriteNodeToListing + * + * PARAMETERS: Op - Parse node to write to the listing file. + * FileId - ID of current listing file + * + * RETURN: None. + * + * DESCRIPTION: Write "a node" to the listing file. This means to + * 1) Write out all of the source text associated with the node + * 2) Write out all of the AML bytes associated with the node + * 3) Write any compiler exceptions associated with the node + * + ******************************************************************************/ + +static void +LsWriteNodeToListing ( + ACPI_PARSE_OBJECT *Op, + UINT32 FileId) +{ + const ACPI_OPCODE_INFO *OpInfo; + UINT32 OpClass; + char *Pathname; + UINT32 Length; + UINT32 i; + + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + OpClass = OpInfo->Class; + + /* TBD: clean this up with a single flag that says: + * I start a named output block + */ + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + case PARSEOP_METHODCALL: + case PARSEOP_INCLUDE: + case PARSEOP_INCLUDE_END: + case PARSEOP_DEFAULT_ARG: + + break; + + default: + switch (OpClass) + { + case AML_CLASS_NAMED_OBJECT: + switch (Op->Asl.AmlOpcode) + { + case AML_SCOPE_OP: + case AML_ALIAS_OP: + break; + + default: + if (Op->Asl.ExternalName) + { + LsFlushListingBuffer (FileId); + FlPrintFile (FileId, " };\n"); + } + break; + } + break; + + default: + /* Don't care about other objects */ + break; + } + break; + } + } + + /* These cases do not have a corresponding AML opcode */ + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + + LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId); + + /* Use the table Signature and TableId to build a unique name */ + + if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) + { + FlPrintFile (FileId, + "%s_%s_Header \\\n", + Gbl_TableSignature, Gbl_TableId); + } + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, + " unsigned char %s_%s_Header [] =\n {\n", + Gbl_TableSignature, Gbl_TableId); + } + if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) + { + FlPrintFile (FileId, + "extrn %s_%s_Header : byte\n", + Gbl_TableSignature, Gbl_TableId); + } + if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) + { + FlPrintFile (FileId, + "extern unsigned char %s_%s_Header [];\n", + Gbl_TableSignature, Gbl_TableId); + } + return; + + + case PARSEOP_METHODCALL: + + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + return; + + + case PARSEOP_INCLUDE: + + /* Flush everything up to and including the include source line */ + + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + + /* Create a new listing node and push it */ + + LsPushNode (Op->Asl.Child->Asl.Value.String); + return; + + + case PARSEOP_INCLUDE_END: + + /* Flush out the rest of the include file */ + + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + + /* Pop off this listing node and go back to the parent file */ + + (void) LsPopNode (); + return; + + + case PARSEOP_DEFAULT_ARG: + + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) + { + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine, + FileId); + } + return; + + + default: + /* All other opcodes have an AML opcode */ + break; + } + + /* + * Otherwise, we look at the AML opcode because we can + * switch on the opcode type, getting an entire class + * at once + */ + switch (OpClass) + { + case AML_CLASS_ARGUMENT: /* argument type only */ + case AML_CLASS_INTERNAL: + + break; + + + case AML_CLASS_NAMED_OBJECT: + + switch (Op->Asl.AmlOpcode) + { + case AML_FIELD_OP: + case AML_INDEX_FIELD_OP: + case AML_BANK_FIELD_OP: + + /* + * For fields, we want to dump all the AML after the + * entire definition + */ + LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, + FileId); + break; + + case AML_NAME_OP: + + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) + { + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + } + else + { + /* + * For fields, we want to dump all the AML after the + * entire definition + */ + LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, + FileId); + } + break; + + default: + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + break; + } + + switch (Op->Asl.AmlOpcode) + { + case AML_SCOPE_OP: + case AML_ALIAS_OP: + + /* These opcodes do not declare a new object, ignore them */ + + break; + + default: + + /* All other named object opcodes come here */ + + switch (FileId) + { + case ASL_FILE_ASM_SOURCE_OUTPUT: + case ASL_FILE_C_SOURCE_OUTPUT: + case ASL_FILE_ASM_INCLUDE_OUTPUT: + case ASL_FILE_C_INCLUDE_OUTPUT: + + /* + * For named objects, we will create a valid symbol so that the + * AML code can be referenced from C or ASM + */ + if (Op->Asl.ExternalName) + { + /* Get the full pathname associated with this node */ + + Pathname = AcpiNsGetExternalPathname (Op->Asl.Node); + Length = strlen (Pathname); + if (Length >= 4) + { + /* Convert all dots in the path to underscores */ + + for (i = 0; i < Length; i++) + { + if (Pathname[i] == '.') + { + Pathname[i] = '_'; + } + } + + /* Create the appropriate symbol in the output file */ + + if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) + { + FlPrintFile (FileId, + "%s_%s_%s \\\n", + Gbl_TableSignature, Gbl_TableId, &Pathname[1]); + } + if (FileId == ASL_FILE_C_SOURCE_OUTPUT) + { + FlPrintFile (FileId, + " unsigned char %s_%s_%s [] =\n {\n", + Gbl_TableSignature, Gbl_TableId, &Pathname[1]); + } + if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) + { + FlPrintFile (FileId, + "extrn %s_%s_%s : byte\n", + Gbl_TableSignature, Gbl_TableId, &Pathname[1]); + } + if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) + { + FlPrintFile (FileId, + "extern unsigned char %s_%s_%s [];\n", + Gbl_TableSignature, Gbl_TableId, &Pathname[1]); + } + } + ACPI_FREE (Pathname); + } + break; + + default: + /* Nothing to do for listing file */ + break; + } + } + break; + + case AML_CLASS_EXECUTE: + case AML_CLASS_CREATE: + default: + + if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) && + (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)) + { + return; + } + + LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, + FileId); + break; + + case AML_CLASS_UNKNOWN: + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: LsDoHexOutput + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create the hex output file. + * + ******************************************************************************/ + +void +LsDoHexOutput ( + void) +{ + + switch (Gbl_HexOutputFlag) + { + case HEX_OUTPUT_C: + + LsDoHexOutputC (); + break; + + case HEX_OUTPUT_ASM: + + LsDoHexOutputAsm (); + break; + + case HEX_OUTPUT_ASL: + + LsDoHexOutputAsl (); + break; + + default: + /* No other output types supported */ + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: LsDoHexOutputC + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create the hex output file. This is the same data as the AML + * output file, but formatted into hex/ascii bytes suitable for + * inclusion into a C source file. + * + ******************************************************************************/ + +static void +LsDoHexOutputC ( + void) +{ + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; + UINT32 Offset = 0; + UINT32 AmlFileSize; + UINT32 i; + + + /* Get AML size, seek back to start */ + + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", + AmlFileSize); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n"); + + while (Offset < AmlFileSize) + { + /* Read enough bytes needed for one output line */ + + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) + { + break; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + + for (i = 0; i < LineLength; i++) + { + /* + * Print each hex byte. + * Add a comma until the very last byte of the AML file + * (Some C compilers complain about a trailing comma) + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); + if ((Offset + i + 1) < AmlFileSize) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } + else + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + } + } + + /* Add fill spaces if needed for last line */ + + if (LineLength < HEX_TABLE_LINE_SIZE) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); + } + + /* Emit the offset and ascii dump for the entire line */ + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", + HEX_TABLE_LINE_SIZE - LineLength + 1, " "); + + Offset += LineLength; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n"); +} + + +/******************************************************************************* + * + * FUNCTION: LsDoHexOutputAsl + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create the hex output file. This is the same data as the AML + * output file, but formatted into hex/ascii bytes suitable for + * inclusion into a C source file. + * + ******************************************************************************/ + +static void +LsDoHexOutputAsl ( + void) +{ + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; + UINT32 Offset = 0; + UINT32 AmlFileSize; + UINT32 i; + + + /* Get AML size, seek back to start */ + + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", + AmlFileSize); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n"); + + while (Offset < AmlFileSize) + { + /* Read enough bytes needed for one output line */ + + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) + { + break; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + + for (i = 0; i < LineLength; i++) + { + /* + * Print each hex byte. + * Add a comma until the very last byte of the AML file + * (Some C compilers complain about a trailing comma) + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); + if ((Offset + i + 1) < AmlFileSize) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } + else + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + } + } + + /* Add fill spaces if needed for last line */ + + if (LineLength < HEX_TABLE_LINE_SIZE) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); + } + + /* Emit the offset and ascii dump for the entire line */ + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", + HEX_TABLE_LINE_SIZE - LineLength + 1, " "); + + Offset += LineLength; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n"); +} + + +/******************************************************************************* + * + * FUNCTION: LsDoHexOutputAsm + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create the hex output file. This is the same data as the AML + * output file, but formatted into hex/ascii bytes suitable for + * inclusion into a ASM source file. + * + ******************************************************************************/ + +static void +LsDoHexOutputAsm ( + void) +{ + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; + UINT32 Offset = 0; + UINT32 AmlFileSize; + UINT32 i; + + + /* Get AML size, seek back to start */ + + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + + FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n", + AmlFileSize); + + while (Offset < AmlFileSize) + { + /* Read enough bytes needed for one output line */ + + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) + { + break; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " db "); + + for (i = 0; i < LineLength; i++) + { + /* + * Print each hex byte. + * Add a comma until the last byte of the line + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]); + if ((i + 1) < LineLength) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + + /* Add fill spaces if needed for last line */ + + if (LineLength < HEX_TABLE_LINE_SIZE) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); + } + + /* Emit the offset and ascii dump for the entire line */ + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); + + Offset += LineLength; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); +} + + diff --git a/source/compiler/aslload.c b/source/compiler/aslload.c new file mode 100644 index 000000000000..c3a0d644f4b1 --- /dev/null +++ b/source/compiler/aslload.c @@ -0,0 +1,898 @@ +/****************************************************************************** + * + * Module Name: dswload - Dispatcher namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __ASLLOAD_C__ + +#include "aslcompiler.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" + +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslload") + +/* Local prototypes */ + +static ACPI_STATUS +LdLoadFieldElements ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +LdLoadResourceElements ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +LdNamespace1Begin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +LdNamespace2Begin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +LdCommonNamespaceEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: LdLoadNamespace + * + * PARAMETERS: RootOp - Root of the parse tree + * + * RETURN: Status + * + * DESCRIPTION: Perform a walk of the parse tree that in turn loads all of the + * named ASL/AML objects into the namespace. The namespace is + * constructed in order to resolve named references and references + * to named fields within resource templates/descriptors. + * + ******************************************************************************/ + +ACPI_STATUS +LdLoadNamespace ( + ACPI_PARSE_OBJECT *RootOp) +{ + ACPI_WALK_STATE *WalkState; + + + DbgPrint (ASL_DEBUG_OUTPUT, "\nCreating namespace\n\n"); + + /* Create a new walk state */ + + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + return AE_NO_MEMORY; + } + + /* Walk the entire parse tree, first pass */ + + TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace1Begin, + LdCommonNamespaceEnd, WalkState); + + /* Second pass to handle forward references */ + + TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace2Begin, + LdCommonNamespaceEnd, WalkState); + + /* Dump the namespace if debug is enabled */ + + AcpiNsDumpTables (ACPI_NS_ALL, ACPI_UINT32_MAX); + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: LdLoadFieldElements + * + * PARAMETERS: Op - Parent node (Field) + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Enter the named elements of the field (children of the parent) + * into the namespace. + * + ******************************************************************************/ + +static ACPI_STATUS +LdLoadFieldElements ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *Child = NULL; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Get the first named field element */ + + switch (Op->Asl.AmlOpcode) + { + case AML_BANK_FIELD_OP: + + Child = UtGetArg (Op, 6); + break; + + case AML_INDEX_FIELD_OP: + + Child = UtGetArg (Op, 5); + break; + + case AML_FIELD_OP: + + Child = UtGetArg (Op, 4); + break; + + default: + /* No other opcodes should arrive here */ + return (AE_BAD_PARAMETER); + } + + /* Enter all elements into the namespace */ + + while (Child) + { + switch (Child->Asl.AmlOpcode) + { + case AML_INT_RESERVEDFIELD_OP: + case AML_INT_ACCESSFIELD_OP: + case AML_INT_CONNECTION_OP: + break; + + default: + + Status = AcpiNsLookup (WalkState->ScopeInfo, + Child->Asl.Value.String, + ACPI_TYPE_LOCAL_REGION_FIELD, + ACPI_IMODE_LOAD_PASS1, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND, + NULL, &Node); + if (ACPI_FAILURE (Status)) + { + if (Status != AE_ALREADY_EXISTS) + { + AslError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Child, + Child->Asl.Value.String); + return (Status); + } + + /* + * The name already exists in this scope + * But continue processing the elements + */ + AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Child, + Child->Asl.Value.String); + } + else + { + Child->Asl.Node = Node; + Node->Op = Child; + } + break; + } + + Child = Child->Asl.Next; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LdLoadResourceElements + * + * PARAMETERS: Op - Parent node (Resource Descriptor) + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Enter the named elements of the resource descriptor (children + * of the parent) into the namespace. + * + * NOTE: In the real AML namespace, these named elements never exist. But + * we simply use the namespace here as a symbol table so we can look + * them up as they are referenced. + * + ******************************************************************************/ + +static ACPI_STATUS +LdLoadResourceElements ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *InitializerOp = NULL; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* + * Enter the resource name into the namespace. Name must not already exist. + * This opens a scope, so later field names are guaranteed to be new/unique. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Namepath, + ACPI_TYPE_LOCAL_RESOURCE, ACPI_IMODE_LOAD_PASS1, + ACPI_NS_NO_UPSEARCH | ACPI_NS_ERROR_IF_FOUND, + WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_ALREADY_EXISTS) + { + /* Actual node causing the error was saved in ParentMethod */ + + AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, + (ACPI_PARSE_OBJECT *) Op->Asl.ParentMethod, Op->Asl.Namepath); + return (AE_OK); + } + return (Status); + } + + Node->Value = (UINT32) Op->Asl.Value.Integer; + Node->Op = Op; + Op->Asl.Node = Node; + + /* + * Now enter the predefined fields, for easy lookup when referenced + * by the source ASL + */ + InitializerOp = ASL_GET_CHILD_NODE (Op); + while (InitializerOp) + { + if (InitializerOp->Asl.ExternalName) + { + Status = AcpiNsLookup (WalkState->ScopeInfo, + InitializerOp->Asl.ExternalName, + ACPI_TYPE_LOCAL_RESOURCE_FIELD, + ACPI_IMODE_LOAD_PASS1, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &Node); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Store the field offset and length in the namespace node + * so it can be used when the field is referenced + */ + Node->Value = InitializerOp->Asl.Value.Tag.BitOffset; + Node->Length = InitializerOp->Asl.Value.Tag.BitLength; + InitializerOp->Asl.Node = Node; + Node->Op = InitializerOp; + } + + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LdNamespace1Begin + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the parse tree walk. If this + * is a named AML opcode, enter into the namespace + * + ******************************************************************************/ + +static ACPI_STATUS +LdNamespace1Begin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE ObjectType; + ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; + char *Path; + UINT32 Flags = ACPI_NS_NO_UPSEARCH; + ACPI_PARSE_OBJECT *Arg; + UINT32 i; + BOOLEAN ForceNewScope = FALSE; + + + ACPI_FUNCTION_NAME (LdNamespace1Begin); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", + Op, Op->Asl.ParseOpName)); + + + /* + * We are only interested in opcodes that have an associated name + * (or multiple names) + */ + switch (Op->Asl.AmlOpcode) + { + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + case AML_FIELD_OP: + + Status = LdLoadFieldElements (Op, WalkState); + return (Status); + + default: + + /* All other opcodes go below */ + break; + } + + /* Check if this object has already been installed in the namespace */ + + if (Op->Asl.Node) + { + return (AE_OK); + } + + Path = Op->Asl.Namepath; + if (!Path) + { + return (AE_OK); + } + + /* Map the raw opcode into an internal object type */ + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_NAME: + + Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ + Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ + + /* + * If this name refers to a ResourceTemplate, we will need to open + * a new scope so that the resource subfield names can be entered into + * the namespace underneath this name + */ + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) + { + ForceNewScope = TRUE; + } + + /* Get the data type associated with the named object, not the name itself */ + + /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ + + ObjectType = 1; + for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) + { + ObjectType++; + } + break; + + + case PARSEOP_EXTERNAL: + + /* + * "External" simply enters a name and type into the namespace. + * We must be careful to not open a new scope, however, no matter + * what type the external name refers to (e.g., a method) + * + * first child is name, next child is ObjectType + */ + ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; + ObjectType = ACPI_TYPE_ANY; + + /* + * We will mark every new node along the path as "External". This + * allows some or all of the nodes to be created later in the ASL + * code. Handles cases like this: + * + * External (\_SB_.PCI0.ABCD, IntObj) + * Scope (_SB_) + * { + * Device (PCI0) + * { + * } + * } + * Method (X) + * { + * Store (\_SB_.PCI0.ABCD, Local0) + * } + */ + Flags |= ACPI_NS_EXTERNAL; + break; + + case PARSEOP_DEFAULT_ARG: + + if (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC) + { + Status = LdLoadResourceElements (Op, WalkState); + return_ACPI_STATUS (Status); + } + + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + break; + + + case PARSEOP_SCOPE: + + /* + * The name referenced by Scope(Name) must already exist at this point. + * In other words, forward references for Scope() are not supported. + * The only real reason for this is that the MS interpreter cannot + * handle this case. Perhaps someday this case can go away. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + WalkState, &(Node)); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + /* The name was not found, go ahead and create it */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, + ACPI_TYPE_LOCAL_SCOPE, + ACPI_IMODE_LOAD_PASS1, Flags, + WalkState, &(Node)); + + /* + * However, this is an error -- primarily because the MS + * interpreter can't handle a forward reference from the + * Scope() operator. + */ + AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, + Op->Asl.ExternalName); + AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, + Op->Asl.ExternalName); + goto FinishNode; + } + + AslCoreSubsystemError (Op, Status, + "Failure from namespace lookup", FALSE); + + return_ACPI_STATUS (Status); + } + + /* We found a node with this name, now check the type */ + + switch (Node->Type) + { + case ACPI_TYPE_LOCAL_SCOPE: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types - they all open a new scope */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. + * This enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + * + * Which is used to workaround the fact that the MS interpreter + * does not allow Scope() forward references. + */ + sprintf (MsgBuffer, "%s [%s], changing type to [Scope]", + Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); + AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); + + /* Switch the type to scope, open the new scope */ + + Node->Type = ACPI_TYPE_LOCAL_SCOPE; + Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + break; + + default: + + /* All other types are an error */ + + sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, + AcpiUtGetTypeName (Node->Type)); + AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); + + /* + * However, switch the type to be an actual scope so + * that compilation can continue without generating a whole + * cascade of additional errors. Open the new scope. + */ + Node->Type = ACPI_TYPE_LOCAL_SCOPE; + Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + break; + } + + Status = AE_OK; + goto FinishNode; + + + default: + + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + break; + } + + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", + Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); + + /* The name must not already exist */ + + Flags |= ACPI_NS_ERROR_IF_FOUND; + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_ALREADY_EXISTS) + { + /* The name already exists in this scope */ + + if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) + { + /* Allow multiple references to the same scope */ + + Node->Type = (UINT8) ObjectType; + Status = AE_OK; + } + else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && + (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) + { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + Node->Flags &= ~ANOBJ_IS_EXTERNAL; + Node->Type = (UINT8) ObjectType; + + /* Just retyped a node, probably will need to open a scope */ + + if (AcpiNsOpensScope (ObjectType)) + { + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + Status = AE_OK; + } + else + { + /* Valid error, object already exists */ + + AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, + Op->Asl.ExternalName); + return_ACPI_STATUS (AE_OK); + } + } + else + { + AslCoreSubsystemError (Op, Status, + "Failure from namespace lookup", FALSE); + return_ACPI_STATUS (Status); + } + } + + if (ForceNewScope) + { + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + +FinishNode: + /* + * Point the parse node to the new namespace node, and point + * the Node back to the original Parse node + */ + Op->Asl.Node = Node; + Node->Op = Op; + + /* Set the actual data type if appropriate (EXTERNAL term only) */ + + if (ActualObjectType != ACPI_TYPE_ANY) + { + Node->Type = (UINT8) ActualObjectType; + Node->Value = ASL_EXTERNAL_METHOD; + } + + if (Op->Asl.ParseOpcode == PARSEOP_METHOD) + { + /* + * Get the method argument count from "Extra" and save + * it in the namespace node + */ + Node->Value = (UINT32) Op->Asl.Extra; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: LdNamespace2Begin + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the pass 2 parse tree walk. + * Second pass resolves some forward references. + * + * Notes: + * Currently only needs to handle the Alias operator. + * Could be used to allow forward references from the Scope() operator, but + * the MS interpreter does not allow this, so this compiler does not either. + * + ******************************************************************************/ + +static ACPI_STATUS +LdNamespace2Begin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OBJECT_TYPE ObjectType; + BOOLEAN ForceNewScope = FALSE; + ACPI_PARSE_OBJECT *Arg; + char *Path; + ACPI_NAMESPACE_NODE *TargetNode; + + + ACPI_FUNCTION_NAME (LdNamespace2Begin); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", + Op, Op->Asl.ParseOpName)); + + + /* Ignore Ops with no namespace node */ + + Node = Op->Asl.Node; + if (!Node) + { + return (AE_OK); + } + + /* Get the type to determine if we should push the scope */ + + if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && + (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)) + { + ObjectType = ACPI_TYPE_LOCAL_RESOURCE; + } + else + { + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + } + + /* Push scope for Resource Templates */ + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) + { + ForceNewScope = TRUE; + } + } + + /* Push the scope stack */ + + if (ForceNewScope || AcpiNsOpensScope (ObjectType)) + { + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) + { + /* Complete the alias node by getting and saving the target node */ + + /* First child is the alias target */ + + Arg = Op->Asl.Child; + + /* Get the target pathname */ + + Path = Arg->Asl.Namepath; + if (!Path) + { + Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + /* Get the NS node associated with the target. It must exist. */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &TargetNode); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, + Op->Asl.ExternalName); + + /* + * The name was not found, go ahead and create it. + * This prevents more errors later. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, + ACPI_TYPE_ANY, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH, + WalkState, &(Node)); + return (AE_OK); + } + + AslCoreSubsystemError (Op, Status, + "Failure from namespace lookup", FALSE); + return (AE_OK); + } + + /* Save the target node within the alias node */ + + Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LdCommonNamespaceEnd + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * We only need to worry about managing the scope stack here. + * + ******************************************************************************/ + +static ACPI_STATUS +LdCommonNamespaceEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; + ACPI_OBJECT_TYPE ObjectType; + BOOLEAN ForceNewScope = FALSE; + + + ACPI_FUNCTION_NAME (LdCommonNamespaceEnd); + + + /* We are only interested in opcodes that have an associated name */ + + if (!Op->Asl.Namepath) + { + return (AE_OK); + } + + /* Get the type to determine if we should pop the scope */ + + if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && + (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)) + { + /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */ + + ObjectType = ACPI_TYPE_LOCAL_RESOURCE; + } + else + { + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + } + + /* Pop scope that was pushed for Resource Templates */ + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) + { + ForceNewScope = TRUE; + } + } + + /* Pop the scope stack */ + + if (ForceNewScope || AcpiNsOpensScope (ObjectType)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "(%s): Popping scope for Op [%s] %p\n", + AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op)); + + (void) AcpiDsScopeStackPop (WalkState); + } + + return (AE_OK); +} + + diff --git a/source/compiler/asllookup.c b/source/compiler/asllookup.c new file mode 100644 index 000000000000..655f9833639a --- /dev/null +++ b/source/compiler/asllookup.c @@ -0,0 +1,1401 @@ +/****************************************************************************** + * + * Module Name: asllookup- Namespace lookup + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asllookup") + +/* Local prototypes */ + +static ACPI_STATUS +LsCompareOneNamespaceObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +LsDoOneNamespaceObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static BOOLEAN +LkObjectExists ( + char *Name); + +static void +LkCheckFieldRange ( + ACPI_PARSE_OBJECT *Op, + UINT32 RegionBitLength, + UINT32 FieldBitOffset, + UINT32 FieldBitLength, + UINT32 AccessBitWidth); + +static ACPI_STATUS +LkNamespaceLocateBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +LkNamespaceLocateEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +LkIsObjectUsed ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +LsDoOnePathname ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_PARSE_OBJECT * +LkGetNameOp ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: LsDoOneNamespaceObject + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Dump a namespace object to the namespace output file. + * Called during the walk of the namespace to dump all objects. + * + ******************************************************************************/ + +static ACPI_STATUS +LsDoOneNamespaceObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PARSE_OBJECT *Op; + + + Gbl_NumNamespaceObjects++; + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5u [%u] %*s %4.4s - %s", + Gbl_NumNamespaceObjects, Level, (Level * 3), " ", + &Node->Name, + AcpiUtGetTypeName (Node->Type)); + + Op = Node->Op; + ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object); + + if (!Op) + { + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n"); + return (AE_OK); + } + + + if ((ObjDesc) && + (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)) + { + switch (Node->Type) + { + case ACPI_TYPE_INTEGER: + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Value 0x%8.8X%8.8X]", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_STRING: + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Value \"%s\"]", + ObjDesc->String.Pointer); + break; + + default: + /* Nothing to do for other types */ + break; + } + + } + else + { + switch (Node->Type) + { + case ACPI_TYPE_INTEGER: + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + Op = Op->Asl.Child; + } + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) + { + Op = Op->Asl.Next; + } + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Value 0x%8.8X%8.8X]", + ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); + break; + + + case ACPI_TYPE_STRING: + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + Op = Op->Asl.Child; + } + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) + { + Op = Op->Asl.Next; + } + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Value \"%s\"]", + Op->Asl.Value.String); + break; + + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) + { + Op = Op->Asl.Child; + } + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Offset 0x%04X Length 0x%04X bits]", + Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_CREATEBYTEFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]"); + break; + + case PARSEOP_CREATEDWORDFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]"); + break; + + case PARSEOP_CREATEQWORDFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]"); + break; + + case PARSEOP_CREATEWORDFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]"); + break; + + case PARSEOP_CREATEBITFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]"); + break; + + case PARSEOP_CREATEFIELD: + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]"); + break; + + default: + break; + + } + break; + + + case ACPI_TYPE_PACKAGE: + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + Op = Op->Asl.Child; + } + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) + { + Op = Op->Asl.Next; + } + Op = Op->Asl.Child; + + if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) || + (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA)) + { + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Length 0x%.2X elements]", + Op->Asl.Value.Integer); + } + break; + + + case ACPI_TYPE_BUFFER: + + if (Op->Asl.ParseOpcode == PARSEOP_NAME) + { + Op = Op->Asl.Child; + } + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) + { + Op = Op->Asl.Next; + } + Op = Op->Asl.Child; + + if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER)) + { + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Initial Length 0x%.2X bytes]", + Op->Asl.Value.Integer); + } + break; + + + case ACPI_TYPE_METHOD: + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Code Length 0x%.4X bytes]", + Op->Asl.AmlSubtreeLength); + break; + + + case ACPI_TYPE_LOCAL_RESOURCE: + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Desc Offset 0x%.4X Bytes]", Node->Value); + break; + + + case ACPI_TYPE_LOCAL_RESOURCE_FIELD: + + if (Node->Flags & 0x80) + { + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Field Offset 0x%.4X Bits 0x%.4X Bytes]", + Node->Value, Node->Value / 8); + } + else + { + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, + " [Field Offset 0x%.4X Bytes]", Node->Value); + } + break; + + + default: + /* Nothing to do for other types */ + break; + } + } + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n"); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LsSetupNsList + * + * PARAMETERS: Handle - local file handle + * + * RETURN: None + * + * DESCRIPTION: Set the namespace output file to the input handle + * + ******************************************************************************/ + +void +LsSetupNsList ( + void *Handle) +{ + + Gbl_NsOutputFlag = TRUE; + Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle; +} + + +/******************************************************************************* + * + * FUNCTION: LsDoOnePathname + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Print the full pathname for a namespace node. + * + ******************************************************************************/ + +static ACPI_STATUS +LsDoOnePathname ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_STATUS Status; + ACPI_BUFFER TargetPath; + + + TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (Node, &TargetPath); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%s\n", TargetPath.Pointer); + ACPI_FREE (TargetPath.Pointer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LsDisplayNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the namespace an display information about each node + * in the tree. Information is written to the optional + * namespace output file. + * + ******************************************************************************/ + +ACPI_STATUS +LsDisplayNamespace ( + void) +{ + ACPI_STATUS Status; + + + if (!Gbl_NsOutputFlag) + { + return (AE_OK); + } + + Gbl_NumNamespaceObjects = 0; + + /* File header */ + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n"); + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n"); + + /* Walk entire namespace from the root */ + + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject, NULL, + NULL, NULL); + + /* Print the full pathname for each namespace node */ + + FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\nNamespace pathnames\n\n"); + + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, LsDoOnePathname, NULL, + NULL, NULL); + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: LsCompareOneNamespaceObject + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Compare name of one object. + * + ******************************************************************************/ + +static ACPI_STATUS +LsCompareOneNamespaceObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + + + /* Simply check the name */ + + if (*((UINT32 *) (Context)) == Node->Name.Integer) + { + /* Abort walk if we found one instance */ + + return (AE_CTRL_TRUE); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LkObjectExists + * + * PARAMETERS: Name - 4 char ACPI name + * + * RETURN: TRUE if name exists in namespace + * + * DESCRIPTION: Walk the namespace to find an object + * + ******************************************************************************/ + +static BOOLEAN +LkObjectExists ( + char *Name) +{ + ACPI_STATUS Status; + + + /* Walk entire namespace from the supplied root */ + + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject, NULL, + Name, NULL); + if (Status == AE_CTRL_TRUE) + { + /* At least one instance of the name was found */ + + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: LkGetNameOp + * + * PARAMETERS: Op - Current Op + * + * RETURN: NameOp associated with the input op + * + * DESCRIPTION: Find the name declaration op associated with the operator + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +LkGetNameOp ( + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *OpInfo; + ACPI_PARSE_OBJECT *NameOp = Op; + + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + + + /* Get the NamePath from the appropriate place */ + + if (OpInfo->Flags & AML_NAMED) + { + /* For nearly all NAMED operators, the name reference is the first child */ + + NameOp = Op->Asl.Child; + if (Op->Asl.AmlOpcode == AML_ALIAS_OP) + { + /* + * ALIAS is the only oddball opcode, the name declaration + * (alias name) is the second operand + */ + NameOp = Op->Asl.Child->Asl.Next; + } + } + else if (OpInfo->Flags & AML_CREATE) + { + /* Name must appear as the last parameter */ + + NameOp = Op->Asl.Child; + while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) + { + NameOp = NameOp->Asl.Next; + } + } + + return (NameOp); +} + + +/******************************************************************************* + * + * FUNCTION: LkIsObjectUsed + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Check for an unreferenced namespace object and emit a warning. + * We have to be careful, because some types and names are + * typically or always unreferenced, we don't want to issue + * excessive warnings. + * + ******************************************************************************/ + +static ACPI_STATUS +LkIsObjectUsed ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + + + /* Referenced flag is set during the namespace xref */ + + if (Node->Flags & ANOBJ_IS_REFERENCED) + { + return (AE_OK); + } + + /* + * Ignore names that start with an underscore, + * these are the reserved ACPI names and are typically not referenced, + * they are called by the host OS. + */ + if (Node->Name.Ascii[0] == '_') + { + return (AE_OK); + } + + /* There are some types that are typically not referenced, ignore them */ + + switch (Node->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + case ACPI_TYPE_LOCAL_RESOURCE: + return (AE_OK); + + default: + break; + } + + /* All others are valid unreferenced namespace objects */ + + if (Node->Op) + { + AslError (ASL_WARNING2, ASL_MSG_NOT_REFERENCED, LkGetNameOp (Node->Op), NULL); + } + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: LkFindUnreferencedObjects + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Namespace walk to find objects that are not referenced in any + * way. Must be called after the namespace has been cross + * referenced. + * + ******************************************************************************/ + +void +LkFindUnreferencedObjects ( + void) +{ + + /* Walk entire namespace from the supplied root */ + + (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL, + NULL, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: LkCrossReferenceNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a cross reference check of the parse tree against the + * namespace. Every named referenced within the parse tree + * should be get resolved with a namespace lookup. If not, the + * original reference in the ASL code is invalid -- i.e., refers + * to a non-existent object. + * + * NOTE: The ASL "External" operator causes the name to be inserted into the + * namespace so that references to the external name will be resolved + * correctly here. + * + ******************************************************************************/ + +ACPI_STATUS +LkCrossReferenceNamespace ( + void) +{ + ACPI_WALK_STATE *WalkState; + + + DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n"); + + /* + * Create a new walk state for use when looking up names + * within the namespace (Passed as context to the callbacks) + */ + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + return AE_NO_MEMORY; + } + + /* Walk the entire parse tree */ + + TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin, + LkNamespaceLocateEnd, WalkState); + return AE_OK; +} + + +/******************************************************************************* + * + * FUNCTION: LkCheckFieldRange + * + * PARAMETERS: RegionBitLength - Length of entire parent region + * FieldBitOffset - Start of the field unit (within region) + * FieldBitLength - Entire length of field unit + * AccessBitWidth - Access width of the field unit + * + * RETURN: None + * + * DESCRIPTION: Check one field unit to make sure it fits in the parent + * op region. + * + * Note: AccessBitWidth must be either 8,16,32, or 64 + * + ******************************************************************************/ + +static void +LkCheckFieldRange ( + ACPI_PARSE_OBJECT *Op, + UINT32 RegionBitLength, + UINT32 FieldBitOffset, + UINT32 FieldBitLength, + UINT32 AccessBitWidth) +{ + UINT32 FieldEndBitOffset; + + + /* + * Check each field unit against the region size. The entire + * field unit (start offset plus length) must fit within the + * region. + */ + FieldEndBitOffset = FieldBitOffset + FieldBitLength; + + if (FieldEndBitOffset > RegionBitLength) + { + /* Field definition itself is beyond the end-of-region */ + + AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); + return; + } + + /* + * Now check that the field plus AccessWidth doesn't go beyond + * the end-of-region. Assumes AccessBitWidth is a power of 2 + */ + FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); + + if (FieldEndBitOffset > RegionBitLength) + { + /* Field definition combined with the access is beyond EOR */ + + AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); + } +} + +/******************************************************************************* + * + * FUNCTION: LkNamespaceLocateBegin + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during cross-reference. For named + * object references, attempt to locate the name in the + * namespace. + * + * NOTE: ASL references to named fields within resource descriptors are + * resolved to integer values here. Therefore, this step is an + * important part of the code generation. We don't know that the + * name refers to a resource descriptor until now. + * + ******************************************************************************/ + +static ACPI_STATUS +LkNamespaceLocateBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE ObjectType; + char *Path; + UINT8 PassedArgs; + ACPI_PARSE_OBJECT *NextOp; + ACPI_PARSE_OBJECT *OwningOp; + ACPI_PARSE_OBJECT *SpaceIdOp; + UINT32 MinimumLength; + UINT32 Offset; + UINT32 FieldBitLength; + UINT32 TagBitLength; + UINT8 Message = 0; + const ACPI_OPCODE_INFO *OpInfo; + UINT32 Flags; + + + ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op); + + /* + * If this node is the actual declaration of a name + * [such as the XXXX name in "Method (XXXX)"], + * we are not interested in it here. We only care about names that are + * references to other objects within the namespace and the parent objects + * of name declarations + */ + if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) + { + return (AE_OK); + } + + /* We are only interested in opcodes that have an associated name */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + + if ((!(OpInfo->Flags & AML_NAMED)) && + (!(OpInfo->Flags & AML_CREATE)) && + (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && + (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && + (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) + { + return (AE_OK); + } + + /* + * One special case: CondRefOf operator - we don't care if the name exists + * or not at this point, just ignore it, the point of the operator is to + * determine if the name exists at runtime. + */ + if ((Op->Asl.Parent) && + (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) + { + return (AE_OK); + } + + /* + * We must enable the "search-to-root" for single NameSegs, but + * we have to be very careful about opening up scopes + */ + Flags = ACPI_NS_SEARCH_PARENT; + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) + { + /* + * These are name references, do not push the scope stack + * for them. + */ + Flags |= ACPI_NS_DONT_OPEN_SCOPE; + } + + /* Get the NamePath from the appropriate place */ + + if (OpInfo->Flags & AML_NAMED) + { + /* For nearly all NAMED operators, the name reference is the first child */ + + Path = Op->Asl.Child->Asl.Value.String; + if (Op->Asl.AmlOpcode == AML_ALIAS_OP) + { + /* + * ALIAS is the only oddball opcode, the name declaration + * (alias name) is the second operand + */ + Path = Op->Asl.Child->Asl.Next->Asl.Value.String; + } + } + else if (OpInfo->Flags & AML_CREATE) + { + /* Name must appear as the last parameter */ + + NextOp = Op->Asl.Child; + while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) + { + NextOp = NextOp->Asl.Next; + } + Path = NextOp->Asl.Value.String; + } + else + { + Path = Op->Asl.Value.String; + } + + ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Type=%s\n", AcpiUtGetTypeName (ObjectType))); + + /* + * Lookup the name in the namespace. Name must exist at this point, or it + * is an invalid reference. + * + * The namespace is also used as a lookup table for references to resource + * descriptors and the fields within them. + */ + Gbl_NsLookupCount++; + + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + /* + * We didn't find the name reference by path -- we can qualify this + * a little better before we print an error message + */ + if (strlen (Path) == ACPI_NAME_SIZE) + { + /* A simple, one-segment ACPI name */ + + if (LkObjectExists (Path)) + { + /* + * There exists such a name, but we couldn't get to it + * from this scope + */ + AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, + Op->Asl.ExternalName); + } + else + { + /* The name doesn't exist, period */ + + AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, + Op, Op->Asl.ExternalName); + } + } + else + { + /* Check for a fully qualified path */ + + if (Path[0] == AML_ROOT_PREFIX) + { + /* Gave full path, the object does not exist */ + + AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, + Op->Asl.ExternalName); + } + else + { + /* + * We can't tell whether it doesn't exist or just + * can't be reached. + */ + AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, + Op->Asl.ExternalName); + } + } + + Status = AE_OK; + } + return (Status); + } + + /* Check for a reference vs. name declaration */ + + if (!(OpInfo->Flags & AML_NAMED) && + !(OpInfo->Flags & AML_CREATE)) + { + /* This node has been referenced, mark it for reference check */ + + Node->Flags |= ANOBJ_IS_REFERENCED; + } + + /* Attempt to optimize the NamePath */ + + OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); + + /* + * 1) Dereference an alias (A name reference that is an alias) + * Aliases are not nested, the alias always points to the final object + */ + if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && + (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) + { + /* This node points back to the original PARSEOP_ALIAS */ + + NextOp = Node->Op; + + /* The first child is the alias target op */ + + NextOp = NextOp->Asl.Child; + + /* That in turn points back to original target alias node */ + + if (NextOp->Asl.Node) + { + Node = NextOp->Asl.Node; + } + + /* Else - forward reference to alias, will be resolved later */ + } + + /* 2) Check for a reference to a resource descriptor */ + + if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || + (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) + { + /* + * This was a reference to a field within a resource descriptor. + * Extract the associated field offset (either a bit or byte + * offset depending on the field type) and change the named + * reference into an integer for AML code generation + */ + Offset = Node->Value; + TagBitLength = Node->Length; + + /* + * If a field is being created, generate the length (in bits) of + * the field. Note: Opcodes other than CreateXxxField and Index + * can come through here. For other opcodes, we just need to + * convert the resource tag reference to an integer offset. + */ + switch (Op->Asl.Parent->Asl.AmlOpcode) + { + case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ + /* + * We know the length operand is an integer constant because + * we know that it contains a reference to a resource + * descriptor tag. + */ + FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; + break; + + case AML_CREATE_BIT_FIELD_OP: + FieldBitLength = 1; + break; + + case AML_CREATE_BYTE_FIELD_OP: + case AML_INDEX_OP: + FieldBitLength = 8; + break; + + case AML_CREATE_WORD_FIELD_OP: + FieldBitLength = 16; + break; + + case AML_CREATE_DWORD_FIELD_OP: + FieldBitLength = 32; + break; + + case AML_CREATE_QWORD_FIELD_OP: + FieldBitLength = 64; + break; + + default: + FieldBitLength = 0; + break; + } + + /* Check the field length against the length of the resource tag */ + + if (FieldBitLength) + { + if (TagBitLength < FieldBitLength) + { + Message = ASL_MSG_TAG_SMALLER; + } + else if (TagBitLength > FieldBitLength) + { + Message = ASL_MSG_TAG_LARGER; + } + + if (Message) + { + sprintf (MsgBuffer, "Tag: %u bit%s, Field: %u bit%s", + TagBitLength, (TagBitLength > 1) ? "s" : "", + FieldBitLength, (FieldBitLength > 1) ? "s" : ""); + + AslError (ASL_WARNING, Message, Op, MsgBuffer); + } + } + + /* Convert the BitOffset to a ByteOffset for certain opcodes */ + + switch (Op->Asl.Parent->Asl.AmlOpcode) + { + case AML_CREATE_BYTE_FIELD_OP: + case AML_CREATE_WORD_FIELD_OP: + case AML_CREATE_DWORD_FIELD_OP: + case AML_CREATE_QWORD_FIELD_OP: + case AML_INDEX_OP: + + Offset = ACPI_DIV_8 (Offset); + break; + + default: + break; + } + + /* Now convert this node to an integer whose value is the field offset */ + + Op->Asl.AmlLength = 0; + Op->Asl.ParseOpcode = PARSEOP_INTEGER; + Op->Asl.Value.Integer = (UINT64) Offset; + Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; + + OpcGenerateAmlOpcode (Op); + } + + /* 3) Check for a method invocation */ + + else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && + (Node->Type == ACPI_TYPE_METHOD) && + (Op->Asl.Parent) && + (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || + + (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) + { + + /* + * A reference to a method within one of these opcodes is not an + * invocation of the method, it is simply a reference to the method. + */ + if ((Op->Asl.Parent) && + ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || + (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || + (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) + { + return (AE_OK); + } + /* + * There are two types of method invocation: + * 1) Invocation with arguments -- the parser recognizes this + * as a METHODCALL. + * 2) Invocation with no arguments --the parser cannot determine that + * this is a method invocation, therefore we have to figure it out + * here. + */ + if (Node->Type != ACPI_TYPE_METHOD) + { + sprintf (MsgBuffer, "%s is a %s", + Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); + + AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); + return (AE_OK); + } + + /* Save the method node in the caller's op */ + + Op->Asl.Node = Node; + if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) + { + return (AE_OK); + } + + /* + * This is a method invocation, with or without arguments. + * Count the number of arguments, each appears as a child + * under the parent node + */ + Op->Asl.ParseOpcode = PARSEOP_METHODCALL; + UtSetParseOpName (Op); + + PassedArgs = 0; + NextOp = Op->Asl.Child; + + while (NextOp) + { + PassedArgs++; + NextOp = NextOp->Asl.Next; + } + + if (Node->Value != ASL_EXTERNAL_METHOD) + { + /* + * Check the parsed arguments with the number expected by the + * method declaration itself + */ + if (PassedArgs != Node->Value) + { + sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, + Node->Value); + + if (PassedArgs < Node->Value) + { + AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); + } + else + { + AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); + } + } + } + } + + /* 4) Check for an ASL Field definition */ + + else if ((Op->Asl.Parent) && + ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || + (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) + { + /* + * Offset checking for fields. If the parent operation region has a + * constant length (known at compile time), we can check fields + * defined in that region against the region length. This will catch + * fields and field units that cannot possibly fit within the region. + * + * Note: Index fields do not directly reference an operation region, + * thus they are not included in this check. + */ + if (Op == Op->Asl.Parent->Asl.Child) + { + /* + * This is the first child of the field node, which is + * the name of the region. Get the parse node for the + * region -- which contains the length of the region. + */ + OwningOp = Node->Op; + Op->Asl.Parent->Asl.ExtraValue = + ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); + + /* Examine the field access width */ + + switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) + { + case AML_FIELD_ACCESS_ANY: + case AML_FIELD_ACCESS_BYTE: + case AML_FIELD_ACCESS_BUFFER: + default: + MinimumLength = 1; + break; + + case AML_FIELD_ACCESS_WORD: + MinimumLength = 2; + break; + + case AML_FIELD_ACCESS_DWORD: + MinimumLength = 4; + break; + + case AML_FIELD_ACCESS_QWORD: + MinimumLength = 8; + break; + } + + /* + * Is the region at least as big as the access width? + * Note: DataTableRegions have 0 length + */ + if (((UINT32) OwningOp->Asl.Value.Integer) && + ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) + { + AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); + } + + /* + * Check EC/CMOS/SMBUS fields to make sure that the correct + * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) + */ + SpaceIdOp = OwningOp->Asl.Child->Asl.Next; + switch ((UINT32) SpaceIdOp->Asl.Value.Integer) + { + case ACPI_ADR_SPACE_EC: + case ACPI_ADR_SPACE_CMOS: + case ACPI_ADR_SPACE_GPIO: + + if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE) + { + AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); + } + break; + + case ACPI_ADR_SPACE_SMBUS: + case ACPI_ADR_SPACE_IPMI: + case ACPI_ADR_SPACE_GSBUS: + + if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) + { + AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); + } + break; + + default: + + /* Nothing to do for other address spaces */ + break; + } + } + else + { + /* + * This is one element of the field list. Check to make sure + * that it does not go beyond the end of the parent operation region. + * + * In the code below: + * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) + * Op->Asl.ExtraValue - Field start offset (bits) + * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) + * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) + */ + if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) + { + LkCheckFieldRange (Op, + Op->Asl.Parent->Asl.ExtraValue, + Op->Asl.ExtraValue, + (UINT32) Op->Asl.Child->Asl.Value.Integer, + Op->Asl.Child->Asl.ExtraValue); + } + } + } + + Op->Asl.Node = Node; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: LkNamespaceLocateEnd + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during cross reference. We only + * need to worry about scope management here. + * + ******************************************************************************/ + +static ACPI_STATUS +LkNamespaceLocateEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_TRACE (LkNamespaceLocateEnd); + + + /* We are only interested in opcodes that have an associated name */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + if (!(OpInfo->Flags & AML_NAMED)) + { + return (AE_OK); + } + + /* Not interested in name references, we did not open a scope for them */ + + if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || + (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || + (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) + { + return (AE_OK); + } + + /* Pop the scope stack if necessary */ + + if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) + { + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "%s: Popping scope for Op %p\n", + AcpiUtGetTypeName (OpInfo->ObjectType), Op)); + + (void) AcpiDsScopeStackPop (WalkState); + } + + return (AE_OK); +} + + diff --git a/source/compiler/aslmain.c b/source/compiler/aslmain.c new file mode 100644 index 000000000000..69a0e8b8236f --- /dev/null +++ b/source/compiler/aslmain.c @@ -0,0 +1,983 @@ + +/****************************************************************************** + * + * Module Name: aslmain - compiler main and utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define _DECLARE_GLOBALS + +#include "aslcompiler.h" +#include "acapps.h" +#include "acdisasm.h" + +#ifdef _DEBUG +#include +#endif + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslmain") + +/* Local prototypes */ + +static void +Options ( + void); + +static void +HelpMessage ( + void); + +static void +Usage ( + void); + +static void +AslInitialize ( + void); + +static int +AslCommandLine ( + int argc, + char **argv); + +static int +AslDoOptions ( + int argc, + char **argv, + BOOLEAN IsResponseFile); + +static void +AslMergeOptionTokens ( + char *InBuffer, + char *OutBuffer); + +static int +AslDoResponseFile ( + char *Filename); + + +#define ASL_TOKEN_SEPARATORS " \t\n" +#define ASL_SUPPORTED_OPTIONS "@:2b:c:d^e:fgh^i^I:l^mno:p:r:s:t:T:G^v:w:x:z" + + +/******************************************************************************* + * + * FUNCTION: Options + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display option help message + * + ******************************************************************************/ + +static void +Options ( + void) +{ + + printf ("\nGlobal:\n"); + ACPI_OPTION ("-@ ", "Specify command file"); + ACPI_OPTION ("-I ", "Specify additional include directory"); + + printf ("\nGeneral Output:\n"); + ACPI_OPTION ("-p ", "Specify path/filename prefix for all output files"); + ACPI_OPTION ("-va", "Disable all errors and warnings (summary only)"); + ACPI_OPTION ("-vi", "Less verbose errors and warnings for use with IDEs"); + ACPI_OPTION ("-vo", "Enable optimization comments"); + ACPI_OPTION ("-vr", "Disable remarks"); + ACPI_OPTION ("-vs", "Disable signon"); + ACPI_OPTION ("-w <1|2|3>", "Set warning reporting level"); + + printf ("\nAML Output Files:\n"); + ACPI_OPTION ("-s ", "Create AML in assembler or C source file (*.asm or *.c)"); + ACPI_OPTION ("-i ", "Create assembler or C include file (*.inc or *.h)"); + ACPI_OPTION ("-t ", "Create AML in assembler, C, or ASL hex table (*.hex)"); + + printf ("\nAML Code Generation:\n"); + ACPI_OPTION ("-oa", "Disable all optimizations (compatibility mode)"); + ACPI_OPTION ("-of", "Disable constant folding"); + ACPI_OPTION ("-oi", "Disable integer optimization to Zero/One/Ones"); + ACPI_OPTION ("-on", "Disable named reference string optimization"); + ACPI_OPTION ("-cr", "Disable Resource Descriptor error checking"); + ACPI_OPTION ("-r ", "Override table header Revision (1-255)"); + + printf ("\nASL Listing Files:\n"); + ACPI_OPTION ("-l", "Create mixed listing file (ASL source and AML) (*.lst)"); + ACPI_OPTION ("-ln", "Create namespace file (*.nsp)"); + ACPI_OPTION ("-ls", "Create combined source file (expanded includes) (*.src)"); + + printf ("\nACPI Data Tables:\n"); + ACPI_OPTION ("-G", "Compile custom table containing generic operators"); + ACPI_OPTION ("-T |ALL|*", "Create table template file(s) for "); + ACPI_OPTION ("-vt", "Create verbose templates (full disassembly)"); + + printf ("\nAML Disassembler:\n"); + ACPI_OPTION ("-d [file]", "Disassemble or decode binary ACPI table to file (*.dsl)"); + ACPI_OPTION ("-da [f1,f2]", "Disassemble multiple tables from single namespace"); + ACPI_OPTION ("-dc [file]", "Disassemble AML and immediately compile it"); + ACPI_OPTION ("", "(Obtain DSDT from current system if no input file)"); + ACPI_OPTION ("-e [f1,f2]", "Include ACPI table(s) for external symbol resolution"); + ACPI_OPTION ("-m", "Do not translate Buffers to Resource Templates"); + ACPI_OPTION ("-2", "Emit ACPI 2.0 compatible ASL code"); + ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)"); + + printf ("\nHelp:\n"); + ACPI_OPTION ("-h", "Additional help and compiler debug options"); + ACPI_OPTION ("-hc", "Display operators allowed in constant expressions"); + ACPI_OPTION ("-hr", "Display ACPI reserved method names"); + ACPI_OPTION ("-ht", "Display currently supported ACPI table names"); +} + + +/******************************************************************************* + * + * FUNCTION: HelpMessage + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display help message + * + ******************************************************************************/ + +static void +HelpMessage ( + void) +{ + + printf ("\nAML output filename generation:\n"); + printf (" Output filenames are generated by appending an extension to a common\n"); + printf (" filename prefix. The filename prefix is obtained via one of the\n"); + printf (" following methods (in priority order):\n"); + printf (" 1) The -p option specifies the prefix\n"); + printf (" 2) The prefix of the AMLFileName in the ASL Definition Block\n"); + printf (" 3) The prefix of the input filename\n"); + printf ("\n"); + + Options (); + + printf ("\nCompiler/Disassembler Debug Options:\n"); + ACPI_OPTION ("-b", "Create compiler debug/trace file (*.txt)"); + ACPI_OPTION ("", "Types: Parse/Tree/Both"); + ACPI_OPTION ("-f", "Ignore errors, force creation of AML output file(s)"); + ACPI_OPTION ("-n", "Parse only, no output generation"); + ACPI_OPTION ("-ot", "Display compile times"); + ACPI_OPTION ("-x", "Set debug level for trace output"); + ACPI_OPTION ("-z", "Do not insert new compiler ID for DataTables"); +} + + +/******************************************************************************* + * + * FUNCTION: Usage + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display usage and option message + * + ******************************************************************************/ + +static void +Usage ( + void) +{ + + printf ("%s\n\n", ASL_COMPLIANCE); + ACPI_USAGE_HEADER ("iasl [Options] [Files]"); + Options (); +} + + +/******************************************************************************* + * + * FUNCTION: AslInitialize + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Initialize compiler globals + * + ******************************************************************************/ + +static void +AslInitialize ( + void) +{ + UINT32 i; + + +#ifdef _DEBUG + _CrtSetDbgFlag (_CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(0)); +#endif + + AcpiDbgLevel = 0; + + for (i = 0; i < ASL_NUM_FILES; i++) + { + Gbl_Files[i].Handle = NULL; + Gbl_Files[i].Filename = NULL; + } + + Gbl_Files[ASL_FILE_STDOUT].Handle = stdout; + Gbl_Files[ASL_FILE_STDOUT].Filename = "STDOUT"; + + Gbl_Files[ASL_FILE_STDERR].Handle = stderr; + Gbl_Files[ASL_FILE_STDERR].Filename = "STDERR"; +} + + +/******************************************************************************* + * + * FUNCTION: AslMergeOptionTokens + * + * PARAMETERS: InBuffer - Input containing an option string + * OutBuffer - Merged output buffer + * + * RETURN: None + * + * DESCRIPTION: Remove all whitespace from an option string. + * + ******************************************************************************/ + +static void +AslMergeOptionTokens ( + char *InBuffer, + char *OutBuffer) +{ + char *Token; + + + *OutBuffer = 0; + + Token = strtok (InBuffer, ASL_TOKEN_SEPARATORS); + while (Token) + { + strcat (OutBuffer, Token); + Token = strtok (NULL, ASL_TOKEN_SEPARATORS); + } +} + + +/******************************************************************************* + * + * FUNCTION: AslDoResponseFile + * + * PARAMETERS: Filename - Name of the response file + * + * RETURN: Status + * + * DESCRIPTION: Open a response file and process all options within. + * + ******************************************************************************/ + +static int +AslDoResponseFile ( + char *Filename) +{ + char *argv = StringBuffer2; + FILE *ResponseFile; + int OptStatus = 0; + int Opterr; + int Optind; + + + ResponseFile = fopen (Filename, "r"); + if (!ResponseFile) + { + printf ("Could not open command file %s, %s\n", + Filename, strerror (errno)); + return -1; + } + + /* Must save the current GetOpt globals */ + + Opterr = AcpiGbl_Opterr; + Optind = AcpiGbl_Optind; + + /* + * Process all lines in the response file. There must be one complete + * option per line + */ + while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ResponseFile)) + { + /* Compress all tokens, allowing us to use a single argv entry */ + + AslMergeOptionTokens (StringBuffer, StringBuffer2); + + /* Process the option */ + + AcpiGbl_Opterr = 0; + AcpiGbl_Optind = 0; + + OptStatus = AslDoOptions (1, &argv, TRUE); + if (OptStatus) + { + printf ("Invalid option in command file %s: %s\n", + Filename, StringBuffer); + break; + } + } + + /* Restore the GetOpt globals */ + + AcpiGbl_Opterr = Opterr; + AcpiGbl_Optind = Optind; + + fclose (ResponseFile); + return (OptStatus); +} + + +/******************************************************************************* + * + * FUNCTION: AslDoOptions + * + * PARAMETERS: argc/argv - Standard argc/argv + * IsResponseFile - TRUE if executing a response file. + * + * RETURN: Status + * + * DESCRIPTION: Command line option processing + * + ******************************************************************************/ + +static int +AslDoOptions ( + int argc, + char **argv, + BOOLEAN IsResponseFile) +{ + int j; + ACPI_STATUS Status; + + + /* Get the command line options */ + + while ((j = AcpiGetopt (argc, argv, ASL_SUPPORTED_OPTIONS)) != EOF) switch (j) + { + case '@': /* Begin a response file */ + + if (IsResponseFile) + { + printf ("Nested command files are not supported\n"); + return -1; + } + + if (AslDoResponseFile (AcpiGbl_Optarg)) + { + return -1; + } + break; + + + case '2': + + Gbl_Acpi2 = TRUE; + break; + + + case 'b': + + switch (AcpiGbl_Optarg[0]) + { + case 'b': + AslCompilerdebug = 1; /* same as yydebug */ + DtParserdebug = 1; + break; + + case 'p': + AslCompilerdebug = 1; /* same as yydebug */ + DtParserdebug = 1; + break; + + case 't': + break; + + default: + printf ("Unknown option: -b%s\n", AcpiGbl_Optarg); + return (-1); + } + + /* Produce debug output file */ + + Gbl_DebugFlag = TRUE; + break; + + + case 'c': + switch (AcpiGbl_Optarg[0]) + { + case 'r': + Gbl_NoResourceChecking = TRUE; + break; + + default: + printf ("Unknown option: -c%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'd': + switch (AcpiGbl_Optarg[0]) + { + case '^': + Gbl_DoCompile = FALSE; + break; + + case 'a': + Gbl_DoCompile = FALSE; + Gbl_DisassembleAll = TRUE; + break; + + case 'c': + break; + + default: + printf ("Unknown option: -d%s\n", AcpiGbl_Optarg); + return (-1); + } + + Gbl_DisasmFlag = TRUE; + break; + + + case 'e': + Status = AcpiDmAddToExternalFileList (AcpiGbl_Optarg); + if (ACPI_FAILURE (Status)) + { + printf ("Could not add %s to external list\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'f': + + /* Ignore errors and force creation of aml file */ + + Gbl_IgnoreErrors = TRUE; + break; + + + case 'g': + + /* Get all ACPI tables */ + + Gbl_GetAllTables = TRUE; + Gbl_DoCompile = FALSE; + break; + + + case 'h': + + switch (AcpiGbl_Optarg[0]) + { + case '^': + HelpMessage (); + exit (0); + + case 'c': + UtDisplayConstantOpcodes (); + exit (0); + + case 'r': + /* reserved names */ + + ApDisplayReservedNames (); + exit (0); + + case 't': + UtDisplaySupportedTables (); + exit (0); + + default: + printf ("Unknown option: -h%s\n", AcpiGbl_Optarg); + return (-1); + } + + + case 'I': /* Add an include file search directory */ + + FlAddIncludeDirectory (AcpiGbl_Optarg); + break; + + + case 'i': + + switch (AcpiGbl_Optarg[0]) + { + case 'a': + + /* Produce assembly code include file */ + + Gbl_AsmIncludeOutputFlag = TRUE; + break; + + case 'c': + + /* Produce C include file */ + + Gbl_C_IncludeOutputFlag = TRUE; + break; + + default: + printf ("Unknown option: -s%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'l': + + switch (AcpiGbl_Optarg[0]) + { + case '^': + /* Produce listing file (Mixed source/aml) */ + + Gbl_ListingFlag = TRUE; + break; + + case 'n': + /* Produce namespace file */ + + Gbl_NsOutputFlag = TRUE; + break; + + case 's': + /* Produce combined source file */ + + Gbl_SourceOutputFlag = TRUE; + break; + + default: + printf ("Unknown option: -l%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'm': + + AcpiGbl_NoResourceDisassembly = TRUE; + break; + + + case 'n': + + /* Parse only */ + + Gbl_ParseOnlyFlag = TRUE; + break; + + + case 'o': + + switch (AcpiGbl_Optarg[0]) + { + case 'a': + + /* Disable all optimizations */ + + Gbl_FoldConstants = FALSE; + Gbl_IntegerOptimizationFlag = FALSE; + Gbl_ReferenceOptimizationFlag = FALSE; + break; + + case 'f': + + /* Disable folding on "normal" expressions */ + + Gbl_FoldConstants = FALSE; + break; + + case 'i': + + /* Disable integer optimization to constants */ + + Gbl_IntegerOptimizationFlag = FALSE; + break; + + case 'n': + + /* Disable named reference optimization */ + + Gbl_ReferenceOptimizationFlag = FALSE; + break; + + case 't': + + /* Display compile time(s) */ + + Gbl_CompileTimesFlag = TRUE; + break; + + default: + printf ("Unknown option: -c%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'p': + + /* Override default AML output filename */ + + Gbl_OutputFilenamePrefix = AcpiGbl_Optarg; + Gbl_UseDefaultAmlFilename = FALSE; + break; + + + case 'r': + Gbl_RevisionOverride = (UINT8) strtoul (AcpiGbl_Optarg, NULL, 0); + break; + + + case 's': + + switch (AcpiGbl_Optarg[0]) + { + case 'a': + + /* Produce assembly code output file */ + + Gbl_AsmOutputFlag = TRUE; + break; + + case 'c': + + /* Produce C hex output file */ + + Gbl_C_OutputFlag = TRUE; + break; + + default: + printf ("Unknown option: -s%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 't': + + /* Produce hex table output file */ + + switch (AcpiGbl_Optarg[0]) + { + case 'a': + Gbl_HexOutputFlag = HEX_OUTPUT_ASM; + break; + + case 'c': + Gbl_HexOutputFlag = HEX_OUTPUT_C; + break; + + case 's': + Gbl_HexOutputFlag = HEX_OUTPUT_ASL; + break; + + default: + printf ("Unknown option: -t%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'G': + Gbl_CompileGeneric = TRUE; + break; + + + case 'T': + Gbl_DoTemplates = TRUE; + Gbl_TemplateSignature = AcpiGbl_Optarg; + break; + + + case 'v': + + switch (AcpiGbl_Optarg[0]) + { + case 'a': + /* Disable All error/warning messages */ + + Gbl_NoErrors = TRUE; + break; + + case 'i': + /* Less verbose error messages */ + + Gbl_VerboseErrors = FALSE; + break; + + case 'o': + Gbl_DisplayOptimizations = TRUE; + break; + + case 'r': + Gbl_DisplayRemarks = FALSE; + break; + + case 's': + Gbl_DoSignon = FALSE; + break; + + case 't': + Gbl_VerboseTemplates = TRUE; + break; + + default: + printf ("Unknown option: -v%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'w': /* Set warning levels */ + + switch (AcpiGbl_Optarg[0]) + { + case '1': + Gbl_WarningLevel = ASL_WARNING; + break; + + case '2': + Gbl_WarningLevel = ASL_WARNING2; + break; + + case '3': + Gbl_WarningLevel = ASL_WARNING3; + break; + + default: + printf ("Unknown option: -w%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + + case 'x': + + AcpiDbgLevel = strtoul (AcpiGbl_Optarg, NULL, 16); + break; + + + case 'z': + + Gbl_UseOriginalCompilerId = TRUE; + break; + + + default: + + return (-1); + } + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: AslCommandLine + * + * PARAMETERS: argc/argv + * + * RETURN: Last argv index + * + * DESCRIPTION: Command line processing + * + ******************************************************************************/ + +static int +AslCommandLine ( + int argc, + char **argv) +{ + int BadCommandLine = 0; + ACPI_STATUS Status; + + + /* Minimum command line contains at least the command and an input file */ + + if (argc < 2) + { + printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); + Usage (); + exit (1); + } + + /* Process all command line options */ + + BadCommandLine = AslDoOptions (argc, argv, FALSE); + + if (Gbl_DoTemplates) + { + Status = DtCreateTemplates (Gbl_TemplateSignature); + if (ACPI_FAILURE (Status)) + { + exit (-1); + } + exit (1); + } + + /* Next parameter must be the input filename */ + + if (!argv[AcpiGbl_Optind] && + !Gbl_DisasmFlag && + !Gbl_GetAllTables) + { + printf ("Missing input filename\n"); + BadCommandLine = TRUE; + } + + if (Gbl_DoSignon) + { + printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); + if (Gbl_IgnoreErrors) + { + printf ("Ignoring all errors, forcing AML file generation\n\n"); + } + } + + /* Abort if anything went wrong on the command line */ + + if (BadCommandLine) + { + printf ("\n"); + Usage (); + exit (1); + } + + return (AcpiGbl_Optind); +} + + +/******************************************************************************* + * + * FUNCTION: main + * + * PARAMETERS: Standard argc/argv + * + * RETURN: Program termination code + * + * DESCRIPTION: C main routine for the Asl Compiler. Handle command line + * options and begin the compile for each file on the command line + * + ******************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char **argv) +{ + ACPI_STATUS Status; + int Index1; + int Index2; + + + AcpiGbl_ExternalFileList = NULL; + +#ifdef _DEBUG + _CrtSetDbgFlag (_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | + _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); +#endif + + /* Init and command line */ + + AslInitialize (); + Index1 = Index2 = AslCommandLine (argc, argv); + + /* Options that have no additional parameters or pathnames */ + + if (Gbl_GetAllTables) + { + Status = AslDoOneFile (NULL); + if (ACPI_FAILURE (Status)) + { + return (-1); + } + return (0); + } + + if (Gbl_DisassembleAll) + { + while (argv[Index1]) + { + Status = AslDoOnePathname (argv[Index1], AcpiDmAddToExternalFileList); + if (ACPI_FAILURE (Status)) + { + return (-1); + } + + Index1++; + } + } + + /* Process each pathname/filename in the list, with possible wildcards */ + + while (argv[Index2]) + { + Status = AslDoOnePathname (argv[Index2], AslDoOneFile); + if (ACPI_FAILURE (Status)) + { + return (-1); + } + + Index2++; + } + + if (AcpiGbl_ExternalFileList) + { + AcpiDmClearExternalFileList(); + } + + return (0); +} + + diff --git a/source/compiler/aslmap.c b/source/compiler/aslmap.c new file mode 100644 index 000000000000..aa8894a02291 --- /dev/null +++ b/source/compiler/aslmap.c @@ -0,0 +1,456 @@ + +/****************************************************************************** + * + * Module Name: aslmap - parser to AML opcode mapping table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "amlcode.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslmap") + + +/******************************************************************************* + * + * FUNCTION: AslMapNamedOpcodeToDataType + * + * PARAMETERS: Opcode - The Named AML opcode to map + * + * RETURN: The ACPI type associated with the named opcode + * + * DESCRIPTION: Convert a raw Named AML opcode to the associated data type. + * Named opcodes are a subset of the AML opcodes. + * + ******************************************************************************/ + +ACPI_OBJECT_TYPE +AslMapNamedOpcodeToDataType ( + UINT16 Opcode) +{ + const ACPI_OPCODE_INFO *OpInfo; + + + /* + * There are some differences from the opcode table types, we + * catch them here. + */ + OpInfo = AcpiPsGetOpcodeInfo (Opcode); + + if (Opcode == AML_INT_NAMEPATH_OP) + { + return (ACPI_TYPE_ANY); + } + + if (Opcode == AML_INT_METHODCALL_OP) + { + return (ACPI_TYPE_ANY); + } + + if (OpInfo->Flags & AML_NSOBJECT) + { + return (OpInfo->ObjectType); + } + + return (ACPI_TYPE_ANY); +} + + +/******************************************************************************* + * + * DATA STRUCTURE: AslKeywordMapping + * + * DESCRIPTION: Maps the ParseOpcode to the actual AML opcode. The parse + * opcodes are generated from Bison, and this table must + * track any additions to them. + * + * Each entry in the table contains the following items: + * + * AML opcode - Opcode that is written to the AML file + * Value - Value of the object to be written (if applicable) + * Flags - 1) Whether this opcode opens an AML "package". + * + ******************************************************************************/ +/* + * TBD: + * AccessAttrib + * AccessType + * AMlop for DMA? + * ObjectType keywords + * Register + */ + +const ASL_MAPPING_ENTRY AslKeywordMapping [] = +{ +/*! [Begin] no source code translation (keep the table structure) */ + + +/* ACCESSAS */ OP_TABLE_ENTRY (AML_INT_ACCESSFIELD_OP, 0, 0, 0), +/* ACCESSATTRIB_BLOCK */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_BLOCK, 0, 0), +/* ACCESSATTRIB_BLOCK_CALL */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_BLOCK_CALL, 0, 0), +/* ACCESSATTRIB_BYTE */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_BYTE, 0, 0), +/* ACCESSATTRIB_MULTIBYTE */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_MULTIBYTE, 0, 0), +/* ACCESSATTRIB_QUICK */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_QUICK, 0, 0), +/* ACCESSATTRIB_RAW_BYTES */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_RAW_BYTES, 0, 0), +/* ACCESSATTRIB_RAW_PROCESS */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_RAW_PROCESS, 0, 0), +/* ACCESSATTRIB_SND_RCV */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_SEND_RCV, 0, 0), +/* ACCESSATTRIB_WORD */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_WORD, 0, 0), +/* ACCESSATTRIB_WORD_CALL */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ATTRIB_WORD_CALL, 0, 0), +/* ACCESSTYPE_ANY */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_ANY, 0, 0), +/* ACCESSTYPE_BUF */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_BUFFER, 0, 0), +/* ACCESSTYPE_BYTE */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_BYTE, 0, 0), +/* ACCESSTYPE_DWORD */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_DWORD, 0, 0), +/* ACCESSTYPE_QWORD */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_QWORD, 0, 0), +/* ACCESSTYPE_WORD */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_ACCESS_WORD, 0, 0), +/* ACQUIRE */ OP_TABLE_ENTRY (AML_ACQUIRE_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ADD */ OP_TABLE_ENTRY (AML_ADD_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ADDRESSINGMODE_7BIT */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* ADDRESSINGMODE_10BIT */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* ADDRESSTYPE_ACPI */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* ADDRESSTYPE_MEMORY */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* ADDRESSTYPE_NVS */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* ADDRESSTYPE_RESERVED */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* ALIAS */ OP_TABLE_ENTRY (AML_ALIAS_OP, 0, 0, 0), +/* AND */ OP_TABLE_ENTRY (AML_BIT_AND_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ARG0 */ OP_TABLE_ENTRY (AML_ARG0, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG1 */ OP_TABLE_ENTRY (AML_ARG1, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG2 */ OP_TABLE_ENTRY (AML_ARG2, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG3 */ OP_TABLE_ENTRY (AML_ARG3, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG4 */ OP_TABLE_ENTRY (AML_ARG4, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG5 */ OP_TABLE_ENTRY (AML_ARG5, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* ARG6 */ OP_TABLE_ENTRY (AML_ARG6, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* BANKFIELD */ OP_TABLE_ENTRY (AML_BANK_FIELD_OP, 0, NODE_AML_PACKAGE, 0), +/* BITSPERBYTE_EIGHT */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* BITSPERBYTE_FIVE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* BITSPERBYTE_NINE */ OP_TABLE_ENTRY (AML_BYTE_OP, 4, 0, 0), +/* BITSPERBYTE_SEVEN */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* BITSPERBYTE_SIX */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* BREAK */ OP_TABLE_ENTRY (AML_BREAK_OP, 0, 0, 0), +/* BREAKPOINT */ OP_TABLE_ENTRY (AML_BREAK_POINT_OP, 0, 0, 0), +/* BUFFER */ OP_TABLE_ENTRY (AML_BUFFER_OP, 0, NODE_AML_PACKAGE, ACPI_BTYPE_BUFFER), +/* BUSMASTERTYPE_MASTER */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* BUSMASTERTYPE_NOTMASTER */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* BYTECONST */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, 0, 0, ACPI_BTYPE_INTEGER), +/* CASE */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* CLOCKPHASE_FIRST */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* CLOCKPHASE_SECOND */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* CLOCKPOLARITY_HIGH */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* CLOCKPOLARITY_LOW */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* CONCATENATE */ OP_TABLE_ENTRY (AML_CONCAT_OP, 0, 0, ACPI_BTYPE_COMPUTE_DATA), +/* CONCATENATERESTEMPLATE */ OP_TABLE_ENTRY (AML_CONCAT_RES_OP, 0, 0, ACPI_BTYPE_BUFFER), +/* CONDREFOF */ OP_TABLE_ENTRY (AML_COND_REF_OF_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* CONNECTION */ OP_TABLE_ENTRY (AML_INT_CONNECTION_OP, 0, 0, 0), +/* CONTINUE */ OP_TABLE_ENTRY (AML_CONTINUE_OP, 0, 0, 0), +/* COPY */ OP_TABLE_ENTRY (AML_COPY_OP, 0, 0, ACPI_BTYPE_DATA_REFERENCE), +/* CREATEBITFIELD */ OP_TABLE_ENTRY (AML_CREATE_BIT_FIELD_OP, 0, 0, 0), +/* CREATEBYTEFIELD */ OP_TABLE_ENTRY (AML_CREATE_BYTE_FIELD_OP, 0, 0, 0), +/* CREATEDWORDFIELD */ OP_TABLE_ENTRY (AML_CREATE_DWORD_FIELD_OP, 0, 0, 0), +/* CREATEFIELD */ OP_TABLE_ENTRY (AML_CREATE_FIELD_OP, 0, 0, 0), +/* CREATEQWORDFIELD */ OP_TABLE_ENTRY (AML_CREATE_QWORD_FIELD_OP, 0, 0, 0), +/* CREATEWORDFIELD */ OP_TABLE_ENTRY (AML_CREATE_WORD_FIELD_OP, 0, 0, 0), +/* DATABUFFER */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DATATABLEREGION */ OP_TABLE_ENTRY (AML_DATA_REGION_OP, 0, 0, 0), +/* DEBUG */ OP_TABLE_ENTRY (AML_DEBUG_OP, 0, 0, ACPI_BTYPE_DEBUG_OBJECT), +/* DECODETYPE_POS */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* DECODETYPE_SUB */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* DECREMENT */ OP_TABLE_ENTRY (AML_DECREMENT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* DEFAULT */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DEFAULT_ARG */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DEFINITIONBLOCK */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DEREFOF */ OP_TABLE_ENTRY (AML_DEREF_OF_OP, 0, 0, ACPI_BTYPE_DATA_REFERENCE | ACPI_BTYPE_STRING), +/* DEVICE */ OP_TABLE_ENTRY (AML_DEVICE_OP, 0, NODE_AML_PACKAGE, 0), +/* DEVICEPOLARITY_HIGH */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* DEVICEPOLARITY_LOW */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* DIVIDE */ OP_TABLE_ENTRY (AML_DIVIDE_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* DMA */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DMATYPE_A */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* DMATYPE_COMPATIBILITY */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* DMATYPE_B */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* DMATYPE_F */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* DWORDCONST */ OP_TABLE_ENTRY (AML_RAW_DATA_DWORD, 0, 0, ACPI_BTYPE_INTEGER), +/* DWORDIO */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DWORDMEMORY */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* DWORDSPACE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* EISAID */ OP_TABLE_ENTRY (AML_DWORD_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ELSE */ OP_TABLE_ENTRY (AML_ELSE_OP, 0, NODE_AML_PACKAGE, 0), +/* ELSEIF */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, NODE_AML_PACKAGE, 0), +/* ENDDEPENDENTFN */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* ENDIAN_BIG */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* ENDIAN_LITTLE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* ENDTAG */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* ERRORNODE */ OP_TABLE_ENTRY (AML_NOOP_OP, 0, 0, 0), +/* EVENT */ OP_TABLE_ENTRY (AML_EVENT_OP, 0, 0, 0), +/* EXTENDEDIO */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* EXTENDEDMEMORY */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* EXTENDEDSPACE */ OP_TABLE_ENTRY (AML_RAW_DATA_QWORD, 0, 0, ACPI_BTYPE_INTEGER), +/* EXTERNAL */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* FATAL */ OP_TABLE_ENTRY (AML_FATAL_OP, 0, 0, 0), +/* FIELD */ OP_TABLE_ENTRY (AML_FIELD_OP, 0, NODE_AML_PACKAGE, 0), +/* FINDSETLEFTBIT */ OP_TABLE_ENTRY (AML_FIND_SET_LEFT_BIT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* FINDSETRIGHTBIT */ OP_TABLE_ENTRY (AML_FIND_SET_RIGHT_BIT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* FIXEDDMA */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* FIXEDIO */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* FLOWCONTROL_HW */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* FLOWCONTROL_NONE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* FLOWCONTROL_SW */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* FROMBCD */ OP_TABLE_ENTRY (AML_FROM_BCD_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* FUNCTION */ OP_TABLE_ENTRY (AML_METHOD_OP, 0, NODE_AML_PACKAGE, 0), +/* GPIOINT */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* GPIOIO */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* I2CSERIALBUS */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* IF */ OP_TABLE_ENTRY (AML_IF_OP, 0, NODE_AML_PACKAGE, 0), +/* INCLUDE */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* INCLUDE_CSTYLE */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* INCLUDE_END */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* INCREMENT */ OP_TABLE_ENTRY (AML_INCREMENT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* INDEX */ OP_TABLE_ENTRY (AML_INDEX_OP, 0, 0, ACPI_BTYPE_REFERENCE), +/* INDEXFIELD */ OP_TABLE_ENTRY (AML_INDEX_FIELD_OP, 0, NODE_AML_PACKAGE, 0), +/* INTEGER */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* INTERRUPT */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* INTLEVEL_ACTIVEBOTH */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* INTLEVEL_ACTIVEHIGH */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* INTLEVEL_ACTIVELOW */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* INTTYPE_EDGE */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* INTTYPE_LEVEL */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* IO */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* IODECODETYPE_10 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* IODECODETYPE_16 */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* IORESTRICT_IN */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* IORESTRICT_NONE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* IORESTRICT_OUT */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* IORESTRICT_PRESERVE */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* IRQ */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* IRQNOFLAGS */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* LAND */ OP_TABLE_ENTRY (AML_LAND_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LEQUAL */ OP_TABLE_ENTRY (AML_LEQUAL_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LGREATER */ OP_TABLE_ENTRY (AML_LGREATER_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LGREATEREQUAL */ OP_TABLE_ENTRY (AML_LGREATEREQUAL_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LINE */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* LLESS */ OP_TABLE_ENTRY (AML_LLESS_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LLESSEQUAL */ OP_TABLE_ENTRY (AML_LLESSEQUAL_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LNOT */ OP_TABLE_ENTRY (AML_LNOT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LNOTEQUAL */ OP_TABLE_ENTRY (AML_LNOTEQUAL_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* LOAD */ OP_TABLE_ENTRY (AML_LOAD_OP, 0, 0, 0), +/* LOADTABLE */ OP_TABLE_ENTRY (AML_LOAD_TABLE_OP, 0, 0, ACPI_BTYPE_DDB_HANDLE), +/* LOCAL0 */ OP_TABLE_ENTRY (AML_LOCAL0, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL1 */ OP_TABLE_ENTRY (AML_LOCAL1, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL2 */ OP_TABLE_ENTRY (AML_LOCAL2, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL3 */ OP_TABLE_ENTRY (AML_LOCAL3, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL4 */ OP_TABLE_ENTRY (AML_LOCAL4, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL5 */ OP_TABLE_ENTRY (AML_LOCAL5, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL6 */ OP_TABLE_ENTRY (AML_LOCAL6, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCAL7 */ OP_TABLE_ENTRY (AML_LOCAL7, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* LOCKRULE_LOCK */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_LOCK_ALWAYS, 0, 0), +/* LOCKRULE_NOLOCK */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_LOCK_NEVER, 0, 0), +/* LOR */ OP_TABLE_ENTRY (AML_LOR_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* MATCH */ OP_TABLE_ENTRY (AML_MATCH_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MEQ */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MEQ, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MGE */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MGE, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MGT */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MGT, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MLE */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MLE, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MLT */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MLT, 0, ACPI_BTYPE_INTEGER), +/* MATCHTYPE_MTR */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, MATCH_MTR, 0, ACPI_BTYPE_INTEGER), +/* MAXTYPE_FIXED */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* MAXTYPE_NOTFIXED */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* MEMORY24 */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* MEMORY32 */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* MEMORY32FIXED */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* MEMTYPE_CACHEABLE */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* MEMTYPE_NONCACHEABLE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* MEMTYPE_PREFETCHABLE */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* MEMTYPE_WRITECOMBINING */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* METHOD */ OP_TABLE_ENTRY (AML_METHOD_OP, 0, NODE_AML_PACKAGE, 0), +/* METHODCALL */ OP_TABLE_ENTRY (AML_INT_METHODCALL_OP, 0, 0, ACPI_BTYPE_OBJECTS_AND_REFS), +/* MID */ OP_TABLE_ENTRY (AML_MID_OP, 0, 0, ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER), +/* MINTYPE_FIXED */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* MINTYPE_NOTFIXED */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* MOD */ OP_TABLE_ENTRY (AML_MOD_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* MULTIPLY */ OP_TABLE_ENTRY (AML_MULTIPLY_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* MUTEX */ OP_TABLE_ENTRY (AML_MUTEX_OP, 0, 0, 0), +/* NAME */ OP_TABLE_ENTRY (AML_NAME_OP, 0, 0, 0), +/* NAMESEG */ OP_TABLE_ENTRY (AML_INT_NAMEPATH_OP, 0, 0, 0), +/* NAMESTRING */ OP_TABLE_ENTRY (AML_INT_NAMEPATH_OP, 0, 0, 0), +/* NAND */ OP_TABLE_ENTRY (AML_BIT_NAND_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* NOOP */ OP_TABLE_ENTRY (AML_NOOP_OP, 0, 0, 0), +/* NOR */ OP_TABLE_ENTRY (AML_BIT_NOR_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* NOT */ OP_TABLE_ENTRY (AML_BIT_NOT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* NOTIFY */ OP_TABLE_ENTRY (AML_NOTIFY_OP, 0, 0, 0), +/* OBJECTTYPE */ OP_TABLE_ENTRY (AML_TYPE_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* OBJECTTYPE_BFF */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_BUFFER_FIELD, 0, 0), +/* OBJECTTYPE_BUF */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_BUFFER, 0, 0), +/* OBJECTTYPE_DDB */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_DDB_HANDLE, 0, 0), +/* OBJECTTYPE_DEV */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_DEVICE, 0, 0), +/* OBJECTTYPE_EVT */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_EVENT, 0, 0), +/* OBJECTTYPE_FLD */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_FIELD_UNIT, 0, 0), +/* OBJECTTYPE_INT */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_INTEGER, 0, 0), +/* OBJECTTYPE_MTH */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_METHOD, 0, 0), +/* OBJECTTYPE_MTX */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_MUTEX, 0, 0), +/* OBJECTTYPE_OPR */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_REGION, 0, 0), +/* OBJECTTYPE_PKG */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_PACKAGE, 0, 0), +/* OBJECTTYPE_POW */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_POWER, 0, 0), +/* OBJECTTYPE_PRO */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_PROCESSOR, 0, 0), +/* OBJECTTYPE_STR */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_STRING, 0, 0), +/* OBJECTTYPE_THZ */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_THERMAL, 0, 0), +/* OBJECTTYPE_UNK */ OP_TABLE_ENTRY (AML_BYTE_OP, ACPI_TYPE_ANY, 0, 0), +/* OFFSET */ OP_TABLE_ENTRY (AML_INT_RESERVEDFIELD_OP, 0, 0, 0), +/* ONE */ OP_TABLE_ENTRY (AML_ONE_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ONES */ OP_TABLE_ENTRY (AML_ONES_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* OPERATIONREGION */ OP_TABLE_ENTRY (AML_REGION_OP, 0, 0, 0), +/* OR */ OP_TABLE_ENTRY (AML_BIT_OR_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* PACKAGE */ OP_TABLE_ENTRY (AML_PACKAGE_OP, 0, NODE_AML_PACKAGE, ACPI_BTYPE_PACKAGE), +/* PACKAGEP_LENGTH */ OP_TABLE_ENTRY (AML_PACKAGE_LENGTH, 0, NODE_AML_PACKAGE, 0), +/* PARITYTYPE_EVEN */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* PARITYTYPE_MARK */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* PARITYTYPE_NONE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* PARITYTYPE_ODD */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* PARITYTYPE_SPACE */ OP_TABLE_ENTRY (AML_BYTE_OP, 4, 0, 0), +/* PIN_NOPULL */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* PIN_PULLDEFAULT */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* PIN_PULLDOWN */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* PIN_PULLUP */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* POWERRESOURCE */ OP_TABLE_ENTRY (AML_POWER_RES_OP, 0, NODE_AML_PACKAGE, 0), +/* PROCESSOR */ OP_TABLE_ENTRY (AML_PROCESSOR_OP, 0, NODE_AML_PACKAGE, 0), +/* QWORDCONST */ OP_TABLE_ENTRY (AML_RAW_DATA_QWORD, 0, 0, ACPI_BTYPE_INTEGER), +/* QWORDIO */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* QWORDMEMORY */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* QWORDSPACE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* RANGE_TYPE_ENTIRE */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* RANGE_TYPE_ISAONLY */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* RANGE_TYPE_NONISAONLY */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* RAW_DATA */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* READWRITETYPE_BOTH */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* READWRITETYPE_READONLY */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* REFOF */ OP_TABLE_ENTRY (AML_REF_OF_OP, 0, 0, ACPI_BTYPE_REFERENCE), +/* REGIONSPACE_CMOS */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_CMOS, 0, 0), +/* REGIONSPACE_EC */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_EC, 0, 0), +/* REGIONSPACE_FFIXEDHW */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_FIXED_HARDWARE, 0, 0), +/* REGIONSPACE_GPIO */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_GPIO, 0, 0), +/* REGIONSPACE_GSBUS */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_GSBUS, 0, 0), +/* REGIONSPACE_IO */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0), +/* REGIONSPACE_IPMI */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_IPMI, 0, 0), +/* REGIONSPACE_MEM */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_SYSTEM_MEMORY, 0, 0), +/* REGIONSPACE_PCI */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_PCI_CONFIG, 0, 0), +/* REGIONSPACE_PCIBAR */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_PCI_BAR_TARGET, 0, 0), +/* REGIONSPACE_SMBUS */ OP_TABLE_ENTRY (AML_RAW_DATA_BYTE, ACPI_ADR_SPACE_SMBUS, 0, 0), +/* REGISTER */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* RELEASE */ OP_TABLE_ENTRY (AML_RELEASE_OP, 0, 0, 0), +/* RESERVED_BYTES */ OP_TABLE_ENTRY (AML_INT_RESERVEDFIELD_OP, 0, 0, 0), +/* RESET */ OP_TABLE_ENTRY (AML_RESET_OP, 0, 0, 0), +/* RESOURCETEMPLATE */ OP_TABLE_ENTRY (AML_BUFFER_OP, 0, 0, ACPI_BTYPE_BUFFER), +/* RESOURCETYPE_CONSUMER */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* RESOURCETYPE_PRODUCER */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* RETURN */ OP_TABLE_ENTRY (AML_RETURN_OP, 0, 0, 0), +/* REVISION */ OP_TABLE_ENTRY (AML_REVISION_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* SCOPE */ OP_TABLE_ENTRY (AML_SCOPE_OP, 0, NODE_AML_PACKAGE, 0), +/* SERIALIZERULE_NOTSERIAL */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* SERIALIZERULE_SERIAL */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* SHARETYPE_EXCLUSIVE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* SHARETYPE_EXCLUSIVEWAKE */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* SHARETYPE_SHARED */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* SHARETYPE_SHAREDWAKE */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* SHIFTLEFT */ OP_TABLE_ENTRY (AML_SHIFT_LEFT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* SHIFTRIGHT */ OP_TABLE_ENTRY (AML_SHIFT_RIGHT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* SIGNAL */ OP_TABLE_ENTRY (AML_SIGNAL_OP, 0, 0, 0), +/* SIZEOF */ OP_TABLE_ENTRY (AML_SIZE_OF_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* SLAVEMODE_CONTROLLERINIT */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* SLAVEMODE_DEVICEINIT */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* SLEEP */ OP_TABLE_ENTRY (AML_SLEEP_OP, 0, 0, 0), +/* SPISERIALBUS */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* STALL */ OP_TABLE_ENTRY (AML_STALL_OP, 0, 0, 0), +/* STARTDEPENDENTFN */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* STARTDEPENDENTFN_NOPRI */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* STOPBITS_ONE */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* STOPBITS_ONEPLUSHALF */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* STOPBITS_TWO */ OP_TABLE_ENTRY (AML_BYTE_OP, 3, 0, 0), +/* STOPBITS_ZERO */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* STORE */ OP_TABLE_ENTRY (AML_STORE_OP, 0, 0, ACPI_BTYPE_DATA_REFERENCE), +/* STRING_LITERAL */ OP_TABLE_ENTRY (AML_STRING_OP, 0, 0, ACPI_BTYPE_STRING), +/* SUBTRACT */ OP_TABLE_ENTRY (AML_SUBTRACT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* SWITCH */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* THERMALZONE */ OP_TABLE_ENTRY (AML_THERMAL_ZONE_OP, 0, NODE_AML_PACKAGE, 0), +/* TIMER */ OP_TABLE_ENTRY (AML_TIMER_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* TOBCD */ OP_TABLE_ENTRY (AML_TO_BCD_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* TOBUFFER */ OP_TABLE_ENTRY (AML_TO_BUFFER_OP, 0, 0, ACPI_BTYPE_BUFFER), +/* TODECIMALSTRING */ OP_TABLE_ENTRY (AML_TO_DECSTRING_OP, 0, 0, ACPI_BTYPE_STRING), +/* TOHEXSTRING */ OP_TABLE_ENTRY (AML_TO_HEXSTRING_OP, 0, 0, ACPI_BTYPE_STRING), +/* TOINTEGER */ OP_TABLE_ENTRY (AML_TO_INTEGER_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* TOSTRING */ OP_TABLE_ENTRY (AML_TO_STRING_OP, 0, 0, ACPI_BTYPE_STRING), +/* TOUUID */ OP_TABLE_ENTRY (AML_DWORD_OP, 0, NODE_AML_PACKAGE, ACPI_BTYPE_INTEGER), +/* TRANSLATIONTYPE_DENSE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* TRANSLATIONTYPE_SPARSE */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* TYPE_STATIC */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* TYPE_TRANSLATION */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* UART_SERIALBUS */ OP_TABLE_ENTRY (AML_DEFAULT_ARG_OP, 0, 0, 0), +/* UNICODE */ OP_TABLE_ENTRY (AML_BUFFER_OP, 0, NODE_AML_PACKAGE, 0), +/* UNLOAD */ OP_TABLE_ENTRY (AML_UNLOAD_OP, 0, 0, 0), +/* UPDATERULE_ONES */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_UPDATE_WRITE_AS_ONES, 0, 0), +/* UPDATERULE_PRESERVE */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_UPDATE_PRESERVE, 0, 0), +/* UPDATERULE_ZEROS */ OP_TABLE_ENTRY (AML_BYTE_OP, AML_FIELD_UPDATE_WRITE_AS_ZEROS,0, 0), +/* VAR_PACKAGE */ OP_TABLE_ENTRY (AML_VAR_PACKAGE_OP, 0, NODE_AML_PACKAGE, ACPI_BTYPE_PACKAGE), +/* VENDORLONG */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* VENDORSHORT */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* WAIT */ OP_TABLE_ENTRY (AML_WAIT_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* WHILE */ OP_TABLE_ENTRY (AML_WHILE_OP, 0, NODE_AML_PACKAGE, 0), +/* WIREMODE_FOUR */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* WIREMODE_THREE */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* WORDBUSNUMBER */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* WORDCONST */ OP_TABLE_ENTRY (AML_RAW_DATA_WORD, 0, 0, ACPI_BTYPE_INTEGER), +/* WORDIO */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* WORDSPACE */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_8 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_16 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_32 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_64 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_128 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERSIZE_256 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERTYPE_8 */ OP_TABLE_ENTRY (AML_BYTE_OP, 0, 0, 0), +/* XFERTYPE_8_16 */ OP_TABLE_ENTRY (AML_BYTE_OP, 1, 0, 0), +/* XFERTYPE_16 */ OP_TABLE_ENTRY (AML_BYTE_OP, 2, 0, 0), +/* XOR */ OP_TABLE_ENTRY (AML_BIT_XOR_OP, 0, 0, ACPI_BTYPE_INTEGER), +/* ZERO */ OP_TABLE_ENTRY (AML_ZERO_OP, 0, 0, ACPI_BTYPE_INTEGER), + +/*! [End] no source code translation !*/ + +}; + + diff --git a/source/compiler/aslmessages.h b/source/compiler/aslmessages.h new file mode 100644 index 000000000000..f96e6f1ea554 --- /dev/null +++ b/source/compiler/aslmessages.h @@ -0,0 +1,391 @@ + +/****************************************************************************** + * + * Module Name: aslmessages.h - Compiler error/warning messages + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ASLMESSAGES_H +#define __ASLMESSAGES_H + + +#define ASL_WARNING 0 +#define ASL_WARNING2 1 +#define ASL_WARNING3 2 +#define ASL_ERROR 3 +#define ASL_REMARK 4 +#define ASL_OPTIMIZATION 5 +#define ASL_NUM_REPORT_LEVELS 6 + + +/* Values for all compiler messages */ + +typedef enum +{ + ASL_MSG_RESERVED = 0, + + ASL_MSG_ALIGNMENT, + ASL_MSG_ALPHANUMERIC_STRING, + ASL_MSG_AML_NOT_IMPLEMENTED, + ASL_MSG_ARG_COUNT_HI, + ASL_MSG_ARG_COUNT_LO, + ASL_MSG_ARG_INIT, + ASL_MSG_BACKWARDS_OFFSET, + ASL_MSG_BUFFER_LENGTH, + ASL_MSG_CLOSE, + ASL_MSG_COMPILER_INTERNAL, + ASL_MSG_COMPILER_RESERVED, + ASL_MSG_CONNECTION_MISSING, + ASL_MSG_CONNECTION_INVALID, + ASL_MSG_CONSTANT_EVALUATION, + ASL_MSG_CONSTANT_FOLDED, + ASL_MSG_CORE_EXCEPTION, + ASL_MSG_DEBUG_FILE_OPEN, + ASL_MSG_DEBUG_FILENAME, + ASL_MSG_DEPENDENT_NESTING, + ASL_MSG_DMA_CHANNEL, + ASL_MSG_DMA_LIST, + ASL_MSG_DUPLICATE_CASE, + ASL_MSG_DUPLICATE_ITEM, + ASL_MSG_EARLY_EOF, + ASL_MSG_ENCODING_LENGTH, + ASL_MSG_EX_INTERRUPT_LIST, + ASL_MSG_EX_INTERRUPT_LIST_MIN, + ASL_MSG_EX_INTERRUPT_NUMBER, + ASL_MSG_FIELD_ACCESS_WIDTH, + ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, + ASL_MSG_FIELD_UNIT_OFFSET, + ASL_MSG_GPE_NAME_CONFLICT, + ASL_MSG_HID_LENGTH, + ASL_MSG_HID_PREFIX, + ASL_MSG_HID_SUFFIX, + ASL_MSG_INCLUDE_FILE_OPEN, + ASL_MSG_INPUT_FILE_OPEN, + ASL_MSG_INTEGER_LENGTH, + ASL_MSG_INTEGER_OPTIMIZATION, + ASL_MSG_INTERRUPT_LIST, + ASL_MSG_INTERRUPT_NUMBER, + ASL_MSG_INVALID_ACCESS_SIZE, + ASL_MSG_INVALID_ADDR_FLAGS, + ASL_MSG_INVALID_CONSTANT_OP, + ASL_MSG_INVALID_EISAID, + ASL_MSG_INVALID_ESCAPE, + ASL_MSG_INVALID_GRAN_FIXED, + ASL_MSG_INVALID_GRANULARITY, + ASL_MSG_INVALID_LENGTH, + ASL_MSG_INVALID_LENGTH_FIXED, + ASL_MSG_INVALID_MIN_MAX, + ASL_MSG_INVALID_OPERAND, + ASL_MSG_INVALID_PERFORMANCE, + ASL_MSG_INVALID_PRIORITY, + ASL_MSG_INVALID_STRING, + ASL_MSG_INVALID_TARGET, + ASL_MSG_INVALID_TIME, + ASL_MSG_INVALID_TYPE, + ASL_MSG_INVALID_UUID, + ASL_MSG_ISA_ADDRESS, + ASL_MSG_LEADING_ASTERISK, + ASL_MSG_LIST_LENGTH_LONG, + ASL_MSG_LIST_LENGTH_SHORT, + ASL_MSG_LISTING_FILE_OPEN, + ASL_MSG_LISTING_FILENAME, + ASL_MSG_LOCAL_INIT, + ASL_MSG_LOCAL_OUTSIDE_METHOD, + ASL_MSG_LONG_LINE, + ASL_MSG_MEMORY_ALLOCATION, + ASL_MSG_MISSING_ENDDEPENDENT, + ASL_MSG_MISSING_STARTDEPENDENT, + ASL_MSG_MULTIPLE_DEFAULT, + ASL_MSG_MULTIPLE_TYPES, + ASL_MSG_NAME_EXISTS, + ASL_MSG_NAME_OPTIMIZATION, + ASL_MSG_NAMED_OBJECT_IN_WHILE, + ASL_MSG_NESTED_COMMENT, + ASL_MSG_NO_CASES, + ASL_MSG_NO_REGION, + ASL_MSG_NO_RETVAL, + ASL_MSG_NO_WHILE, + ASL_MSG_NON_ASCII, + ASL_MSG_NON_ZERO, + ASL_MSG_NOT_EXIST, + ASL_MSG_NOT_FOUND, + ASL_MSG_NOT_METHOD, + ASL_MSG_NOT_PARAMETER, + ASL_MSG_NOT_REACHABLE, + ASL_MSG_NOT_REFERENCED, + ASL_MSG_NULL_DESCRIPTOR, + ASL_MSG_NULL_STRING, + ASL_MSG_OPEN, + ASL_MSG_OUTPUT_FILE_OPEN, + ASL_MSG_OUTPUT_FILENAME, + ASL_MSG_PACKAGE_LENGTH, + ASL_MSG_READ, + ASL_MSG_RECURSION, + ASL_MSG_REGION_BUFFER_ACCESS, + ASL_MSG_REGION_BYTE_ACCESS, + ASL_MSG_RESERVED_ARG_COUNT_HI, + ASL_MSG_RESERVED_ARG_COUNT_LO, + ASL_MSG_RESERVED_METHOD, + ASL_MSG_RESERVED_NO_RETURN_VAL, + ASL_MSG_RESERVED_OPERAND_TYPE, + ASL_MSG_RESERVED_RETURN_VALUE, + ASL_MSG_RESERVED_USE, + ASL_MSG_RESERVED_WORD, + ASL_MSG_RESOURCE_FIELD, + ASL_MSG_RESOURCE_INDEX, + ASL_MSG_RESOURCE_LIST, + ASL_MSG_RESOURCE_SOURCE, + ASL_MSG_RESULT_NOT_USED, + ASL_MSG_RETURN_TYPES, + ASL_MSG_SCOPE_FWD_REF, + ASL_MSG_SCOPE_TYPE, + ASL_MSG_SEEK, + ASL_MSG_SERIALIZED, + ASL_MSG_SINGLE_NAME_OPTIMIZATION, + ASL_MSG_SOME_NO_RETVAL, + ASL_MSG_STRING_LENGTH, + ASL_MSG_SWITCH_TYPE, + ASL_MSG_SYNC_LEVEL, + ASL_MSG_SYNTAX, + ASL_MSG_TABLE_SIGNATURE, + ASL_MSG_TAG_LARGER, + ASL_MSG_TAG_SMALLER, + ASL_MSG_TIMEOUT, + ASL_MSG_TOO_MANY_TEMPS, + ASL_MSG_UNKNOWN_RESERVED_NAME, + ASL_MSG_UNREACHABLE_CODE, + ASL_MSG_UNSUPPORTED, + ASL_MSG_UPPER_CASE, + ASL_MSG_VENDOR_LIST, + ASL_MSG_WRITE, + +/* These messages are used by the data table compiler only */ + + ASL_MSG_BUFFER_ELEMENT, + ASL_MSG_DIVIDE_BY_ZERO, + ASL_MSG_FLAG_VALUE, + ASL_MSG_INTEGER_SIZE, + ASL_MSG_INVALID_EXPRESSION, + ASL_MSG_INVALID_FIELD_NAME, + ASL_MSG_INVALID_HEX_INTEGER, + ASL_MSG_OEM_TABLE, + ASL_MSG_RESERVED_VALUE, + ASL_MSG_UNKNOWN_LABEL, + ASL_MSG_UNKNOWN_SUBTABLE, + ASL_MSG_UNKNOWN_TABLE, + ASL_MSG_ZERO_VALUE + +} ASL_MESSAGE_IDS; + + +#ifdef ASL_EXCEPTIONS + +/* Actual message strings for each compiler message */ + +char *AslMessages [] = { +/* The zeroth message is reserved */ "", +/* ASL_MSG_ALIGNMENT */ "Must be a multiple of alignment/granularity value", +/* ASL_MSG_ALPHANUMERIC_STRING */ "String must be entirely alphanumeric", +/* ASL_MSG_AML_NOT_IMPLEMENTED */ "Opcode is not implemented in compiler AML code generator", +/* ASL_MSG_ARG_COUNT_HI */ "Too many arguments", +/* ASL_MSG_ARG_COUNT_LO */ "Too few arguments", +/* ASL_MSG_ARG_INIT */ "Method argument is not initialized", +/* ASL_MSG_BACKWARDS_OFFSET */ "Invalid backwards offset", +/* ASL_MSG_BUFFER_LENGTH */ "Effective AML buffer length is zero", +/* ASL_MSG_CLOSE */ "Could not close file", +/* ASL_MSG_COMPILER_INTERNAL */ "Internal compiler error", +/* ASL_MSG_COMPILER_RESERVED */ "Use of compiler reserved name", +/* ASL_MSG_CONNECTION_MISSING */ "A Connection operator is required for this field SpaceId", +/* ASL_MSG_CONNECTION_INVALID */ "Invalid OpRegion SpaceId for use of Connection operator", +/* ASL_MSG_CONSTANT_EVALUATION */ "Could not evaluate constant expression", +/* ASL_MSG_CONSTANT_FOLDED */ "Constant expression evaluated and reduced", +/* ASL_MSG_CORE_EXCEPTION */ "From ACPI CA Subsystem", +/* ASL_MSG_DEBUG_FILE_OPEN */ "Could not open debug file", +/* ASL_MSG_DEBUG_FILENAME */ "Could not create debug filename", +/* ASL_MSG_DEPENDENT_NESTING */ "Dependent function macros cannot be nested",\ +/* ASL_MSG_DMA_CHANNEL */ "Invalid DMA channel (must be 0-7)", +/* ASL_MSG_DMA_LIST */ "Too many DMA channels (8 max)", +/* ASL_MSG_DUPLICATE_CASE */ "Case value already specified", +/* ASL_MSG_DUPLICATE_ITEM */ "Duplicate value in list", +/* ASL_MSG_EARLY_EOF */ "Premature end-of-file reached", +/* ASL_MSG_ENCODING_LENGTH */ "Package length too long to encode", +/* ASL_MSG_EX_INTERRUPT_LIST */ "Too many interrupts (255 max)", +/* ASL_MSG_EX_INTERRUPT_LIST_MIN */ "Too few interrupts (1 minimum required)", +/* ASL_MSG_EX_INTERRUPT_NUMBER */ "Invalid interrupt number (must be 32 bits)", +/* ASL_MSG_FIELD_ACCESS_WIDTH */ "Access width is greater than region size", +/* ASL_MSG_FIELD_UNIT_ACCESS_WIDTH */ "Access width of Field Unit extends beyond region limit", +/* ASL_MSG_FIELD_UNIT_OFFSET */ "Field Unit extends beyond region limit", +/* ASL_MSG_GPE_NAME_CONFLICT */ "Name conflicts with a previous GPE method", +/* ASL_MSG_HID_LENGTH */ "_HID string must be exactly 7 or 8 characters", +/* ASL_MSG_HID_PREFIX */ "_HID prefix must be all uppercase or decimal digits", +/* ASL_MSG_HID_SUFFIX */ "_HID suffix must be all hex digits", +/* ASL_MSG_INCLUDE_FILE_OPEN */ "Could not open include file", +/* ASL_MSG_INPUT_FILE_OPEN */ "Could not open input file", +/* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating", +/* ASL_MSG_INTEGER_OPTIMIZATION */ "Integer optimized to single-byte AML opcode", +/* ASL_MSG_INTERRUPT_LIST */ "Too many interrupts (16 max)", +/* ASL_MSG_INTERRUPT_NUMBER */ "Invalid interrupt number (must be 0-15)", +/* ASL_MSG_INVALID_ACCESS_SIZE */ "Invalid AccessSize (Maximum is 4 - QWord access)", +/* ASL_MSG_INVALID_ADDR_FLAGS */ "Invalid combination of Length and Min/Max fixed flags", +/* ASL_MSG_INVALID_CONSTANT_OP */ "Invalid operator in constant expression (not type 3/4/5)", +/* ASL_MSG_INVALID_EISAID */ "EISAID string must be of the form \"UUUXXXX\" (3 uppercase, 4 hex digits)", +/* ASL_MSG_INVALID_ESCAPE */ "Invalid or unknown escape sequence", +/* ASL_MSG_INVALID_GRAN_FIXED */ "Granularity must be zero for fixed Min/Max", +/* ASL_MSG_INVALID_GRANULARITY */ "Granularity must be zero or a power of two minus one", +/* ASL_MSG_INVALID_LENGTH */ "Length is larger than Min/Max window", +/* ASL_MSG_INVALID_LENGTH_FIXED */ "Length is not equal to fixed Min/Max window", +/* ASL_MSG_INVALID_MIN_MAX */ "Address Min is greater than Address Max", +/* ASL_MSG_INVALID_OPERAND */ "Invalid operand", +/* ASL_MSG_INVALID_PERFORMANCE */ "Invalid performance/robustness value", +/* ASL_MSG_INVALID_PRIORITY */ "Invalid priority value", +/* ASL_MSG_INVALID_STRING */ "Invalid Hex/Octal Escape - Non-ASCII or NULL", +/* ASL_MSG_INVALID_TARGET */ "Target operand not allowed in constant expression", +/* ASL_MSG_INVALID_TIME */ "Time parameter too long (255 max)", +/* ASL_MSG_INVALID_TYPE */ "Invalid type", +/* ASL_MSG_INVALID_UUID */ "UUID string must be of the form \"aabbccdd-eeff-gghh-iijj-kkllmmnnoopp\"", +/* ASL_MSG_ISA_ADDRESS */ "Maximum 10-bit ISA address (0x3FF)", +/* ASL_MSG_LEADING_ASTERISK */ "Invalid leading asterisk", +/* ASL_MSG_LIST_LENGTH_LONG */ "Initializer list longer than declared package length", +/* ASL_MSG_LIST_LENGTH_SHORT */ "Initializer list shorter than declared package length", +/* ASL_MSG_LISTING_FILE_OPEN */ "Could not open listing file", +/* ASL_MSG_LISTING_FILENAME */ "Could not create listing filename", +/* ASL_MSG_LOCAL_INIT */ "Method local variable is not initialized", +/* ASL_MSG_LOCAL_OUTSIDE_METHOD */ "Local or Arg used outside a control method", +/* ASL_MSG_LONG_LINE */ "Splitting long input line", +/* ASL_MSG_MEMORY_ALLOCATION */ "Memory allocation failure", +/* ASL_MSG_MISSING_ENDDEPENDENT */ "Missing EndDependentFn() macro in dependent resource list", +/* ASL_MSG_MISSING_STARTDEPENDENT */ "Missing StartDependentFn() macro in dependent resource list", +/* ASL_MSG_MULTIPLE_DEFAULT */ "More than one Default statement within Switch construct", +/* ASL_MSG_MULTIPLE_TYPES */ "Multiple types", +/* ASL_MSG_NAME_EXISTS */ "Name already exists in scope", +/* ASL_MSG_NAME_OPTIMIZATION */ "NamePath optimized", +/* ASL_MSG_NAMED_OBJECT_IN_WHILE */ "Creating a named object in a While loop", +/* ASL_MSG_NESTED_COMMENT */ "Nested comment found", +/* ASL_MSG_NO_CASES */ "No Case statements under Switch", +/* ASL_MSG_NO_REGION */ "_REG has no corresponding Operation Region", +/* ASL_MSG_NO_RETVAL */ "Called method returns no value", +/* ASL_MSG_NO_WHILE */ "No enclosing While statement", +/* ASL_MSG_NON_ASCII */ "Invalid characters found in file", +/* ASL_MSG_NON_ZERO */ "Operand evaluates to zero", +/* ASL_MSG_NOT_EXIST */ "Object does not exist", +/* ASL_MSG_NOT_FOUND */ "Object not found or not accessible from scope", +/* ASL_MSG_NOT_METHOD */ "Not a control method, cannot invoke", +/* ASL_MSG_NOT_PARAMETER */ "Not a parameter, used as local only", +/* ASL_MSG_NOT_REACHABLE */ "Object is not accessible from this scope", +/* ASL_MSG_NOT_REFERENCED */ "Namespace object is not referenced", +/* ASL_MSG_NULL_DESCRIPTOR */ "Min/Max/Length/Gran are all zero, but no resource tag", +/* ASL_MSG_NULL_STRING */ "Invalid zero-length (null) string", +/* ASL_MSG_OPEN */ "Could not open file", +/* ASL_MSG_OUTPUT_FILE_OPEN */ "Could not open output AML file", +/* ASL_MSG_OUTPUT_FILENAME */ "Could not create output filename", +/* ASL_MSG_PACKAGE_LENGTH */ "Effective AML package length is zero", +/* ASL_MSG_READ */ "Could not read file", +/* ASL_MSG_RECURSION */ "Recursive method call", +/* ASL_MSG_REGION_BUFFER_ACCESS */ "Host Operation Region requires BufferAcc access", +/* ASL_MSG_REGION_BYTE_ACCESS */ "Host Operation Region requires ByteAcc access", +/* ASL_MSG_RESERVED_ARG_COUNT_HI */ "Reserved method has too many arguments", +/* ASL_MSG_RESERVED_ARG_COUNT_LO */ "Reserved method has too few arguments", +/* ASL_MSG_RESERVED_METHOD */ "Reserved name must be a control method", +/* ASL_MSG_RESERVED_NO_RETURN_VAL */ "Reserved method should not return a value", +/* ASL_MSG_RESERVED_OPERAND_TYPE */ "Invalid object type for reserved name", +/* ASL_MSG_RESERVED_RETURN_VALUE */ "Reserved method must return a value", +/* ASL_MSG_RESERVED_USE */ "Invalid use of reserved name", +/* ASL_MSG_RESERVED_WORD */ "Use of reserved name", +/* ASL_MSG_RESOURCE_FIELD */ "Resource field name cannot be used as a target", +/* ASL_MSG_RESOURCE_INDEX */ "Missing ResourceSourceIndex (required)", +/* ASL_MSG_RESOURCE_LIST */ "Too many resource items (internal error)", +/* ASL_MSG_RESOURCE_SOURCE */ "Missing ResourceSource string (required)", +/* ASL_MSG_RESULT_NOT_USED */ "Result is not used, operator has no effect", +/* ASL_MSG_RETURN_TYPES */ "Not all control paths return a value", +/* ASL_MSG_SCOPE_FWD_REF */ "Forward references from Scope operator not allowed", +/* ASL_MSG_SCOPE_TYPE */ "Existing object has invalid type for Scope operator", +/* ASL_MSG_SEEK */ "Could not seek file", +/* ASL_MSG_SERIALIZED */ "Control Method marked Serialized", +/* ASL_MSG_SINGLE_NAME_OPTIMIZATION */ "NamePath optimized to NameSeg (uses run-time search path)", +/* ASL_MSG_SOME_NO_RETVAL */ "Called method may not always return a value", +/* ASL_MSG_STRING_LENGTH */ "String literal too long", +/* ASL_MSG_SWITCH_TYPE */ "Switch expression is not a static Integer/Buffer/String data type, defaulting to Integer", +/* ASL_MSG_SYNC_LEVEL */ "SyncLevel must be in the range 0-15", +/* ASL_MSG_SYNTAX */ "", +/* ASL_MSG_TABLE_SIGNATURE */ "Invalid Table Signature", +/* ASL_MSG_TAG_LARGER */ "ResourceTag larger than Field", +/* ASL_MSG_TAG_SMALLER */ "ResourceTag smaller than Field", +/* ASL_MSG_TIMEOUT */ "Result is not used, possible operator timeout will be missed", +/* ASL_MSG_TOO_MANY_TEMPS */ "Method requires too many temporary variables (_T_x)", +/* ASL_MSG_UNKNOWN_RESERVED_NAME */ "Unknown reserved name", +/* ASL_MSG_UNREACHABLE_CODE */ "Statement is unreachable", +/* ASL_MSG_UNSUPPORTED */ "Unsupported feature", +/* ASL_MSG_UPPER_CASE */ "Non-hex letters must be upper case", +/* ASL_MSG_VENDOR_LIST */ "Too many vendor data bytes (7 max)", +/* ASL_MSG_WRITE */ "Could not write file", + +/* These messages are used by the data table compiler only */ + +/* ASL_MSG_BUFFER_ELEMENT */ "Invalid element in buffer initializer list", +/* ASL_MSG_DIVIDE_BY_ZERO */ "Expression contains divide-by-zero", +/* ASL_MSG_FLAG_VALUE */ "Flag value is too large", +/* ASL_MSG_INTEGER_SIZE */ "Integer too large for target", +/* ASL_MSG_INVALID_EXPRESSION */ "Invalid expression", +/* ASL_MSG_INVALID_FIELD_NAME */ "Invalid Field Name", +/* ASL_MSG_INVALID_HEX_INTEGER */ "Invalid hex integer constant", +/* ASL_MSG_OEM_TABLE */ "OEM table - unknown contents", +/* ASL_MSG_RESERVED_VALUE */ "Reserved field must be zero", +/* ASL_MSG_UNKNOWN_LABEL */ "Label is undefined", +/* ASL_MSG_UNKNOWN_SUBTABLE */ "Unknown subtable type", +/* ASL_MSG_UNKNOWN_TABLE */ "Unknown ACPI table signature", +/* ASL_MSG_ZERO_VALUE */ "Value must be non-zero" +}; + + +char *AslErrorLevel [ASL_NUM_REPORT_LEVELS] = { + "Warning ", + "Warning ", + "Warning ", + "Error ", + "Remark ", + "Optimize" +}; + +#define ASL_ERROR_LEVEL_LENGTH 8 /* Length of strings above */ + +#endif /* ASL_EXCEPTIONS */ + +#endif /* __ASLMESSAGES_H */ diff --git a/source/compiler/aslopcodes.c b/source/compiler/aslopcodes.c new file mode 100644 index 000000000000..9f3e15d6be81 --- /dev/null +++ b/source/compiler/aslopcodes.c @@ -0,0 +1,814 @@ + +/****************************************************************************** + * + * Module Name: aslopcode - AML opcode generation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslopcodes") + + +/* Local prototypes */ + +static void +OpcDoAccessAs ( + ACPI_PARSE_OBJECT *Op); + +static void +OpcDoConnection ( + ACPI_PARSE_OBJECT *Op); + +static void +OpcDoUnicode ( + ACPI_PARSE_OBJECT *Op); + +static void +OpcDoEisaId ( + ACPI_PARSE_OBJECT *Op); + +static void +OpcDoUuId ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: OpcAmlOpcodeUpdateWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Opcode update walk, ascending callback + * + ******************************************************************************/ + +ACPI_STATUS +OpcAmlOpcodeUpdateWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + /* + * Handle the Package() case where the actual opcode cannot be determined + * until the PackageLength operand has been folded and minimized. + * (PackageOp versus VarPackageOp) + * + * This is (as of ACPI 3.0) the only case where the AML opcode can change + * based upon the value of a parameter. + * + * The parser always inserts a VarPackage opcode, which can possibly be + * optimized to a Package opcode. + */ + if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE) + { + OpnDoPackage (Op); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: OpcAmlOpcodeWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML + * operands. + * + ******************************************************************************/ + +ACPI_STATUS +OpcAmlOpcodeWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + TotalParseNodes++; + + OpcGenerateAmlOpcode (Op); + OpnGenerateAmlOperands (Op); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: OpcGetIntegerWidth + * + * PARAMETERS: Op - DEFINITION BLOCK op + * + * RETURN: none + * + * DESCRIPTION: Extract integer width from the table revision + * + ******************************************************************************/ + +void +OpcGetIntegerWidth ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Child; + + + if (!Op) + { + return; + } + + if (Gbl_RevisionOverride) + { + AcpiUtSetIntegerWidth (Gbl_RevisionOverride); + } + else + { + Child = Op->Asl.Child; + Child = Child->Asl.Next; + Child = Child->Asl.Next; + + /* Use the revision to set the integer width */ + + AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer); + } +} + + +/******************************************************************************* + * + * FUNCTION: OpcSetOptimalIntegerSize + * + * PARAMETERS: Op - A parse tree node + * + * RETURN: Integer width, in bytes. Also sets the node AML opcode to the + * optimal integer AML prefix opcode. + * + * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading + * zeros can be truncated to squeeze the integer into the + * minimal number of AML bytes. + * + ******************************************************************************/ + +UINT32 +OpcSetOptimalIntegerSize ( + ACPI_PARSE_OBJECT *Op) +{ + +#if 0 + /* + * TBD: - we don't want to optimize integers in the block header, but the + * code below does not work correctly. + */ + if (Op->Asl.Parent && + Op->Asl.Parent->Asl.Parent && + (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) + { + return 0; + } +#endif + + /* + * Check for the special AML integers first - Zero, One, Ones. + * These are single-byte opcodes that are the smallest possible + * representation of an integer. + * + * This optimization is optional. + */ + if (Gbl_IntegerOptimizationFlag) + { + switch (Op->Asl.Value.Integer) + { + case 0: + + Op->Asl.AmlOpcode = AML_ZERO_OP; + AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, + Op, "Zero"); + return 1; + + case 1: + + Op->Asl.AmlOpcode = AML_ONE_OP; + AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, + Op, "One"); + return 1; + + case ACPI_UINT32_MAX: + + /* Check for table integer width (32 or 64) */ + + if (AcpiGbl_IntegerByteWidth == 4) + { + Op->Asl.AmlOpcode = AML_ONES_OP; + AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, + Op, "Ones"); + return 1; + } + break; + + case ACPI_UINT64_MAX: + + /* Check for table integer width (32 or 64) */ + + if (AcpiGbl_IntegerByteWidth == 8) + { + Op->Asl.AmlOpcode = AML_ONES_OP; + AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, + Op, "Ones"); + return 1; + } + break; + + default: + break; + } + } + + /* Find the best fit using the various AML integer prefixes */ + + if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX) + { + Op->Asl.AmlOpcode = AML_BYTE_OP; + return 1; + } + if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX) + { + Op->Asl.AmlOpcode = AML_WORD_OP; + return 2; + } + if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX) + { + Op->Asl.AmlOpcode = AML_DWORD_OP; + return 4; + } + else + { + if (AcpiGbl_IntegerByteWidth == 4) + { + AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH, + Op, NULL); + + if (!Gbl_IgnoreErrors) + { + /* Truncate the integer to 32-bit */ + Op->Asl.AmlOpcode = AML_DWORD_OP; + return 4; + } + } + + Op->Asl.AmlOpcode = AML_QWORD_OP; + return 8; + } +} + + +/******************************************************************************* + * + * FUNCTION: OpcDoAccessAs + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Implement the ACCESS_AS ASL keyword. + * + ******************************************************************************/ + +static void +OpcDoAccessAs ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *TypeOp; + ACPI_PARSE_OBJECT *AttribOp; + ACPI_PARSE_OBJECT *LengthOp; + UINT8 Attribute; + + + Op->Asl.AmlOpcodeLength = 1; + TypeOp = Op->Asl.Child; + + /* First child is the access type */ + + TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + + /* Second child is the optional access attribute */ + + AttribOp = TypeOp->Asl.Next; + if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + AttribOp->Asl.Value.Integer = 0; + } + AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + + /* Only a few AccessAttributes support AccessLength */ + + Attribute = (UINT8) AttribOp->Asl.Value.Integer; + if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) && + (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) && + (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS)) + { + return; + } + + Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP; + + /* + * Child of Attributes is the AccessLength (required for Multibyte, + * RawBytes, RawProcess.) + */ + LengthOp = AttribOp->Asl.Child; + if (!LengthOp) + { + return; + } + + /* TBD: probably can remove */ + + if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + LengthOp->Asl.Value.Integer = 16; + } + + LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; +} + + +/******************************************************************************* + * + * FUNCTION: OpcDoConnection + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Implement the Connection ASL keyword. + * + ******************************************************************************/ + +static void +OpcDoConnection ( + ACPI_PARSE_OBJECT *Op) +{ + ASL_RESOURCE_NODE *Rnode; + ACPI_PARSE_OBJECT *BufferOp; + ACPI_PARSE_OBJECT *BufferLengthOp; + ACPI_PARSE_OBJECT *BufferDataOp; + UINT8 State; + + + Op->Asl.AmlOpcodeLength = 1; + + if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP) + { + return; + } + + BufferOp = Op->Asl.Child; + BufferLengthOp = BufferOp->Asl.Child; + BufferDataOp = BufferLengthOp->Asl.Next; + + State = ACPI_RSTATE_NORMAL; + Rnode = RsDoOneResourceDescriptor (BufferDataOp->Asl.Next, 0, &State); + if (!Rnode) + { + return; /* error */ + } + + /* + * Transform the nodes into the following + * + * Op -> AML_BUFFER_OP + * First Child -> BufferLength + * Second Child -> Descriptor Buffer (raw byte data) + */ + BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER; + BufferOp->Asl.AmlOpcode = AML_BUFFER_OP; + BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC; + UtSetParseOpName (BufferOp); + + BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; + BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength; + (void) OpcSetOptimalIntegerSize (BufferLengthOp); + UtSetParseOpName (BufferLengthOp); + + BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN; + BufferDataOp->Asl.AmlOpcodeLength = 0; + BufferDataOp->Asl.AmlLength = Rnode->BufferLength; + BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode; + UtSetParseOpName (BufferDataOp); +} + + +/******************************************************************************* + * + * FUNCTION: OpcDoUnicode + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Implement the UNICODE ASL "macro". Convert the input string + * to a unicode buffer. There is no Unicode AML opcode. + * + * Note: The Unicode string is 16 bits per character, no leading signature, + * with a 16-bit terminating NULL. + * + ******************************************************************************/ + +static void +OpcDoUnicode ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *InitializerOp; + UINT32 Length; + UINT32 Count; + UINT32 i; + UINT8 *AsciiString; + UINT16 *UnicodeString; + ACPI_PARSE_OBJECT *BufferLengthOp; + + + /* Change op into a buffer object */ + + Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; + Op->Asl.ParseOpcode = PARSEOP_BUFFER; + UtSetParseOpName (Op); + + /* Buffer Length is first, followed by the string */ + + BufferLengthOp = Op->Asl.Child; + InitializerOp = BufferLengthOp->Asl.Next; + + AsciiString = (UINT8 *) InitializerOp->Asl.Value.String; + + /* Create a new buffer for the Unicode string */ + + Count = strlen (InitializerOp->Asl.Value.String) + 1; + Length = Count * sizeof (UINT16); + UnicodeString = UtLocalCalloc (Length); + + /* Convert to Unicode string (including null terminator) */ + + for (i = 0; i < Count; i++) + { + UnicodeString[i] = (UINT16) AsciiString[i]; + } + + /* + * Just set the buffer size node to be the buffer length, regardless + * of whether it was previously an integer or a default_arg placeholder + */ + BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; + BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; + BufferLengthOp->Asl.Value.Integer = Length; + UtSetParseOpName (BufferLengthOp); + + (void) OpcSetOptimalIntegerSize (BufferLengthOp); + + /* The Unicode string is a raw data buffer */ + + InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString; + InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; + InitializerOp->Asl.AmlLength = Length; + InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + InitializerOp->Asl.Child = NULL; + UtSetParseOpName (InitializerOp); +} + + +/******************************************************************************* + * + * FUNCTION: OpcDoEisaId + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Convert a string EISA ID to numeric representation. See the + * Pnp BIOS Specification for details. Here is an excerpt: + * + * A seven character ASCII representation of the product + * identifier compressed into a 32-bit identifier. The seven + * character ID consists of a three character manufacturer code, + * a three character hexadecimal product identifier, and a one + * character hexadecimal revision number. The manufacturer code + * is a 3 uppercase character code that is compressed into 3 5-bit + * values as follows: + * 1) Find hex ASCII value for each letter + * 2) Subtract 40h from each ASCII value + * 3) Retain 5 least signficant bits for each letter by + * discarding upper 3 bits because they are always 0. + * 4) Compressed code = concatenate 0 and the 3 5-bit values + * + * The format of the compressed product identifier is as follows: + * Byte 0: Bit 7 - Reserved (0) + * Bits 6-2: - 1st character of compressed mfg code + * Bits 1-0 - Upper 2 bits of 2nd character of mfg code + * Byte 1: Bits 7-5 - Lower 3 bits of 2nd character of mfg code + * Bits 4-0 - 3rd character of mfg code + * Byte 2: Bits 7-4 - 1st hex digit of product number + * Bits 3-0 - 2nd hex digit of product number + * Byte 3: Bits 7-4 - 3st hex digit of product number + * Bits 3-0 - Hex digit of the revision number + * + ******************************************************************************/ + +static void +OpcDoEisaId ( + ACPI_PARSE_OBJECT *Op) +{ + UINT32 EisaId = 0; + UINT32 BigEndianId; + char *InString; + ACPI_STATUS Status = AE_OK; + UINT32 i; + + + InString = (char *) Op->Asl.Value.String; + + /* + * The EISAID string must be exactly 7 characters and of the form + * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001") + */ + if (ACPI_STRLEN (InString) != 7) + { + Status = AE_BAD_PARAMETER; + } + else + { + /* Check all 7 characters for correct format */ + + for (i = 0; i < 7; i++) + { + /* First 3 characters must be uppercase letters */ + + if (i < 3) + { + if (!isupper ((int) InString[i])) + { + Status = AE_BAD_PARAMETER; + } + } + + /* Last 4 characters must be hex digits */ + + else if (!isxdigit ((int) InString[i])) + { + Status = AE_BAD_PARAMETER; + } + } + } + + if (ACPI_FAILURE (Status)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String); + } + else + { + /* Create ID big-endian first (bits are contiguous) */ + + BigEndianId = + (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 | + (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 | + (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 | + + (UtHexCharToValue (InString[3])) << 12 | + (UtHexCharToValue (InString[4])) << 8 | + (UtHexCharToValue (InString[5])) << 4 | + UtHexCharToValue (InString[6]); + + /* Swap to little-endian to get final ID (see function header) */ + + EisaId = AcpiUtDwordByteSwap (BigEndianId); + } + + /* + * Morph the Op into an integer, regardless of whether there + * was an error in the EISAID string + */ + Op->Asl.Value.Integer = EisaId; + + Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; + Op->Asl.ParseOpcode = PARSEOP_INTEGER; + (void) OpcSetOptimalIntegerSize (Op); + + /* Op is now an integer */ + + UtSetParseOpName (Op); +} + + +/******************************************************************************* + * + * FUNCTION: OpcDoUuId + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Convert UUID string to 16-byte buffer + * + ******************************************************************************/ + +static void +OpcDoUuId ( + ACPI_PARSE_OBJECT *Op) +{ + char *InString; + char *Buffer; + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *NewOp; + + + InString = (char *) Op->Asl.Value.String; + Buffer = UtLocalCalloc (16); + + Status = AuValidateUuid (InString); + if (ACPI_FAILURE (Status)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String); + } + else + { + (void) AuConvertStringToUuid (InString, Buffer); + } + + /* Change Op to a Buffer */ + + Op->Asl.ParseOpcode = PARSEOP_BUFFER; + Op->Common.AmlOpcode = AML_BUFFER_OP; + + /* Disable further optimization */ + + Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; + UtSetParseOpName (Op); + + /* Child node is the buffer length */ + + NewOp = TrAllocateNode (PARSEOP_INTEGER); + + NewOp->Asl.AmlOpcode = AML_BYTE_OP; + NewOp->Asl.Value.Integer = 16; + NewOp->Asl.Parent = Op; + + Op->Asl.Child = NewOp; + Op = NewOp; + + /* Peer to the child is the raw buffer data */ + + NewOp = TrAllocateNode (PARSEOP_RAW_DATA); + NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; + NewOp->Asl.AmlLength = 16; + NewOp->Asl.Value.String = (char *) Buffer; + NewOp->Asl.Parent = Op->Asl.Parent; + + Op->Asl.Next = NewOp; +} + + +/******************************************************************************* + * + * FUNCTION: OpcGenerateAmlOpcode + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Generate the AML opcode associated with the node and its + * parse (lex/flex) keyword opcode. Essentially implements + * a mapping between the parse opcodes and the actual AML opcodes. + * + ******************************************************************************/ + +void +OpcGenerateAmlOpcode ( + ACPI_PARSE_OBJECT *Op) +{ + + UINT16 Index; + + + Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); + + Op->Asl.AmlOpcode = AslKeywordMapping[Index].AmlOpcode; + Op->Asl.AcpiBtype = AslKeywordMapping[Index].AcpiBtype; + Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags; + + if (!Op->Asl.Value.Integer) + { + Op->Asl.Value.Integer = AslKeywordMapping[Index].Value; + } + + /* Special handling for some opcodes */ + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_INTEGER: + /* + * Set the opcode based on the size of the integer + */ + (void) OpcSetOptimalIntegerSize (Op); + break; + + case PARSEOP_OFFSET: + + Op->Asl.AmlOpcodeLength = 1; + break; + + case PARSEOP_ACCESSAS: + + OpcDoAccessAs (Op); + break; + + case PARSEOP_CONNECTION: + + OpcDoConnection (Op); + break; + + case PARSEOP_EISAID: + + OpcDoEisaId (Op); + break; + + case PARSEOP_TOUUID: + + OpcDoUuId (Op); + break; + + case PARSEOP_UNICODE: + + OpcDoUnicode (Op); + break; + + case PARSEOP_INCLUDE: + + Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + Gbl_HasIncludeFiles = TRUE; + break; + + case PARSEOP_EXTERNAL: + + Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + break; + + default: + /* Nothing to do for other opcodes */ + break; + } + + return; +} + + diff --git a/source/compiler/asloperands.c b/source/compiler/asloperands.c new file mode 100644 index 000000000000..37274e79d610 --- /dev/null +++ b/source/compiler/asloperands.c @@ -0,0 +1,1184 @@ + +/****************************************************************************** + * + * Module Name: asloperands - AML operand processing + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asloperands") + +/* Local prototypes */ + +static void +OpnDoField ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoBankField ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoBuffer ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoDefinitionBlock ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoFieldCommon ( + ACPI_PARSE_OBJECT *FieldOp, + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoIndexField ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoLoadTable ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoMethod ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoMutex ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnDoRegion ( + ACPI_PARSE_OBJECT *Op); + +static void +OpnAttachNameToNode ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: OpnDoMutex + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the operands for the MUTEX ASL keyword. + * + ******************************************************************************/ + +static void +OpnDoMutex ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + Next = Op->Asl.Child; + Next = Next->Asl.Next; + + if (Next->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); + } + return; +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoMethod + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the operands for the METHOD ASL keyword. + * + ******************************************************************************/ + +static void +OpnDoMethod ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + /* Optional arguments for this opcode with defaults */ + + UINT8 NumArgs = 0; + UINT8 Serialized = 0; + UINT8 Concurrency = 0; + UINT8 MethodFlags; + + + /* Opcode and package length first */ + /* Method name */ + + Next = Op->Asl.Child; + + /* Num args */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + NumArgs = (UINT8) Next->Asl.Value.Integer; + Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + } + + /* Serialized Flag */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Serialized = (UINT8) Next->Asl.Value.Integer; + Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + } + + /* Concurrency value (valid values are 0-15) */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + if (Next->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); + } + Concurrency = (UINT8) Next->Asl.Value.Integer; + } + + /* Put the bits in their proper places */ + + MethodFlags = (UINT8) ((NumArgs & 0x7) | + ((Serialized & 0x1) << 3) | + ((Concurrency & 0xF) << 4)); + + /* Use the last node for the combined flags byte */ + + Next->Asl.Value.Integer = MethodFlags; + Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + Next->Asl.AmlLength = 1; + Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; + + /* Save the arg count in the first node */ + + Op->Asl.Extra = NumArgs; +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoFieldCommon + * + * PARAMETERS: FieldOp - Node for an ASL field + * Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the various field keywords, + * FIELD, BANKFIELD, INDEXFIELD + * + ******************************************************************************/ + +static void +OpnDoFieldCommon ( + ACPI_PARSE_OBJECT *FieldOp, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_PARSE_OBJECT *PkgLengthNode; + UINT32 CurrentBitOffset; + UINT32 NewBitOffset; + UINT8 AccessType; + UINT8 LockRule; + UINT8 UpdateRule; + UINT8 FieldFlags; + UINT32 MinimumLength; + + + /* AccessType -- not optional, so no need to check for DEFAULT_ARG */ + + AccessType = (UINT8) Op->Asl.Value.Integer; + Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + + /* Set the access type in the parent (field) node for use later */ + + FieldOp->Asl.Value.Integer = AccessType; + + /* LockRule -- not optional, so no need to check for DEFAULT_ARG */ + + Next = Op->Asl.Next; + LockRule = (UINT8) Next->Asl.Value.Integer; + Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + + /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */ + + Next = Next->Asl.Next; + UpdateRule = (UINT8) Next->Asl.Value.Integer; + + /* + * Generate the flags byte. The various fields are already + * in the right bit position via translation from the + * keywords by the parser. + */ + FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule); + + /* Use the previous node to be the FieldFlags node */ + + /* Set the node to RAW_DATA */ + + Next->Asl.Value.Integer = FieldFlags; + Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + Next->Asl.AmlLength = 1; + Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; + + /* Process the FieldUnitList */ + + Next = Next->Asl.Next; + CurrentBitOffset = 0; + + while (Next) + { + /* Save the offset of this field unit */ + + Next->Asl.ExtraValue = CurrentBitOffset; + + switch (Next->Asl.ParseOpcode) + { + case PARSEOP_ACCESSAS: + + PkgLengthNode = Next->Asl.Child; + AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer; + + /* Nothing additional to do */ + break; + + + case PARSEOP_OFFSET: + + /* New offset into the field */ + + PkgLengthNode = Next->Asl.Child; + NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8; + + /* + * Examine the specified offset in relation to the + * current offset counter. + */ + if (NewBitOffset < CurrentBitOffset) + { + /* + * Not allowed to specify a backwards offset! + * Issue error and ignore this node. + */ + AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode, + NULL); + Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + } + else if (NewBitOffset == CurrentBitOffset) + { + /* + * Offset is redundant; we don't need to output an + * offset opcode. Just set these nodes to default + */ + Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + } + else + { + /* + * Valid new offset - set the value to be inserted into the AML + * and update the offset counter. + */ + PkgLengthNode->Asl.Value.Integer = + NewBitOffset - CurrentBitOffset; + CurrentBitOffset = NewBitOffset; + } + break; + + + case PARSEOP_NAMESEG: + case PARSEOP_RESERVED_BYTES: + + /* Named or reserved field entry */ + + PkgLengthNode = Next->Asl.Child; + NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer; + CurrentBitOffset += NewBitOffset; + + /* Save the current AccessAs value for error checking later */ + + switch (AccessType) + { + case AML_FIELD_ACCESS_ANY: + case AML_FIELD_ACCESS_BYTE: + case AML_FIELD_ACCESS_BUFFER: + default: + MinimumLength = 8; + break; + + case AML_FIELD_ACCESS_WORD: + MinimumLength = 16; + break; + + case AML_FIELD_ACCESS_DWORD: + MinimumLength = 32; + break; + + case AML_FIELD_ACCESS_QWORD: + MinimumLength = 64; + break; + } + + PkgLengthNode->Asl.ExtraValue = MinimumLength; + break; + + default: + /* All supported field opcodes must appear above */ + break; + } + + /* Move on to next entry in the field list */ + + Next = Next->Asl.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoField + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword + * + ******************************************************************************/ + +static void +OpnDoField ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Opcode is parent node */ + /* First child is field name */ + + Next = Op->Asl.Child; + + /* Second child is the AccessType */ + + OpnDoFieldCommon (Op, Next->Asl.Next); +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoIndexField + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword + * + ******************************************************************************/ + +static void +OpnDoIndexField ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Opcode is parent node */ + /* First child is the index name */ + + Next = Op->Asl.Child; + + /* Second child is the data name */ + + Next = Next->Asl.Next; + + /* Third child is the AccessType */ + + OpnDoFieldCommon (Op, Next->Asl.Next); +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoBankField + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword + * + ******************************************************************************/ + +static void +OpnDoBankField ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Opcode is parent node */ + /* First child is the region name */ + + Next = Op->Asl.Child; + + /* Second child is the bank name */ + + Next = Next->Asl.Next; + + /* Third child is the bank value */ + + Next = Next->Asl.Next; + + /* Fourth child is the AccessType */ + + OpnDoFieldCommon (Op, Next->Asl.Next); +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoRegion + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Tries to get the length of the region. Can only do this at + * compile time if the length is a constant. + * + ******************************************************************************/ + +static void +OpnDoRegion ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Opcode is parent node */ + /* First child is the region name */ + + Next = Op->Asl.Child; + + /* Second child is the space ID*/ + + Next = Next->Asl.Next; + + /* Third child is the region offset */ + + Next = Next->Asl.Next; + + /* Fourth child is the region length */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode == PARSEOP_INTEGER) + { + Op->Asl.Value.Integer = Next->Asl.Value.Integer; + } + else + { + Op->Asl.Value.Integer = ACPI_UINT64_MAX; + } +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoBuffer + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We + * build a single raw byte buffer from the initialization nodes, + * each parse node contains a buffer byte. + * + ******************************************************************************/ + +static void +OpnDoBuffer ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *BufferLengthOp; + + /* Optional arguments for this opcode with defaults */ + + UINT32 BufferLength = 0; + + + /* Opcode and package length first */ + /* Buffer Length is next, followed by the initializer list */ + + BufferLengthOp = Op->Asl.Child; + InitializerOp = BufferLengthOp->Asl.Next; + + /* + * If the BufferLength is not an INTEGER or was not specified in the ASL + * (DEFAULT_ARG), it is a TermArg that is + * evaluated at run-time, and we are therefore finished. + */ + if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) && + (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) + { + return; + } + + /* + * We want to count the number of items in the initializer list, because if + * it is larger than the buffer length, we will define the buffer size + * to be the size of the initializer list (as per the ACPI Specification) + */ + switch (InitializerOp->Asl.ParseOpcode) + { + case PARSEOP_INTEGER: + case PARSEOP_BYTECONST: + case PARSEOP_WORDCONST: + case PARSEOP_DWORDCONST: + + /* The peer list contains the byte list (if any...) */ + + while (InitializerOp) + { + /* For buffers, this is a list of raw bytes */ + + InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + InitializerOp->Asl.AmlLength = 1; + InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + + BufferLength++; + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + } + break; + + + case PARSEOP_STRING_LITERAL: + + /* + * Only one initializer, the string. Buffer must be big enough to hold + * the string plus the null termination byte + */ + BufferLength = strlen (InitializerOp->Asl.Value.String) + 1; + + InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; + InitializerOp->Asl.AmlLength = BufferLength; + InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + break; + + + case PARSEOP_RAW_DATA: + + /* Buffer nodes are already initialized (e.g. Unicode operator) */ + return; + + + case PARSEOP_DEFAULT_ARG: + break; + + + default: + AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp, + "Unknown buffer initializer opcode"); + printf ("Unknown buffer initializer opcode [%s]\n", + UtGetOpName (InitializerOp->Asl.ParseOpcode)); + return; + } + + /* Check if initializer list is longer than the buffer length */ + + if (BufferLengthOp->Asl.Value.Integer > BufferLength) + { + BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer; + } + + if (!BufferLength) + { + /* No length AND no items -- issue notice */ + + AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL); + + /* But go ahead and put the buffer length of zero into the AML */ + } + + /* + * Just set the buffer size node to be the buffer length, regardless + * of whether it was previously an integer or a default_arg placeholder + */ + BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; + BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; + BufferLengthOp->Asl.Value.Integer = BufferLength; + + (void) OpcSetOptimalIntegerSize (BufferLengthOp); + + /* Remaining nodes are handled via the tree walk */ +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoPackage + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE: + * can only be called after constants have been folded, to ensure + * that the PackageLength operand has been fully reduced. + * + ******************************************************************************/ + +void +OpnDoPackage ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *PackageLengthOp; + UINT32 PackageLength = 0; + + + /* Opcode and package length first, followed by the initializer list */ + + PackageLengthOp = Op->Asl.Child; + InitializerOp = PackageLengthOp->Asl.Next; + + /* Count the number of items in the initializer list */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* The peer list contains the byte list (if any...) */ + + while (InitializerOp) + { + PackageLength++; + InitializerOp = InitializerOp->Asl.Next; + } + } + + /* If package length is a constant, compare to the initializer list */ + + if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || + (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)) + { + if (PackageLengthOp->Asl.Value.Integer > PackageLength) + { + /* + * Allow package length to be longer than the initializer + * list -- but if the length of initializer list is nonzero, + * issue a message since this is probably a coding error, + * even though technically legal. + */ + if (PackageLength > 0) + { + AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT, + PackageLengthOp, NULL); + } + + PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer; + } + else if (PackageLengthOp->Asl.Value.Integer < PackageLength) + { + /* + * The package length is smaller than the length of the + * initializer list. This is an error as per the ACPI spec. + */ + AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG, + PackageLengthOp, NULL); + } + } + + if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* + * This is the case if the PackageLength was left empty - Package() + * The package length becomes the length of the initializer list + */ + Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER; + Op->Asl.Child->Asl.Value.Integer = PackageLength; + + /* Set the AML opcode */ + + (void) OpcSetOptimalIntegerSize (Op->Asl.Child); + } + + /* If not a variable-length package, check for a zero package length */ + + if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || + (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) || + (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO) || + (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)) + { + if (!PackageLength) + { + /* No length AND no initializer list -- issue a remark */ + + AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH, + PackageLengthOp, NULL); + + /* But go ahead and put the buffer length of zero into the AML */ + } + } + + /* + * If the PackageLength is a constant <= 255, we can change the + * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode. + */ + if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && + (Op->Asl.Child->Asl.Value.Integer <= 255)) || + (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) || + (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)|| + (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO)) + { + Op->Asl.AmlOpcode = AML_PACKAGE_OP; + Op->Asl.ParseOpcode = PARSEOP_PACKAGE; + + /* + * Just set the package size node to be the package length, regardless + * of whether it was previously an integer or a default_arg placeholder + */ + PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; + PackageLengthOp->Asl.AmlLength = 1; + PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + PackageLengthOp->Asl.Value.Integer = PackageLength; + } + + /* Remaining nodes are handled via the tree walk */ +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoLoadTable + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword. + * + ******************************************************************************/ + +static void +OpnDoLoadTable ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + + + /* Opcode is parent node */ + /* First child is the table signature */ + + Next = Op->Asl.Child; + + /* Second child is the OEM ID*/ + + Next = Next->Asl.Next; + + /* Third child is the OEM table ID */ + + Next = Next->Asl.Next; + + /* Fourth child is the RootPath string */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode == PARSEOP_ZERO) + { + Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; + Next->Asl.Value.String = "\\"; + Next->Asl.AmlLength = 2; + OpcGenerateAmlOpcode (Next); + } + +#ifdef ASL_FUTURE_IMPLEMENTATION + + /* TBD: NOT IMPLEMENTED */ + /* Fifth child is the [optional] ParameterPathString */ + /* Sixth child is the [optional] ParameterData */ + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode == DEFAULT_ARG) + { + Next->Asl.AmlLength = 1; + Next->Asl.ParseOpcode = ZERO; + OpcGenerateAmlOpcode (Next); + } + + + Next = Next->Asl.Next; + if (Next->Asl.ParseOpcode == DEFAULT_ARG) + { + Next->Asl.AmlLength = 1; + Next->Asl.ParseOpcode = ZERO; + OpcGenerateAmlOpcode (Next); + } +#endif +} + + +/******************************************************************************* + * + * FUNCTION: OpnDoDefinitionBlock + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword + * + ******************************************************************************/ + +static void +OpnDoDefinitionBlock ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Child; + ACPI_SIZE Length; + UINT32 i; + char *Filename; + + + /* + * These nodes get stuffed into the table header. They are special + * cased when the table is written to the output file. + * + * Mark all of these nodes as non-usable so they won't get output + * as AML opcodes! + */ + + /* Get AML filename. Use it if non-null */ + + Child = Op->Asl.Child; + if (Child->Asl.Value.Buffer && + *Child->Asl.Value.Buffer && + (Gbl_UseDefaultAmlFilename)) + { + /* + * We will use the AML filename that is embedded in the source file + * for the output filename. + */ + Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) + + strlen ((char *) Child->Asl.Value.Buffer) + 1); + + /* Prepend the current directory path */ + + strcpy (Filename, Gbl_DirectoryPath); + strcat (Filename, (char *) Child->Asl.Value.Buffer); + + Gbl_OutputFilenamePrefix = Filename; + } + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + + /* Signature */ + + Child = Child->Asl.Next; + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + if (Child->Asl.Value.String) + { + Gbl_TableSignature = Child->Asl.Value.String; + if (ACPI_STRLEN (Gbl_TableSignature) != 4) + { + AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, + "Length not exactly 4"); + } + + for (i = 0; i < 4; i++) + { + if (!isalnum ((int) Gbl_TableSignature[i])) + { + AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, + "Contains non-alphanumeric characters"); + } + } + } + + /* Revision */ + + Child = Child->Asl.Next; + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + /* + * We used the revision to set the integer width earlier + */ + + /* OEMID */ + + Child = Child->Asl.Next; + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + + /* OEM TableID */ + + Child = Child->Asl.Next; + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + if (Child->Asl.Value.String) + { + Length = ACPI_STRLEN (Child->Asl.Value.String); + Gbl_TableId = AcpiOsAllocate (Length + 1); + ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String); + + for (i = 0; i < Length; i++) + { + if (Gbl_TableId[i] == ' ') + { + Gbl_TableId[i] = 0; + break; + } + } + } + + /* OEM Revision */ + + Child = Child->Asl.Next; + Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; +} + + +/******************************************************************************* + * + * FUNCTION: UtGetArg + * + * PARAMETERS: Op - Get an argument for this op + * Argn - Nth argument to get + * + * RETURN: The argument (as an Op object). NULL if argument does not exist + * + * DESCRIPTION: Get the specified op's argument (peer) + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +UtGetArg ( + ACPI_PARSE_OBJECT *Op, + UINT32 Argn) +{ + ACPI_PARSE_OBJECT *Arg = NULL; + + + /* Get the requested argument object */ + + Arg = Op->Asl.Child; + while (Arg && Argn) + { + Argn--; + Arg = Arg->Asl.Next; + } + + return (Arg); +} + + +/******************************************************************************* + * + * FUNCTION: OpnAttachNameToNode + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: For the named ASL/AML operators, get the actual name from the + * argument list and attach it to the parent node so that we + * can get to it quickly later. + * + ******************************************************************************/ + +static void +OpnAttachNameToNode ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Child = NULL; + + + if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) + { + Child = UtGetArg (Op, 0); + } + else switch (Op->Asl.AmlOpcode) + { + case AML_DATA_REGION_OP: + case AML_DEVICE_OP: + case AML_EVENT_OP: + case AML_METHOD_OP: + case AML_MUTEX_OP: + case AML_REGION_OP: + case AML_POWER_RES_OP: + case AML_PROCESSOR_OP: + case AML_THERMAL_ZONE_OP: + case AML_NAME_OP: + case AML_SCOPE_OP: + + Child = UtGetArg (Op, 0); + break; + + case AML_ALIAS_OP: + + Child = UtGetArg (Op, 1); + break; + + case AML_CREATE_BIT_FIELD_OP: + case AML_CREATE_BYTE_FIELD_OP: + case AML_CREATE_WORD_FIELD_OP: + case AML_CREATE_DWORD_FIELD_OP: + case AML_CREATE_QWORD_FIELD_OP: + + Child = UtGetArg (Op, 2); + break; + + case AML_CREATE_FIELD_OP: + + Child = UtGetArg (Op, 3); + break; + + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + case AML_FIELD_OP: + + return; + + default: + return; + } + + if (Child) + { + UtAttachNamepathToOwner (Op, Child); + } +} + + +/******************************************************************************* + * + * FUNCTION: OpnGenerateAmlOperands + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more + * complex AML opcodes require processing of the child nodes + * (arguments/operands). + * + ******************************************************************************/ + +void +OpnGenerateAmlOperands ( + ACPI_PARSE_OBJECT *Op) +{ + + + if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) + { + return; + } + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + OpnDoDefinitionBlock (Op); + break; + + case PARSEOP_METHOD: + OpnDoMethod (Op); + break; + + case PARSEOP_MUTEX: + OpnDoMutex (Op); + break; + + case PARSEOP_FIELD: + OpnDoField (Op); + break; + + case PARSEOP_INDEXFIELD: + OpnDoIndexField (Op); + break; + + case PARSEOP_BANKFIELD: + OpnDoBankField (Op); + break; + + case PARSEOP_BUFFER: + OpnDoBuffer (Op); + break; + + case PARSEOP_LOADTABLE: + OpnDoLoadTable (Op); + break; + + case PARSEOP_OPERATIONREGION: + OpnDoRegion (Op); + break; + + case PARSEOP_RESOURCETEMPLATE: + RsDoResourceTemplate (Op); + break; + + case PARSEOP_NAMESEG: + case PARSEOP_NAMESTRING: + case PARSEOP_METHODCALL: + case PARSEOP_STRING_LITERAL: + break; + + default: + break; + } + + /* TBD: move */ + + OpnAttachNameToNode (Op); +} + + diff --git a/source/compiler/aslopt.c b/source/compiler/aslopt.c new file mode 100644 index 000000000000..6942f7b5ebaf --- /dev/null +++ b/source/compiler/aslopt.c @@ -0,0 +1,796 @@ +/****************************************************************************** + * + * Module Name: aslopt- Compiler optimizations + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslopt") + + +static UINT32 OptTotal = 0; + +/* Local prototypes */ + +static ACPI_STATUS +OptSearchToRoot ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + ACPI_BUFFER *TargetPath, + char **NewPath); + +static ACPI_STATUS +OptBuildShortestPath ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + ACPI_BUFFER *CurrentPath, + ACPI_BUFFER *TargetPath, + ACPI_SIZE AmlNameStringLength, + UINT8 IsDeclaration, + char **ReturnNewPath); + +static ACPI_STATUS +OptOptimizeNameDeclaration ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + char *AmlNameString, + char **NewPath); + + +/******************************************************************************* + * + * FUNCTION: OptSearchToRoot + * + * PARAMETERS: Op - Current parser op + * WalkState - Current state + * CurrentNode - Where we are in the namespace + * TargetNode - Node to which we are referring + * TargetPath - External full path to the target node + * NewPath - Where the optimized path is returned + * + * RETURN: Status + * + * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI + * name utilizing the search-to-root name resolution algorithm + * that is used by AML interpreters. + * + ******************************************************************************/ + +static ACPI_STATUS +OptSearchToRoot ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + ACPI_BUFFER *TargetPath, + char **NewPath) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_GENERIC_STATE ScopeInfo; + ACPI_STATUS Status; + char *Path; + + + ACPI_FUNCTION_NAME (OptSearchToRoot); + + + /* + * Check if search-to-root can be utilized. Use the last NameSeg of + * the NamePath and 1) See if can be found and 2) If found, make + * sure that it is the same node that we want. If there is another + * name in the search path before the one we want, the nodes will + * not match, and we cannot use this optimization. + */ + Path = &(((char *) TargetPath->Pointer)[TargetPath->Length - + ACPI_NAME_SIZE]), + ScopeInfo.Scope.Node = CurrentNode; + + /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */ + + Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &(Node)); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * We found the name, but we must check to make sure that the node + * matches. Otherwise, there is another identical name in the search + * path that precludes the use of this optimization. + */ + if (Node != TargetNode) + { + /* + * This means that another object with the same name was found first, + * and we cannot use this optimization. + */ + return (AE_NOT_FOUND); + } + + /* Found the node, we can use this optimization */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + "NAMESEG: %-24s", Path)); + + /* We must allocate a new string for the name (TargetPath gets deleted) */ + + *NewPath = ACPI_ALLOCATE_ZEROED (ACPI_NAME_SIZE + 1); + ACPI_STRCPY (*NewPath, Path); + + if (ACPI_STRNCMP (*NewPath, "_T_", 3)) + { + AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op, + *NewPath); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: OptBuildShortestPath + * + * PARAMETERS: Op - Current parser op + * WalkState - Current state + * CurrentNode - Where we are in the namespace + * TargetNode - Node to which we are referring + * CurrentPath - External full path to the current node + * TargetPath - External full path to the target node + * AmlNameStringLength - Length of the original namepath + * IsDeclaration - TRUE for declaration, FALSE for reference + * ReturnNewPath - Where the optimized path is returned + * + * RETURN: Status + * + * DESCRIPTION: Build an optimal NamePath using carats + * + ******************************************************************************/ + +static ACPI_STATUS +OptBuildShortestPath ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + ACPI_BUFFER *CurrentPath, + ACPI_BUFFER *TargetPath, + ACPI_SIZE AmlNameStringLength, + UINT8 IsDeclaration, + char **ReturnNewPath) +{ + UINT32 NumCommonSegments; + UINT32 MaxCommonSegments; + UINT32 Index; + UINT32 NumCarats; + UINT32 i; + char *NewPath; + char *NewPathExternal; + ACPI_NAMESPACE_NODE *Node; + ACPI_GENERIC_STATE ScopeInfo; + ACPI_STATUS Status; + BOOLEAN SubPath = FALSE; + + + ACPI_FUNCTION_NAME (OptBuildShortestPath); + + + ScopeInfo.Scope.Node = CurrentNode; + + /* + * Determine the maximum number of NameSegs that the Target and Current paths + * can possibly have in common. (To optimize, we have to have at least 1) + * + * Note: The external NamePath string lengths are always a multiple of 5 + * (ACPI_NAME_SIZE + separator) + */ + MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH; + if (CurrentPath->Length < TargetPath->Length) + { + MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH; + } + + /* + * Determine how many NameSegs the two paths have in common. + * (Starting from the root) + */ + for (NumCommonSegments = 0; + NumCommonSegments < MaxCommonSegments; + NumCommonSegments++) + { + /* Compare two single NameSegs */ + + if (ACPI_STRNCMP ( + &((char *) TargetPath->Pointer)[(NumCommonSegments * + ACPI_PATH_SEGMENT_LENGTH) + 1], + &((char *) CurrentPath->Pointer)[(NumCommonSegments * + ACPI_PATH_SEGMENT_LENGTH) + 1], + ACPI_NAME_SIZE)) + { + /* Mismatch */ + + break; + } + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u", + NumCommonSegments)); + + /* There must be at least 1 common NameSeg in order to optimize */ + + if (NumCommonSegments == 0) + { + return (AE_NOT_FOUND); + } + + if (NumCommonSegments == MaxCommonSegments) + { + if (CurrentPath->Length == TargetPath->Length) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH")); + return (AE_NOT_FOUND); + } + else + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH")); + SubPath = TRUE; + } + } + + /* Determine how many prefix Carats are required */ + + NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) - + NumCommonSegments; + + /* + * Construct a new target string + */ + NewPathExternal = ACPI_ALLOCATE_ZEROED ( + TargetPath->Length + NumCarats + 1); + + /* Insert the Carats into the Target string */ + + for (i = 0; i < NumCarats; i++) + { + NewPathExternal[i] = '^'; + } + + /* + * Copy only the necessary (optimal) segments from the original + * target string + */ + Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1; + + /* Special handling for exact subpath in a name declaration */ + + if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length)) + { + /* + * The current path is longer than the target, and the target is a + * subpath of the current path. We must include one more NameSeg of + * the target path + */ + Index -= ACPI_PATH_SEGMENT_LENGTH; + + /* Special handling for Scope() operator */ + + if (Op->Asl.AmlOpcode == AML_SCOPE_OP) + { + NewPathExternal[i] = '^'; + i++; + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)")); + } + } + + /* Make sure we haven't gone off the end of the target path */ + + if (Index > TargetPath->Length) + { + Index = TargetPath->Length; + } + + ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal)); + + /* + * Internalize the new target string and check it against the original + * string to make sure that this is in fact an optimization. If the + * original string is already optimal, there is no point in continuing. + */ + Status = AcpiNsInternalizeName (NewPathExternal, &NewPath); + if (ACPI_FAILURE (Status)) + { + AslCoreSubsystemError (Op, Status, "Internalizing new NamePath", + ASL_NO_ABORT); + ACPI_FREE (NewPathExternal); + return (Status); + } + + if (ACPI_STRLEN (NewPath) >= AmlNameStringLength) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + " NOT SHORTER (New %u old %u)", + (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength)); + ACPI_FREE (NewPathExternal); + return (AE_NOT_FOUND); + } + + /* + * Check to make sure that the optimization finds the node we are + * looking for. This is simply a sanity check on the new + * path that has been created. + */ + Status = AcpiNsLookup (&ScopeInfo, NewPath, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node)); + if (ACPI_SUCCESS (Status)) + { + /* Found the namepath, but make sure the node is correct */ + + if (Node == TargetNode) + { + /* The lookup matched the node, accept this optimization */ + + AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION, + Op, NewPathExternal); + *ReturnNewPath = NewPath; + } + else + { + /* Node is not correct, do not use this optimization */ + + Status = AE_NOT_FOUND; + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE")); + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, + "Not using optimized name - found wrong node"); + } + } + else + { + /* The lookup failed, we obviously cannot use this optimization */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND")); + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, + "Not using optimized name - did not find node"); + } + + ACPI_FREE (NewPathExternal); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: OptOptimizeNameDeclaration + * + * PARAMETERS: Op - Current parser op + * WalkState - Current state + * CurrentNode - Where we are in the namespace + * AmlNameString - Unoptimized namepath + * NewPath - Where the optimized path is returned + * + * RETURN: Status. AE_OK If path is optimized + * + * DESCRIPTION: Perform a simple optimization of removing an extraneous + * backslash prefix if we are already at the root scope. + * + ******************************************************************************/ + +static ACPI_STATUS +OptOptimizeNameDeclaration ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *CurrentNode, + ACPI_NAMESPACE_NODE *TargetNode, + char *AmlNameString, + char **NewPath) +{ + ACPI_STATUS Status; + char *NewPathExternal; + ACPI_GENERIC_STATE ScopeInfo; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration); + + + if (((CurrentNode == AcpiGbl_RootNode) || + (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) && + (AmlNameString[0] == '\\')) + { + /* + * The current scope is the root, and the namepath has a root prefix + * that is therefore extraneous. Remove it. + */ + *NewPath = &AmlNameString[1]; + + /* Debug output */ + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath, + NULL, &NewPathExternal); + if (ACPI_FAILURE (Status)) + { + AslCoreSubsystemError (Op, Status, "Externalizing NamePath", + ASL_NO_ABORT); + return (Status); + } + + /* + * Check to make sure that the optimization finds the node we are + * looking for. This is simply a sanity check on the new + * path that has been created. + */ + ScopeInfo.Scope.Node = CurrentNode; + Status = AcpiNsLookup (&ScopeInfo, *NewPath, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node)); + if (ACPI_SUCCESS (Status)) + { + /* Found the namepath, but make sure the node is correct */ + + if (Node == TargetNode) + { + /* The lookup matched the node, accept this optimization */ + + AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION, + Op, NewPathExternal); + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + "AT ROOT: %-24s", NewPathExternal)); + } + else + { + /* Node is not correct, do not use this optimization */ + + Status = AE_NOT_FOUND; + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + " ***** WRONG NODE")); + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, + "Not using optimized name - found wrong node"); + } + } + else + { + /* The lookup failed, we obviously cannot use this optimization */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + " ***** NOT FOUND")); + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, + "Not using optimized name - did not find node"); + } + + ACPI_FREE (NewPathExternal); + return (Status); + } + + /* Could not optimize */ + + return (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: OptOptimizeNamePath + * + * PARAMETERS: Op - Current parser op + * Flags - Opcode info flags + * WalkState - Current state + * AmlNameString - Unoptimized namepath + * TargetNode - Node to which AmlNameString refers + * + * RETURN: None. If path is optimized, the Op is updated with new path + * + * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length. + * Must take into account both the current location in the + * namespace and the actual reference path. + * + ******************************************************************************/ + +void +OptOptimizeNamePath ( + ACPI_PARSE_OBJECT *Op, + UINT32 Flags, + ACPI_WALK_STATE *WalkState, + char *AmlNameString, + ACPI_NAMESPACE_NODE *TargetNode) +{ + ACPI_STATUS Status; + ACPI_BUFFER TargetPath; + ACPI_BUFFER CurrentPath; + ACPI_SIZE AmlNameStringLength; + ACPI_NAMESPACE_NODE *CurrentNode; + char *ExternalNameString; + char *NewPath = NULL; + ACPI_SIZE HowMuchShorter; + ACPI_PARSE_OBJECT *NextOp; + + + ACPI_FUNCTION_TRACE (OptOptimizeNamePath); + + + /* This is an optional optimization */ + + if (!Gbl_ReferenceOptimizationFlag) + { + return_VOID; + } + + /* Various required items */ + + if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent) + { + return_VOID; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "%5d [%12.12s] [%12.12s] ", + Op->Asl.LogicalLineNumber, + AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), + AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); + + if (!(Flags & (AML_NAMED | AML_CREATE))) + { + if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) + { + /* We don't want to fuss with actual name declaration nodes here */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + "******* NAME DECLARATION\n")); + return_VOID; + } + } + + /* + * The original path must be longer than one NameSeg (4 chars) for there + * to be any possibility that it can be optimized to a shorter string + */ + AmlNameStringLength = ACPI_STRLEN (AmlNameString); + if (AmlNameStringLength <= ACPI_NAME_SIZE) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + "NAMESEG %4.4s\n", AmlNameString)); + return_VOID; + } + + /* + * We need to obtain the node that represents the current scope -- where + * we are right now in the namespace. We will compare this path + * against the Namepath, looking for commonality. + */ + CurrentNode = AcpiGbl_RootNode; + if (WalkState->ScopeInfo) + { + CurrentNode = WalkState->ScopeInfo->Scope.Node; + } + + if (Flags & (AML_NAMED | AML_CREATE)) + { + /* This is the declaration of a new name */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME")); + + /* + * The node of interest is the parent of this node + * (the containing scope) + */ + CurrentNode = Op->Asl.Parent->Asl.Node; + if (!CurrentNode) + { + CurrentNode = AcpiGbl_RootNode; + } + } + else + { + /* This is a reference to an existing named object */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REF ")); + } + + /* + * Obtain the full paths to the two nodes that we are interested in + * (Target and current namespace location) in external + * format -- something we can easily manipulate + */ + TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (TargetNode, &TargetPath); + if (ACPI_FAILURE (Status)) + { + AslCoreSubsystemError (Op, Status, "Getting Target NamePath", + ASL_NO_ABORT); + return_VOID; + } + TargetPath.Length--; /* Subtract one for null terminator */ + + /* CurrentPath is the path to this scope (where we are in the namespace) */ + + CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath); + if (ACPI_FAILURE (Status)) + { + AslCoreSubsystemError (Op, Status, "Getting Current NamePath", + ASL_NO_ABORT); + return_VOID; + } + CurrentPath.Length--; /* Subtract one for null terminator */ + + /* Debug output only */ + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString, + NULL, &ExternalNameString); + if (ACPI_FAILURE (Status)) + { + AslCoreSubsystemError (Op, Status, "Externalizing NamePath", + ASL_NO_ABORT); + return_VOID; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, + "%37s (%2u) ==> %-32s(%2u) %-32s", + (char *) CurrentPath.Pointer, (UINT32) CurrentPath.Length, + (char *) TargetPath.Pointer, (UINT32) TargetPath.Length, ExternalNameString)); + + ACPI_FREE (ExternalNameString); + + /* + * Attempt an optmization depending on the type of namepath + */ + if (Flags & (AML_NAMED | AML_CREATE)) + { + /* + * This is a named opcode and the namepath is a name declaration, not + * a reference. + */ + Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode, + TargetNode, AmlNameString, &NewPath); + if (ACPI_FAILURE (Status)) + { + /* + * 2) now attempt to + * optimize the namestring with carats (up-arrow) + */ + Status = OptBuildShortestPath (Op, WalkState, CurrentNode, + TargetNode, &CurrentPath, &TargetPath, + AmlNameStringLength, 1, &NewPath); + } + } + else + { + /* + * This is a reference to an existing named object + * + * 1) Check if search-to-root can be utilized using the last + * NameSeg of the NamePath + */ + Status = OptSearchToRoot (Op, WalkState, CurrentNode, + TargetNode, &TargetPath, &NewPath); + if (ACPI_FAILURE (Status)) + { + /* + * 2) Search-to-root could not be used, now attempt to + * optimize the namestring with carats (up-arrow) + */ + Status = OptBuildShortestPath (Op, WalkState, CurrentNode, + TargetNode, &CurrentPath, &TargetPath, + AmlNameStringLength, 0, &NewPath); + } + } + + /* + * Success from above indicates that the NamePath was successfully + * optimized. We need to update the parse op with the new name + */ + if (ACPI_SUCCESS (Status)) + { + HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath)); + OptTotal += HowMuchShorter; + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED %2u (%u)", + (UINT32) HowMuchShorter, OptTotal)); + + if (Flags & AML_NAMED) + { + if (Op->Asl.AmlOpcode == AML_ALIAS_OP) + { + /* + * ALIAS is the only oddball opcode, the name declaration + * (alias name) is the second operand + */ + Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath; + Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath); + } + else + { + Op->Asl.Child->Asl.Value.String = NewPath; + Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath); + } + } + else if (Flags & AML_CREATE) + { + /* Name must appear as the last parameter */ + + NextOp = Op->Asl.Child; + while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) + { + NextOp = NextOp->Asl.Next; + } + /* Update the parse node with the new NamePath */ + + NextOp->Asl.Value.String = NewPath; + NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath); + } + else + { + /* Update the parse node with the new NamePath */ + + Op->Asl.Value.String = NewPath; + Op->Asl.AmlLength = ACPI_STRLEN (NewPath); + } + } + else + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL")); + } + + /* Cleanup path buffers */ + + ACPI_FREE (TargetPath.Pointer); + ACPI_FREE (CurrentPath.Pointer); + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n")); + return_VOID; +} + diff --git a/source/compiler/aslpredef.c b/source/compiler/aslpredef.c new file mode 100644 index 000000000000..8a25a9d5ca20 --- /dev/null +++ b/source/compiler/aslpredef.c @@ -0,0 +1,839 @@ +/****************************************************************************** + * + * Module Name: aslpredef - support for ACPI predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define ACPI_CREATE_PREDEFINED_TABLE + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslpredef") + + +/* Local prototypes */ + +static void +ApCheckForUnexpectedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo); + +static UINT32 +ApCheckForSpecialName ( + ACPI_PARSE_OBJECT *Op, + char *Name); + +static void +ApCheckObjectType ( + ACPI_PARSE_OBJECT *Op, + UINT32 ExpectedBtypes); + +static void +ApGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes); + + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *AcpiRtypeNames[] = +{ + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + +/* + * Predefined names for use in Resource Descriptors. These names do not + * appear in the global Predefined Name table (since these names never + * appear in actual AML byte code, only in the original ASL) + */ +static const ACPI_PREDEFINED_INFO ResourceNames[] = { + {{"_ALN", 0, 0}}, + {{"_ASI", 0, 0}}, + {{"_ASZ", 0, 0}}, + {{"_ATT", 0, 0}}, + {{"_BAS", 0, 0}}, + {{"_BM_", 0, 0}}, + {{"_DBT", 0, 0}}, /* Acpi 5.0 */ + {{"_DEC", 0, 0}}, + {{"_DPL", 0, 0}}, /* Acpi 5.0 */ + {{"_DRS", 0, 0}}, /* Acpi 5.0 */ + {{"_END", 0, 0}}, /* Acpi 5.0 */ + {{"_FLC", 0, 0}}, /* Acpi 5.0 */ + {{"_GRA", 0, 0}}, + {{"_HE_", 0, 0}}, + {{"_INT", 0, 0}}, + {{"_IOR", 0, 0}}, /* Acpi 5.0 */ + {{"_LEN", 0, 0}}, + {{"_LIN", 0, 0}}, /* Acpi 5.0 */ + {{"_LL_", 0, 0}}, + {{"_MAF", 0, 0}}, + {{"_MAX", 0, 0}}, + {{"_MEM", 0, 0}}, + {{"_MIF", 0, 0}}, + {{"_MIN", 0, 0}}, + {{"_MOD", 0, 0}}, /* Acpi 5.0 */ + {{"_MTP", 0, 0}}, + {{"_PAR", 0, 0}}, /* Acpi 5.0 */ + {{"_PHA", 0, 0}}, /* Acpi 5.0 */ + {{"_PIN", 0, 0}}, /* Acpi 5.0 */ + {{"_PPI", 0, 0}}, /* Acpi 5.0 */ + {{"_POL", 0, 0}}, /* Acpi 5.0 */ + {{"_RBO", 0, 0}}, + {{"_RBW", 0, 0}}, + {{"_RNG", 0, 0}}, + {{"_RT_", 0, 0}}, /* Acpi 3.0 */ + {{"_RW_", 0, 0}}, + {{"_RXL", 0, 0}}, /* Acpi 5.0 */ + {{"_SHR", 0, 0}}, + {{"_SIZ", 0, 0}}, + {{"_SLV", 0, 0}}, /* Acpi 5.0 */ + {{"_SPE", 0, 0}}, /* Acpi 5.0 */ + {{"_STB", 0, 0}}, /* Acpi 5.0 */ + {{"_TRA", 0, 0}}, + {{"_TRS", 0, 0}}, + {{"_TSF", 0, 0}}, /* Acpi 3.0 */ + {{"_TTP", 0, 0}}, + {{"_TXL", 0, 0}}, /* Acpi 5.0 */ + {{"_TYP", 0, 0}}, + {{"_VEN", 0, 0}}, /* Acpi 5.0 */ + {{{0,0,0,0}, 0, 0}} /* Table terminator */ +}; + +static const ACPI_PREDEFINED_INFO ScopeNames[] = { + {{"_SB_", 0, 0}}, + {{"_SI_", 0, 0}}, + {{"_TZ_", 0, 0}}, + {{{0,0,0,0}, 0, 0}} /* Table terminator */ +}; + + +/******************************************************************************* + * + * FUNCTION: ApCheckForPredefinedMethod + * + * PARAMETERS: Op - A parse node of type "METHOD". + * MethodInfo - Saved info about this method + * + * RETURN: None + * + * DESCRIPTION: If method is a predefined name, check that the number of + * arguments and the return type (returns a value or not) + * is correct. + * + ******************************************************************************/ + +BOOLEAN +ApCheckForPredefinedMethod ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo) +{ + UINT32 Index; + UINT32 RequiredArgsCurrent; + UINT32 RequiredArgsOld; + + + /* Check for a match against the predefined name list */ + + Index = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); + + switch (Index) + { + case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ + case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ + case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ + + /* Just return, nothing to do */ + return (FALSE); + + + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ + + Gbl_ReservedMethods++; + + /* NumArguments must be zero for all _Lxx/_Exx/_Wxx/_Qxx methods */ + + if (MethodInfo->NumArguments != 0) + { + sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 0); + + AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, + MsgBuffer); + } + break; + + + default: + /* + * Matched a predefined method name + * + * Validate the ASL-defined argument count. Allow two different legal + * arg counts. + */ + Gbl_ReservedMethods++; + + RequiredArgsCurrent = PredefinedNames[Index].Info.ParamCount & 0x0F; + RequiredArgsOld = PredefinedNames[Index].Info.ParamCount >> 4; + + if ((MethodInfo->NumArguments != RequiredArgsCurrent) && + (MethodInfo->NumArguments != RequiredArgsOld)) + { + sprintf (MsgBuffer, "%4.4s requires %u", + PredefinedNames[Index].Info.Name, RequiredArgsCurrent); + + if (MethodInfo->NumArguments > RequiredArgsCurrent) + { + AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, + MsgBuffer); + } + else + { + AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op, + MsgBuffer); + } + } + + /* + * Check if method returns no value, but the predefined name is + * required to return a value + */ + if (MethodInfo->NumReturnNoValue && + PredefinedNames[Index].Info.ExpectedBtypes) + { + ApGetExpectedTypes (StringBuffer, + PredefinedNames[Index].Info.ExpectedBtypes); + + sprintf (MsgBuffer, "%s required for %4.4s", + StringBuffer, PredefinedNames[Index].Info.Name); + + AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, + MsgBuffer); + } + break; + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckForUnexpectedReturnValue + * + * PARAMETERS: Op - A parse node of type "RETURN". + * MethodInfo - Saved info about this method + * + * RETURN: None + * + * DESCRIPTION: Check for an unexpected return value from a predefined method. + * Invoked for predefined methods that are defined to not return + * any value. If there is a return value, issue a remark, since + * the ASL writer may be confused as to the method definition + * and/or functionality. + * + * Note: We ignore all return values of "Zero", since this is what a standalone + * Return() statement will always generate -- so we ignore it here -- + * i.e., there is no difference between Return() and Return(Zero). + * Also, a null Return() will be disassembled to return(Zero) -- so, we + * don't want to generate extraneous remarks/warnings for a disassembled + * ASL file. + * + ******************************************************************************/ + +static void +ApCheckForUnexpectedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo) +{ + ACPI_PARSE_OBJECT *ReturnValueOp; + + + /* Ignore Return() and Return(Zero) (they are the same) */ + + ReturnValueOp = Op->Asl.Child; + if (ReturnValueOp->Asl.ParseOpcode == PARSEOP_ZERO) + { + return; + } + + /* We have a valid return value, but the reserved name did not expect it */ + + AslError (ASL_WARNING, ASL_MSG_RESERVED_NO_RETURN_VAL, + Op, MethodInfo->Op->Asl.ExternalName); +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckPredefinedReturnValue + * + * PARAMETERS: Op - A parse node of type "RETURN". + * MethodInfo - Saved info about this method + * + * RETURN: None + * + * DESCRIPTION: If method is a predefined name, attempt to validate the return + * value. Only "static" types can be validated - a simple return + * of an integer/string/buffer/package or a named reference to + * a static object. Values such as a Localx or Argx or a control + * method invocation are not checked. Issue a warning if there is + * a valid return value, but the reserved method defines no + * return value. + * + ******************************************************************************/ + +void +ApCheckPredefinedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo) +{ + UINT32 Index; + ACPI_PARSE_OBJECT *ReturnValueOp; + + + /* Check parent method for a match against the predefined name list */ + + Index = ApCheckForPredefinedName (MethodInfo->Op, + MethodInfo->Op->Asl.NameSeg); + + switch (Index) + { + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ + + /* No return value expected, warn if there is one */ + + ApCheckForUnexpectedReturnValue (Op, MethodInfo); + return; + + case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ + case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ + case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ + + /* Just return, nothing to do */ + return; + + default: /* A standard predefined ACPI name */ + + if (!PredefinedNames[Index].Info.ExpectedBtypes) + { + /* No return value expected, warn if there is one */ + + ApCheckForUnexpectedReturnValue (Op, MethodInfo); + return; + } + + /* Get the object returned, it is the next argument */ + + ReturnValueOp = Op->Asl.Child; + switch (ReturnValueOp->Asl.ParseOpcode) + { + case PARSEOP_ZERO: + case PARSEOP_ONE: + case PARSEOP_ONES: + case PARSEOP_INTEGER: + case PARSEOP_STRING_LITERAL: + case PARSEOP_BUFFER: + case PARSEOP_PACKAGE: + + /* Static data return object - check against expected type */ + + ApCheckObjectType (ReturnValueOp, + PredefinedNames[Index].Info.ExpectedBtypes); + break; + + default: + + /* + * All other ops are very difficult or impossible to typecheck at + * compile time. These include all Localx, Argx, and method + * invocations. Also, NAMESEG and NAMESTRING because the type of + * any named object can be changed at runtime (for example, + * CopyObject will change the type of the target object.) + */ + break; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckForPredefinedObject + * + * PARAMETERS: Op - A parse node + * Name - The ACPI name to be checked + * + * RETURN: None + * + * DESCRIPTION: Check for a predefined name for a static object (created via + * the ASL Name operator). If it is a predefined ACPI name, ensure + * that the name does not require any arguments (which would + * require a control method implemenation of the name), and that + * the type of the object is one of the expected types for the + * predefined name. + * + ******************************************************************************/ + +void +ApCheckForPredefinedObject ( + ACPI_PARSE_OBJECT *Op, + char *Name) +{ + UINT32 Index; + + + /* + * Check for a real predefined name -- not a resource descriptor name + * or a predefined scope name + */ + Index = ApCheckForPredefinedName (Op, Name); + + switch (Index) + { + case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ + case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ + case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ + + /* Nothing to do */ + return; + + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ + + /* + * These names must be control methods, by definition in ACPI spec. + * Also because they are defined to return no value. None of them + * require any arguments. + */ + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with zero arguments"); + return; + + default: /* A standard predefined ACPI name */ + + /* + * If this predefined name requires input arguments, then + * it must be implemented as a control method + */ + if (PredefinedNames[Index].Info.ParamCount > 0) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with arguments"); + return; + } + + /* + * If no return value is expected from this predefined name, then + * it follows that it must be implemented as a control method + * (with zero args, because the args > 0 case was handled above) + * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx + */ + if (!PredefinedNames[Index].Info.ExpectedBtypes) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with zero arguments"); + return; + } + + /* Typecheck the actual object, it is the next argument */ + + ApCheckObjectType (Op->Asl.Child->Asl.Next, + PredefinedNames[Index].Info.ExpectedBtypes); + return; + } +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckForPredefinedName + * + * PARAMETERS: Op - A parse node + * Name - NameSeg to check + * + * RETURN: None + * + * DESCRIPTION: Check a NameSeg against the reserved list. + * + ******************************************************************************/ + +UINT32 +ApCheckForPredefinedName ( + ACPI_PARSE_OBJECT *Op, + char *Name) +{ + UINT32 i; + + + if (Name[0] == 0) + { + AcpiOsPrintf ("Found a null name, external = %s\n", + Op->Asl.ExternalName); + } + + /* All reserved names are prefixed with a single underscore */ + + if (Name[0] != '_') + { + return (ACPI_NOT_RESERVED_NAME); + } + + /* Check for a standard predefined method name */ + + for (i = 0; PredefinedNames[i].Info.Name[0]; i++) + { + if (ACPI_COMPARE_NAME (Name, PredefinedNames[i].Info.Name)) + { + /* Return index into predefined array */ + return (i); + } + } + + /* Check for resource names and predefined scope names */ + + for (i = 0; ResourceNames[i].Info.Name[0]; i++) + { + if (ACPI_COMPARE_NAME (Name, ResourceNames[i].Info.Name)) + { + return (ACPI_PREDEFINED_NAME); + } + } + + for (i = 0; ScopeNames[i].Info.Name[0]; i++) + { + if (ACPI_COMPARE_NAME (Name, ScopeNames[i].Info.Name)) + { + return (ACPI_PREDEFINED_NAME); + } + } + + /* Check for _Lxx/_Exx/_Wxx/_Qxx/_T_x. Warning if unknown predefined name */ + + return (ApCheckForSpecialName (Op, Name)); +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckForSpecialName + * + * PARAMETERS: Op - A parse node + * Name - NameSeg to check + * + * RETURN: None + * + * DESCRIPTION: Check for the "special" predefined names - + * _Lxx, _Exx, _Qxx, _Wxx, and _T_x + * + ******************************************************************************/ + +static UINT32 +ApCheckForSpecialName ( + ACPI_PARSE_OBJECT *Op, + char *Name) +{ + + /* + * Check for the "special" predefined names. We already know that the + * first character is an underscore. + * GPE: _Lxx + * GPE: _Exx + * GPE: _Wxx + * EC: _Qxx + */ + if ((Name[1] == 'L') || + (Name[1] == 'E') || + (Name[1] == 'W') || + (Name[1] == 'Q')) + { + /* The next two characters must be hex digits */ + + if ((isxdigit ((int) Name[2])) && + (isxdigit ((int) Name[3]))) + { + return (ACPI_EVENT_RESERVED_NAME); + } + } + + /* Check for the names reserved for the compiler itself: _T_x */ + + else if ((Op->Asl.ExternalName[1] == 'T') && + (Op->Asl.ExternalName[2] == '_')) + { + /* Ignore if actually emitted by the compiler */ + + if (Op->Asl.CompileFlags & NODE_COMPILER_EMITTED) + { + return (ACPI_NOT_RESERVED_NAME); + } + + /* + * Was not actually emitted by the compiler. This is a special case, + * however. If the ASL code being compiled was the result of a + * dissasembly, it may possibly contain valid compiler-emitted names + * of the form "_T_x". We don't want to issue an error or even a + * warning and force the user to manually change the names. So, we + * will issue a remark instead. + */ + AslError (ASL_REMARK, ASL_MSG_COMPILER_RESERVED, Op, Op->Asl.ExternalName); + return (ACPI_COMPILER_RESERVED_NAME); + } + + /* + * The name didn't match any of the known predefined names. Flag it as a + * warning, since the entire namespace starting with an underscore is + * reserved by the ACPI spec. + */ + AslError (ASL_WARNING, ASL_MSG_UNKNOWN_RESERVED_NAME, Op, + Op->Asl.ExternalName); + + return (ACPI_NOT_RESERVED_NAME); +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckObjectType + * + * PARAMETERS: Op - Current parse node + * ExpectedBtypes - Bitmap of expected return type(s) + * + * RETURN: None + * + * DESCRIPTION: Check if the object type is one of the types that is expected + * by the predefined name. Only a limited number of object types + * can be returned by the predefined names. + * + ******************************************************************************/ + +static void +ApCheckObjectType ( + ACPI_PARSE_OBJECT *Op, + UINT32 ExpectedBtypes) +{ + UINT32 ReturnBtype; + + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_ZERO: + case PARSEOP_ONE: + case PARSEOP_ONES: + case PARSEOP_INTEGER: + ReturnBtype = ACPI_RTYPE_INTEGER; + break; + + case PARSEOP_BUFFER: + ReturnBtype = ACPI_RTYPE_BUFFER; + break; + + case PARSEOP_STRING_LITERAL: + ReturnBtype = ACPI_RTYPE_STRING; + break; + + case PARSEOP_PACKAGE: + case PARSEOP_VAR_PACKAGE: + ReturnBtype = ACPI_RTYPE_PACKAGE; + break; + + default: + /* Not one of the supported object types */ + + goto TypeErrorExit; + } + + /* Exit if the object is one of the expected types */ + + if (ReturnBtype & ExpectedBtypes) + { + return; + } + + +TypeErrorExit: + + /* Format the expected types and emit an error message */ + + ApGetExpectedTypes (StringBuffer, ExpectedBtypes); + + sprintf (MsgBuffer, "found %s, requires %s", + UtGetOpName (Op->Asl.ParseOpcode), StringBuffer); + + AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, + MsgBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: ApDisplayReservedNames + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump information about the ACPI predefined names and predefined + * resource descriptor names. + * + ******************************************************************************/ + +void +ApDisplayReservedNames ( + void) +{ + const ACPI_PREDEFINED_INFO *ThisName; + char TypeBuffer[48]; /* Room for 5 types */ + UINT32 Count; + + + /* + * Predefined names/methods + */ + printf ("\nPredefined Name Information\n\n"); + + Count = 0; + ThisName = PredefinedNames; + while (ThisName->Info.Name[0]) + { + printf ("%4.4s Requires %u arguments, ", + ThisName->Info.Name, ThisName->Info.ParamCount & 0x0F); + + if (ThisName->Info.ExpectedBtypes) + { + ApGetExpectedTypes (TypeBuffer, ThisName->Info.ExpectedBtypes); + printf ("Must return: %s\n", TypeBuffer); + } + else + { + printf ("No return value\n"); + } + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE) + { + ThisName++; + } + + Count++; + ThisName++; + } + + printf ("%u Predefined Names are recognized\n", Count); + + /* + * Resource Descriptor names + */ + printf ("\nResource Descriptor Predefined Names\n\n"); + + Count = 0; + ThisName = ResourceNames; + while (ThisName->Info.Name[0]) + { + printf ("%4.4s Resource Descriptor\n", ThisName->Info.Name); + Count++; + ThisName++; + } + + printf ("%u Resource Descriptor Names are recognized\n", Count); + + /* + * Predefined scope names + */ + printf ("\nPredefined Scope Names\n\n"); + + ThisName = ScopeNames; + while (ThisName->Info.Name[0]) + { + printf ("%4.4s Scope\n", ThisName->Info.Name); + ThisName++; + } +} + + +/******************************************************************************* + * + * FUNCTION: ApGetExpectedTypes + * + * PARAMETERS: Buffer - Where the formatted string is returned + * ExpectedBTypes - Bitfield of expected data types + * + * RETURN: None, formatted string + * + * DESCRIPTION: Format the expected object types into a printable string. + * + ******************************************************************************/ + +static void +ApGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes) +{ + UINT32 ThisRtype; + UINT32 i; + UINT32 j; + + + j = 1; + Buffer[0] = 0; + ThisRtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) + { + /* If one of the expected types, concatenate the name of this type */ + + if (ExpectedBtypes & ThisRtype) + { + ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]); + j = 0; /* Use name separator from now on */ + } + ThisRtype <<= 1; /* Next Rtype */ + } +} diff --git a/source/compiler/aslresource.c b/source/compiler/aslresource.c new file mode 100644 index 000000000000..8dbbb2652f85 --- /dev/null +++ b/source/compiler/aslresource.c @@ -0,0 +1,1066 @@ + +/****************************************************************************** + * + * Module Name: aslresource - Resource template/descriptor utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslresource") + + +/******************************************************************************* + * + * FUNCTION: RsSmallAddressCheck + * + * PARAMETERS: Minimum - Address Min value + * Maximum - Address Max value + * Length - Address range value + * Alignment - Address alignment value + * MinOp - Original Op for Address Min + * MaxOp - Original Op for Address Max + * LengthOp - Original Op for address range + * AlignOp - Original Op for address alignment. If + * NULL, means "zero value for alignment is + * OK, and means 64K alignment" (for + * Memory24 descriptor) + * Op - Parent Op for entire construct + * + * RETURN: None. Adds error messages to error log if necessary + * + * DESCRIPTION: Perform common value checks for "small" address descriptors. + * Currently: + * Io, Memory24, Memory32 + * + ******************************************************************************/ + +void +RsSmallAddressCheck ( + UINT8 Type, + UINT32 Minimum, + UINT32 Maximum, + UINT32 Length, + UINT32 Alignment, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *AlignOp, + ACPI_PARSE_OBJECT *Op) +{ + + if (Gbl_NoResourceChecking) + { + return; + } + + /* + * Check for a so-called "null descriptor". These are descriptors that are + * created with most fields set to zero. The intent is that the descriptor + * will be updated/completed at runtime via a BufferField. + * + * If the descriptor does NOT have a resource tag, it cannot be referenced + * by a BufferField and we will flag this as an error. Conversely, if + * the descriptor has a resource tag, we will assume that a BufferField + * will be used to dynamically update it, so no error. + * + * A possible enhancement to this check would be to verify that in fact + * a BufferField is created using the resource tag, and perhaps even + * verify that a Store is performed to the BufferField. + * + * Note: for these descriptors, Alignment is allowed to be zero + */ + if (!Minimum && !Maximum && !Length) + { + if (!Op->Asl.ExternalName) + { + /* No resource tag. Descriptor is fixed and is also illegal */ + + AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); + } + + return; + } + + /* Special case for Memory24, values are compressed */ + + if (Type == ACPI_RESOURCE_NAME_MEMORY24) + { + if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */ + { + Alignment = ACPI_UINT16_MAX + 1; + } + + Minimum <<= 8; + Maximum <<= 8; + Length *= 256; + } + + /* IO descriptor has different definition of min/max, don't check */ + + if (Type != ACPI_RESOURCE_NAME_IO) + { + /* Basic checks on Min/Max/Length */ + + if (Minimum > Maximum) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); + } + else if (Length > (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); + } + } + + /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */ + + if (!Alignment) + { + Alignment = 1; + } + + /* Addresses must be an exact multiple of the alignment value */ + + if (Minimum % Alignment) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); + } + if (Maximum % Alignment) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL); + } +} + + +/******************************************************************************* + * + * FUNCTION: RsLargeAddressCheck + * + * PARAMETERS: Minimum - Address Min value + * Maximum - Address Max value + * Length - Address range value + * Granularity - Address granularity value + * Flags - General flags for address descriptors: + * _MIF, _MAF, _DEC + * MinOp - Original Op for Address Min + * MaxOp - Original Op for Address Max + * LengthOp - Original Op for address range + * GranOp - Original Op for address granularity + * Op - Parent Op for entire construct + * + * RETURN: None. Adds error messages to error log if necessary + * + * DESCRIPTION: Perform common value checks for "large" address descriptors. + * Currently: + * WordIo, WordBusNumber, WordSpace + * DWordIo, DWordMemory, DWordSpace + * QWordIo, QWordMemory, QWordSpace + * ExtendedIo, ExtendedMemory, ExtendedSpace + * + * _MIF flag set means that the minimum address is fixed and is not relocatable + * _MAF flag set means that the maximum address is fixed and is not relocatable + * Length of zero means that the record size is variable + * + * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40 + * of the ACPI 4.0a specification. Added 04/2010. + * + ******************************************************************************/ + +void +RsLargeAddressCheck ( + UINT64 Minimum, + UINT64 Maximum, + UINT64 Length, + UINT64 Granularity, + UINT8 Flags, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *GranOp, + ACPI_PARSE_OBJECT *Op) +{ + + if (Gbl_NoResourceChecking) + { + return; + } + + /* + * Check for a so-called "null descriptor". These are descriptors that are + * created with most fields set to zero. The intent is that the descriptor + * will be updated/completed at runtime via a BufferField. + * + * If the descriptor does NOT have a resource tag, it cannot be referenced + * by a BufferField and we will flag this as an error. Conversely, if + * the descriptor has a resource tag, we will assume that a BufferField + * will be used to dynamically update it, so no error. + * + * A possible enhancement to this check would be to verify that in fact + * a BufferField is created using the resource tag, and perhaps even + * verify that a Store is performed to the BufferField. + */ + if (!Minimum && !Maximum && !Length && !Granularity) + { + if (!Op->Asl.ExternalName) + { + /* No resource tag. Descriptor is fixed and is also illegal */ + + AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); + } + + return; + } + + /* Basic checks on Min/Max/Length */ + + if (Minimum > Maximum) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); + return; + } + else if (Length > (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); + return; + } + + /* If specified (non-zero), ensure granularity is a power-of-two minus one */ + + if (Granularity) + { + if ((Granularity + 1) & + Granularity) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL); + return; + } + } + + /* + * Check the various combinations of Length, MinFixed, and MaxFixed + */ + if (Length) + { + /* Fixed non-zero length */ + + switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) + { + case 0: + /* + * Fixed length, variable locations (both _MIN and _MAX). + * Length must be a multiple of granularity + */ + if (Granularity & Length) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL); + } + break; + + case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): + + /* Fixed length, fixed location. Granularity must be zero */ + + if (Granularity != 0) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL); + } + + /* Length must be exactly the size of the min/max window */ + + if (Length != (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL); + } + break; + + /* All other combinations are invalid */ + + case ACPI_RESOURCE_FLAG_MIF: + case ACPI_RESOURCE_FLAG_MAF: + default: + AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); + } + } + else + { + /* Variable length (length==0) */ + + switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) + { + case 0: + /* + * Both _MIN and _MAX are variable. + * No additional requirements, just exit + */ + break; + + case ACPI_RESOURCE_FLAG_MIF: + + /* _MIN is fixed. _MIN must be multiple of _GRA */ + + /* + * The granularity is defined by the ACPI specification to be a + * power-of-two minus one, therefore the granularity is a + * bitmask which can be used to easily validate the addresses. + */ + if (Granularity & Minimum) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); + } + break; + + case ACPI_RESOURCE_FLAG_MAF: + + /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */ + + if (Granularity & (Maximum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1"); + } + break; + + /* Both MIF/MAF set is invalid if length is zero */ + + case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): + default: + AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: RsGetStringDataLength + * + * PARAMETERS: InitializerOp - Start of a subtree of init nodes + * + * RETURN: Valid string length if a string node is found (otherwise 0) + * + * DESCRIPTION: In a list of peer nodes, find the first one that contains a + * string and return the length of the string. + * + ******************************************************************************/ + +UINT16 +RsGetStringDataLength ( + ACPI_PARSE_OBJECT *InitializerOp) +{ + + while (InitializerOp) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) + { + return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1)); + } + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + } + + return 0; +} + + +/******************************************************************************* + * + * FUNCTION: RsAllocateResourceNode + * + * PARAMETERS: Size - Size of node in bytes + * + * RETURN: The allocated node - aborts on allocation failure + * + * DESCRIPTION: Allocate a resource description node and the resource + * descriptor itself (the nodes are used to link descriptors). + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsAllocateResourceNode ( + UINT32 Size) +{ + ASL_RESOURCE_NODE *Rnode; + + + /* Allocate the node */ + + Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE)); + + /* Allocate the resource descriptor itself */ + + Rnode->Buffer = UtLocalCalloc (Size); + Rnode->BufferLength = Size; + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsCreateResourceField + * + * PARAMETERS: Op - Resource field node + * Name - Name of the field (Used only to reference + * the field in the ASL, not in the AML) + * ByteOffset - Offset from the field start + * BitOffset - Additional bit offset + * BitLength - Number of bits in the field + * + * RETURN: None, sets fields within the input node + * + * DESCRIPTION: Utility function to generate a named bit field within a + * resource descriptor. Mark a node as 1) a field in a resource + * descriptor, and 2) set the value to be a BIT offset + * + ******************************************************************************/ + +void +RsCreateResourceField ( + ACPI_PARSE_OBJECT *Op, + char *Name, + UINT32 ByteOffset, + UINT32 BitOffset, + UINT32 BitLength) +{ + + Op->Asl.ExternalName = Name; + Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; + + + Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset; + Op->Asl.Value.Tag.BitLength = BitLength; +} + + +/******************************************************************************* + * + * FUNCTION: RsSetFlagBits + * + * PARAMETERS: *Flags - Pointer to the flag byte + * Op - Flag initialization node + * Position - Bit position within the flag byte + * Default - Used if the node is DEFAULT. + * + * RETURN: Sets bits within the *Flags output byte. + * + * DESCRIPTION: Set a bit in a cumulative flags word from an initialization + * node. Will use a default value if the node is DEFAULT, meaning + * that no value was specified in the ASL. Used to merge multiple + * keywords into a single flags byte. + * + ******************************************************************************/ + +void +RsSetFlagBits ( + UINT8 *Flags, + ACPI_PARSE_OBJECT *Op, + UINT8 Position, + UINT8 DefaultBit) +{ + + if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* Use the default bit */ + + *Flags |= (DefaultBit << Position); + } + else + { + /* Use the bit specified in the initialization node */ + + *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position); + } +} + + +void +RsSetFlagBits16 ( + UINT16 *Flags, + ACPI_PARSE_OBJECT *Op, + UINT8 Position, + UINT8 DefaultBit) +{ + + if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* Use the default bit */ + + *Flags |= (DefaultBit << Position); + } + else + { + /* Use the bit specified in the initialization node */ + + *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position); + } +} + + +/******************************************************************************* + * + * FUNCTION: RsCompleteNodeAndGetNext + * + * PARAMETERS: Op - Resource node to be completed + * + * RETURN: The next peer to the input node. + * + * DESCRIPTION: Mark the current node completed and return the next peer. + * The node ParseOpcode is set to DEFAULT_ARG, meaning that + * this node is to be ignored from now on. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +RsCompleteNodeAndGetNext ( + ACPI_PARSE_OBJECT *Op) +{ + + /* Mark this node unused */ + + Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + + /* Move on to the next peer node in the initializer list */ + + return (ASL_GET_PEER_NODE (Op)); +} + + +/******************************************************************************* + * + * FUNCTION: RsCheckListForDuplicates + * + * PARAMETERS: Op - First op in the initializer list + * + * RETURN: None + * + * DESCRIPTION: Check an initializer list for duplicate values. Emits an error + * if any duplicates are found. + * + ******************************************************************************/ + +void +RsCheckListForDuplicates ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *NextValueOp = Op; + ACPI_PARSE_OBJECT *NextOp; + UINT32 Value; + + + if (!Op) + { + return; + } + + /* Search list once for each value in the list */ + + while (NextValueOp) + { + Value = (UINT32) NextValueOp->Asl.Value.Integer; + + /* Compare this value to all remaining values in the list */ + + NextOp = ASL_GET_PEER_NODE (NextValueOp); + while (NextOp) + { + if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Compare values */ + + if (Value == (UINT32) NextOp->Asl.Value.Integer) + { + /* Emit error only once per duplicate node */ + + if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE)) + { + NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE; + AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM, + NextOp, NULL); + } + } + } + + NextOp = ASL_GET_PEER_NODE (NextOp); + } + + NextValueOp = ASL_GET_PEER_NODE (NextValueOp); + } +} + + +/******************************************************************************* + * + * FUNCTION: RsDoOneResourceDescriptor + * + * PARAMETERS: DescriptorTypeOp - Parent parse node of the descriptor + * CurrentByteOffset - Offset in the resource descriptor + * buffer. + * + * RETURN: A valid resource node for the descriptor + * + * DESCRIPTION: Dispatches the processing of one resource descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoOneResourceDescriptor ( + ACPI_PARSE_OBJECT *DescriptorTypeOp, + UINT32 CurrentByteOffset, + UINT8 *State) +{ + ASL_RESOURCE_NODE *Rnode = NULL; + + + /* Construct the resource */ + + switch (DescriptorTypeOp->Asl.ParseOpcode) + { + case PARSEOP_DMA: + Rnode = RsDoDmaDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_FIXEDDMA: + Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_DWORDIO: + Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_DWORDMEMORY: + Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_DWORDSPACE: + Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_ENDDEPENDENTFN: + switch (*State) + { + case ACPI_RSTATE_NORMAL: + AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT, + DescriptorTypeOp, NULL); + break; + + case ACPI_RSTATE_START_DEPENDENT: + AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, + DescriptorTypeOp, NULL); + break; + + case ACPI_RSTATE_DEPENDENT_LIST: + default: + break; + } + + *State = ACPI_RSTATE_NORMAL; + Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_ENDTAG: + Rnode = RsDoEndTagDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_EXTENDEDIO: + Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_EXTENDEDMEMORY: + Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_EXTENDEDSPACE: + Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_FIXEDIO: + Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_INTERRUPT: + Rnode = RsDoInterruptDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_IO: + Rnode = RsDoIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_IRQ: + Rnode = RsDoIrqDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_IRQNOFLAGS: + Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_MEMORY24: + Rnode = RsDoMemory24Descriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_MEMORY32: + Rnode = RsDoMemory32Descriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_MEMORY32FIXED: + Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_QWORDIO: + Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_QWORDMEMORY: + Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_QWORDSPACE: + Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_REGISTER: + Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_STARTDEPENDENTFN: + switch (*State) + { + case ACPI_RSTATE_START_DEPENDENT: + AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, + DescriptorTypeOp, NULL); + break; + + case ACPI_RSTATE_NORMAL: + case ACPI_RSTATE_DEPENDENT_LIST: + default: + break; + } + + *State = ACPI_RSTATE_START_DEPENDENT; + Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp, + CurrentByteOffset); + *State = ACPI_RSTATE_DEPENDENT_LIST; + break; + + case PARSEOP_STARTDEPENDENTFN_NOPRI: + switch (*State) + { + case ACPI_RSTATE_START_DEPENDENT: + AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, + DescriptorTypeOp, NULL); + break; + + case ACPI_RSTATE_NORMAL: + case ACPI_RSTATE_DEPENDENT_LIST: + default: + break; + } + + *State = ACPI_RSTATE_START_DEPENDENT; + Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp, + CurrentByteOffset); + *State = ACPI_RSTATE_DEPENDENT_LIST; + break; + + case PARSEOP_VENDORLONG: + Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_VENDORSHORT: + Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_WORDBUSNUMBER: + Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_WORDIO: + Rnode = RsDoWordIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_WORDSPACE: + Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_GPIO_INT: + Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_GPIO_IO: + Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_I2C_SERIALBUS: + Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_SPI_SERIALBUS: + Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_UART_SERIALBUS: + Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp, + CurrentByteOffset); + break; + + case PARSEOP_DEFAULT_ARG: + /* Just ignore any of these, they are used as fillers/placeholders */ + break; + + default: + printf ("Unknown resource descriptor type [%s]\n", + DescriptorTypeOp->Asl.ParseOpName); + break; + } + + /* + * Mark original node as unused, but head of a resource descriptor. + * This allows the resource to be installed in the namespace so that + * references to the descriptor can be resolved. + */ + DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC; + DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset; + + if (Rnode) + { + DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength; + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsLinkDescriptorChain + * + * PARAMETERS: PreviousRnode - Pointer to the node that will be previous + * to the linked node, At exit, set to the + * last node in the new chain. + * Rnode - Resource node to link into the list + * + * RETURN: Cumulative buffer byte offset of the new segment of chain + * + * DESCRIPTION: Link a descriptor chain at the end of an existing chain. + * + ******************************************************************************/ + +UINT32 +RsLinkDescriptorChain ( + ASL_RESOURCE_NODE **PreviousRnode, + ASL_RESOURCE_NODE *Rnode) +{ + ASL_RESOURCE_NODE *LastRnode; + UINT32 CurrentByteOffset; + + + /* Anything to do? */ + + if (!Rnode) + { + return 0; + } + + /* Point the previous node to the new node */ + + (*PreviousRnode)->Next = Rnode; + CurrentByteOffset = Rnode->BufferLength; + + /* Walk to the end of the chain headed by Rnode */ + + LastRnode = Rnode; + while (LastRnode->Next) + { + LastRnode = LastRnode->Next; + CurrentByteOffset += LastRnode->BufferLength; + } + + /* Previous node becomes the last node in the chain */ + + *PreviousRnode = LastRnode; + return CurrentByteOffset; +} + + +/******************************************************************************* + * + * FUNCTION: RsDoResourceTemplate + * + * PARAMETERS: Op - Parent of a resource template list + * + * RETURN: None. Sets input node to point to a list of AML code + * + * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer, + * in preparation for output to the AML output file. + * + ******************************************************************************/ + +void +RsDoResourceTemplate ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *BufferLengthOp; + ACPI_PARSE_OBJECT *BufferOp; + ACPI_PARSE_OBJECT *DescriptorTypeOp; + ACPI_PARSE_OBJECT *LastOp = NULL; + UINT32 CurrentByteOffset = 0; + ASL_RESOURCE_NODE HeadRnode; + ASL_RESOURCE_NODE *PreviousRnode; + ASL_RESOURCE_NODE *Rnode; + UINT8 State; + + + /* Mark parent as containing a resource template */ + + if (Op->Asl.Parent) + { + Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC; + } + + /* ResourceTemplate Opcode is first (Op) */ + /* Buffer Length node is first child */ + + BufferLengthOp = ASL_GET_CHILD_NODE (Op); + + /* Buffer Op is first peer */ + + BufferOp = ASL_GET_PEER_NODE (BufferLengthOp); + + /* First Descriptor type is next */ + + DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp); + + /* + * Process all resource descriptors in the list + * Note: It is assumed that the EndTag node has been automatically + * inserted at the end of the template by the parser. + */ + State = ACPI_RSTATE_NORMAL; + PreviousRnode = &HeadRnode; + while (DescriptorTypeOp) + { + DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC; + Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset, + &State); + + /* + * Update current byte offset to indicate the number of bytes from the + * start of the buffer. Buffer can include multiple descriptors, we + * must keep track of the offset of not only each descriptor, but each + * element (field) within each descriptor as well. + */ + CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode); + + /* Get the next descriptor in the list */ + + LastOp = DescriptorTypeOp; + DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp); + } + + if (State == ACPI_RSTATE_DEPENDENT_LIST) + { + if (LastOp) + { + LastOp = LastOp->Asl.Parent; + } + AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL); + } + + /* + * Transform the nodes into the following + * + * Op -> AML_BUFFER_OP + * First Child -> BufferLength + * Second Child -> Descriptor Buffer (raw byte data) + */ + Op->Asl.ParseOpcode = PARSEOP_BUFFER; + Op->Asl.AmlOpcode = AML_BUFFER_OP; + Op->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC; + UtSetParseOpName (Op); + + BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; + BufferLengthOp->Asl.Value.Integer = CurrentByteOffset; + (void) OpcSetOptimalIntegerSize (BufferLengthOp); + UtSetParseOpName (BufferLengthOp); + + BufferOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; + BufferOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN; + BufferOp->Asl.AmlOpcodeLength = 0; + BufferOp->Asl.AmlLength = CurrentByteOffset; + BufferOp->Asl.Value.Buffer = (UINT8 *) HeadRnode.Next; + BufferOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DATA; + UtSetParseOpName (BufferOp); + + return; +} diff --git a/source/compiler/aslrestype1.c b/source/compiler/aslrestype1.c new file mode 100644 index 000000000000..d137fe3061ff --- /dev/null +++ b/source/compiler/aslrestype1.c @@ -0,0 +1,645 @@ + +/****************************************************************************** + * + * Module Name: aslrestype1 - Miscellaneous small resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype1") + +/* + * This module contains miscellaneous small resource descriptors: + * + * EndTag + * EndDependentFn + * Memory24 + * Memory32 + * Memory32Fixed + * StartDependentFn + * StartDependentFnNoPri + * VendorShort + */ + +/******************************************************************************* + * + * FUNCTION: RsDoEndTagDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "EndDependentFn" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoEndTagDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ASL_RESOURCE_NODE *Rnode; + + + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_END_TAG)); + + Descriptor = Rnode->Buffer; + Descriptor->EndTag.DescriptorType = ACPI_RESOURCE_NAME_END_TAG | + ASL_RDESC_END_TAG_SIZE; + Descriptor->EndTag.Checksum = 0; + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoEndDependentDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "EndDependentFn" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoEndDependentDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ASL_RESOURCE_NODE *Rnode; + + + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_END_DEPENDENT)); + + Descriptor = Rnode->Buffer; + Descriptor->EndDpf.DescriptorType = ACPI_RESOURCE_NAME_END_DEPENDENT | + ASL_RDESC_END_DEPEND_SIZE; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoMemory24Descriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "Memory24" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoMemory24Descriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_MEMORY24)); + + Descriptor = Rnode->Buffer; + Descriptor->Memory24.DescriptorType = ACPI_RESOURCE_NAME_MEMORY24; + Descriptor->Memory24.ResourceLength = 9; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Read/Write type */ + + RsSetFlagBits (&Descriptor->Memory24.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Flags), 0); + break; + + case 1: /* Min Address */ + + Descriptor->Memory24.Minimum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Minimum)); + MinOp = InitializerOp; + break; + + case 2: /* Max Address */ + + Descriptor->Memory24.Maximum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Maximum)); + MaxOp = InitializerOp; + break; + + case 3: /* Alignment */ + + Descriptor->Memory24.Alignment = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_ALIGNMENT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Alignment)); + break; + + case 4: /* Length */ + + Descriptor->Memory24.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.AddressLength)); + LengthOp = InitializerOp; + break; + + case 5: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Align values (Alignment==0 means 64K) */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY24, + Descriptor->Memory24.Minimum, + Descriptor->Memory24.Maximum, + Descriptor->Memory24.AddressLength, + Descriptor->Memory24.Alignment, + MinOp, MaxOp, LengthOp, NULL, Op); + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoMemory32Descriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "Memory32" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoMemory32Descriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *AlignOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_MEMORY32)); + + Descriptor = Rnode->Buffer; + Descriptor->Memory32.DescriptorType = ACPI_RESOURCE_NAME_MEMORY32; + Descriptor->Memory32.ResourceLength = 17; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Read/Write type */ + + RsSetFlagBits (&Descriptor->Memory32.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Flags), 0); + break; + + case 1: /* Min Address */ + + Descriptor->Memory32.Minimum = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Minimum)); + MinOp = InitializerOp; + break; + + case 2: /* Max Address */ + + Descriptor->Memory32.Maximum = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Maximum)); + MaxOp = InitializerOp; + break; + + case 3: /* Alignment */ + + Descriptor->Memory32.Alignment = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_ALIGNMENT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Alignment)); + AlignOp = InitializerOp; + break; + + case 4: /* Length */ + + Descriptor->Memory32.AddressLength = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 5: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Align values */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY32, + Descriptor->Memory32.Minimum, + Descriptor->Memory32.Maximum, + Descriptor->Memory32.AddressLength, + Descriptor->Memory32.Alignment, + MinOp, MaxOp, LengthOp, AlignOp, Op); + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoMemory32FixedDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "Memory32Fixed" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoMemory32FixedDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_MEMORY32)); + + Descriptor = Rnode->Buffer; + Descriptor->FixedMemory32.DescriptorType = ACPI_RESOURCE_NAME_FIXED_MEMORY32; + Descriptor->FixedMemory32.ResourceLength = 9; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Read/Write type */ + + RsSetFlagBits (&Descriptor->FixedMemory32.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedMemory32.Flags), 0); + break; + + case 1: /* Address */ + + Descriptor->FixedMemory32.Address = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_BASEADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedMemory32.Address)); + break; + + case 2: /* Length */ + + Descriptor->FixedMemory32.AddressLength = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedMemory32.AddressLength)); + break; + + case 3: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoStartDependentDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "StartDependentFn" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoStartDependentDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + ASL_RESOURCE_NODE *PreviousRnode; + ASL_RESOURCE_NODE *NextRnode; + UINT32 i; + UINT8 State; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_START_DEPENDENT)); + + PreviousRnode = Rnode; + Descriptor = Rnode->Buffer; + + /* Descriptor has priority byte */ + + Descriptor->StartDpf.DescriptorType = ACPI_RESOURCE_NAME_START_DEPENDENT | + (ASL_RDESC_ST_DEPEND_SIZE + 0x01); + + /* Process all child initialization nodes */ + + State = ACPI_RSTATE_START_DEPENDENT; + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Compatibility Priority */ + + if ((UINT8) InitializerOp->Asl.Value.Integer > 2) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_PRIORITY, + InitializerOp, NULL); + } + + RsSetFlagBits (&Descriptor->StartDpf.Flags, InitializerOp, 0, 0); + break; + + case 1: /* Performance/Robustness Priority */ + + if ((UINT8) InitializerOp->Asl.Value.Integer > 2) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_PERFORMANCE, + InitializerOp, NULL); + } + + RsSetFlagBits (&Descriptor->StartDpf.Flags, InitializerOp, 2, 0); + break; + + default: + + NextRnode = RsDoOneResourceDescriptor (InitializerOp, + CurrentByteOffset, &State); + + /* + * Update current byte offset to indicate the number of bytes from the + * start of the buffer. Buffer can include multiple descriptors, we + * must keep track of the offset of not only each descriptor, but each + * element (field) within each descriptor as well. + */ + CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, + NextRnode); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoStartDependentNoPriDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "StartDependentNoPri" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoStartDependentNoPriDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + ASL_RESOURCE_NODE *PreviousRnode; + ASL_RESOURCE_NODE *NextRnode; + UINT8 State; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_START_DEPENDENT_NOPRIO)); + + Descriptor = Rnode->Buffer; + Descriptor->StartDpf.DescriptorType = ACPI_RESOURCE_NAME_START_DEPENDENT | + ASL_RDESC_ST_DEPEND_SIZE; + PreviousRnode = Rnode; + + /* Process all child initialization nodes */ + + State = ACPI_RSTATE_START_DEPENDENT; + while (InitializerOp) + { + NextRnode = RsDoOneResourceDescriptor (InitializerOp, + CurrentByteOffset, &State); + + /* + * Update current byte offset to indicate the number of bytes from the + * start of the buffer. Buffer can include multiple descriptors, we + * must keep track of the offset of not only each descriptor, but each + * element (field) within each descriptor as well. + */ + CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, NextRnode); + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoVendorSmallDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "VendorShort" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoVendorSmallDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT8 *VendorData; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* Allocate worst case - 7 vendor bytes */ + + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_SMALL) + 7); + + Descriptor = Rnode->Buffer; + Descriptor->VendorSmall.DescriptorType = ACPI_RESOURCE_NAME_VENDOR_SMALL; + VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_SMALL_HEADER); + + /* Process all child initialization nodes */ + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + for (i = 0; InitializerOp; i++) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + break; + } + + /* Maximum 7 vendor data bytes allowed (0-6) */ + + if (i >= 7) + { + AslError (ASL_ERROR, ASL_MSG_VENDOR_LIST, InitializerOp, NULL); + + /* Eat the excess initializers */ + + while (InitializerOp) + { + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + break; + } + + VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer; + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Adjust the Rnode buffer size, so correct number of bytes are emitted */ + + Rnode->BufferLength -= (7 - i); + + /* Set the length in the Type Tag */ + + Descriptor->VendorSmall.DescriptorType |= (UINT8) i; + return (Rnode); +} + diff --git a/source/compiler/aslrestype1i.c b/source/compiler/aslrestype1i.c new file mode 100644 index 000000000000..1178fd003ddb --- /dev/null +++ b/source/compiler/aslrestype1i.c @@ -0,0 +1,672 @@ + +/****************************************************************************** + * + * Module Name: aslrestype1i - Small I/O-related resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype1i") + +/* + * This module contains the I/O-related small resource descriptors: + * + * DMA + * FixedDMA + * FixedIO + * IO + * IRQ + * IRQNoFlags + */ + +/******************************************************************************* + * + * FUNCTION: RsDoDmaDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "DMA" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDmaDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + UINT8 DmaChannelMask = 0; + UINT8 DmaChannels = 0; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA)); + + Descriptor = Rnode->Buffer; + Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA | + ASL_RDESC_DMA_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* DMA type */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_DMATYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5, 2); + break; + + case 1: /* Bus Master */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2); + break; + + case 2: /* Xfer Type (transfer width) */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_XFERTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0, 2); + break; + + case 3: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* All DMA channel bytes are handled here, after flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 8 channels can be specified in the list */ + + DmaChannels++; + if (DmaChannels > 8) + { + AslError (ASL_ERROR, ASL_MSG_DMA_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only DMA channels 0-7 are allowed (mask is 8 bits) */ + + if (InitializerOp->Asl.Value.Integer > 7) + { + AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL, + InitializerOp, NULL); + } + + /* Build the mask */ + + DmaChannelMask |= + (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); + } + + if (i == 4) /* case 4: First DMA byte */ + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA, + CurrentByteOffset + + ASL_RESDESC_OFFSET (Dma.DmaChannelMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the channel mask */ + + Descriptor->Dma.DmaChannelMask = DmaChannelMask; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoFixedDmaDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "FixedDMA" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoFixedDmaDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_DMA)); + + Descriptor = Rnode->Buffer; + Descriptor->FixedDma.DescriptorType = + ACPI_RESOURCE_NAME_FIXED_DMA | ASL_RDESC_FIXED_DMA_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* DMA Request Lines [WORD] (_DMA) */ + + Descriptor->FixedDma.RequestLines = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_DMA, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.RequestLines)); + break; + + case 1: /* DMA Channel [WORD] (_TYP) */ + + Descriptor->FixedDma.Channels = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_DMATYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Channels)); + break; + + case 2: /* Transfer Width [BYTE] (_SIZ) */ + + Descriptor->FixedDma.Width = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_XFERTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Width)); + break; + + case 3: /* Descriptor Name (optional) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: /* Ignore any extra nodes */ + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoFixedIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "FixedIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoFixedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *AddressOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO)); + + Descriptor = Rnode->Buffer; + Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO | + ASL_RDESC_FIXED_IO_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Base Address */ + + Descriptor->FixedIo.Address = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_BASEADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address)); + AddressOp = InitializerOp; + break; + + case 1: /* Length */ + + Descriptor->FixedIo.AddressLength = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength)); + break; + + case 2: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Error checks */ + + if (Descriptor->FixedIo.Address > 0x03FF) + { + AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *AlignOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO)); + + Descriptor = Rnode->Buffer; + Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO | + ASL_RDESC_IO_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Decode size */ + + RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0); + break; + + case 1: /* Min Address */ + + Descriptor->Io.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum)); + MinOp = InitializerOp; + break; + + case 2: /* Max Address */ + + Descriptor->Io.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum)); + MaxOp = InitializerOp; + break; + + case 3: /* Alignment */ + + Descriptor->Io.Alignment = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment)); + AlignOp = InitializerOp; + break; + + case 4: /* Length */ + + Descriptor->Io.AddressLength = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength)); + LengthOp = InitializerOp; + break; + + case 5: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Align values */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO, + Descriptor->Io.Minimum, + Descriptor->Io.Maximum, + Descriptor->Io.AddressLength, + Descriptor->Io.Alignment, + MinOp, MaxOp, LengthOp, AlignOp, Op); + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIrqDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IRQ" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIrqDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 Interrupts = 0; + UINT16 IrqMask = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ)); + + /* Length = 3 (with flag byte) */ + + Descriptor = Rnode->Buffer; + Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | + (ASL_RDESC_IRQ_SIZE + 0x01); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Interrupt Type (or Mode - edge/level) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0); + break; + + case 1: /* Interrupt Level (or Polarity - Active high/low) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3); + break; + + case 2: /* Share Type - Default: exclusive (0) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4); + break; + + case 3: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* All IRQ bytes are handled here, after the flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 16 interrupts can be specified in the list */ + + Interrupts++; + if (Interrupts > 16) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only interrupts 0-15 are allowed (mask is 16 bits) */ + + if (InitializerOp->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, + InitializerOp, NULL); + } + else + { + IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer); + } + } + + /* Case 4: First IRQ value in list */ + + if (i == 4) + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the channel mask */ + + Descriptor->Irq.IrqMask = IrqMask; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIrqNoFlagsDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IRQNoFlags" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIrqNoFlagsDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT16 IrqMask = 0; + UINT32 Interrupts = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS)); + + Descriptor = Rnode->Buffer; + Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | + ASL_RDESC_IRQ_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* IRQ bytes are handled here, after the flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 16 interrupts can be specified in the list */ + + Interrupts++; + if (Interrupts > 16) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only interrupts 0-15 are allowed (mask is 16 bits) */ + + if (InitializerOp->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, + InitializerOp, NULL); + } + else + { + IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); + } + } + + /* Case 1: First IRQ value in list */ + + if (i == 1) + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the interrupt mask */ + + Descriptor->Irq.IrqMask = IrqMask; + return (Rnode); +} diff --git a/source/compiler/aslrestype2.c b/source/compiler/aslrestype2.c new file mode 100644 index 000000000000..9c157937568b --- /dev/null +++ b/source/compiler/aslrestype2.c @@ -0,0 +1,461 @@ +/****************************************************************************** + * + * Module Name: aslrestype2 - Miscellaneous Large resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2") + +/* + * This module contains miscellaneous large resource descriptors: + * + * Register + * Interrupt + * VendorLong + */ + +/******************************************************************************* + * + * FUNCTION: RsDoGeneralRegisterDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "Register" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoGeneralRegisterDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER)); + + Descriptor = Rnode->Buffer; + Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER; + Descriptor->GenericReg.ResourceLength = 12; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Address space */ + + Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId)); + break; + + case 1: /* Register Bit Width */ + + Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth)); + break; + + case 2: /* Register Bit Offset */ + + Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset)); + break; + + case 3: /* Register Address */ + + Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_ADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address)); + break; + + case 4: /* Access Size (ACPI 3.0) */ + + Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize)); + + if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE, + InitializerOp, NULL); + } + break; + + case 5: /* ResourceTag (ACPI 3.0b) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoInterruptDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "Interrupt" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoInterruptDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + AML_RESOURCE *Rover = NULL; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN HasResSourceIndex = FALSE; + UINT8 ResSourceIndex = 0; + UINT8 *ResSourceString = NULL; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + /* Count the interrupt numbers */ + + for (i = 0; InitializerOp; i++) + { + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + + if (i <= 6) + { + if (i == 3 && + InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* + * ResourceSourceIndex was specified, always make room for + * it, even if the ResourceSource was omitted. + */ + OptionIndex++; + } + + continue; + } + + OptionIndex += 4; + } + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_EXTENDED_IRQ) + + 1 + OptionIndex + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtendedIrq.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_IRQ; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + Descriptor->ExtendedIrq.ResourceLength = 2; /* Flags and table length byte */ + Descriptor->ExtendedIrq.InterruptCount = 0; + + Rover = ACPI_CAST_PTR (AML_RESOURCE, + (&(Descriptor->ExtendedIrq.Interrupts[0]))); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage (Default: consumer (1) */ + + RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 0, 1); + break; + + case 1: /* Interrupt Type (or Mode - edge/level) */ + + RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 1); + break; + + case 2: /* Interrupt Level (or Polarity - Active high/low) */ + + RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 2); + break; + + case 3: /* Share Type - Default: exclusive (0) */ + + RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 3); + break; + + case 4: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + HasResSourceIndex = TRUE; + ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 5: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + ResSourceString = (UINT8 *) InitializerOp->Asl.Value.String; + } + + /* ResourceSourceIndex must also be valid */ + + if (!HasResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (HasResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 6: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + /* + * Interrupt Numbers come through here, repeatedly + */ + + /* Maximum 255 interrupts allowed for this descriptor */ + + if (Descriptor->ExtendedIrq.InterruptCount == 255) + { + AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Each interrupt number must be a 32-bit value */ + + if (InitializerOp->Asl.Value.Integer > ACPI_UINT32_MAX) + { + AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_NUMBER, + InitializerOp, NULL); + } + + /* Save the integer and move pointer to the next one */ + + Rover->DwordItem = (UINT32) InitializerOp->Asl.Value.Integer; + Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->DwordItem), 4); + Descriptor->ExtendedIrq.InterruptCount++; + Descriptor->ExtendedIrq.ResourceLength += 4; + + /* Case 7: First interrupt number in list */ + + if (i == 7) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* Must be at least one interrupt */ + + AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN, + InitializerOp, NULL); + } + + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateDwordField (InitializerOp, ACPI_RESTAG_INTERRUPT, + CurrentByteOffset + + ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0])); + } + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + + /* Add optional ResSourceIndex if present */ + + if (HasResSourceIndex) + { + Rover->ByteItem = ResSourceIndex; + Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->ByteItem), 1); + Descriptor->ExtendedIrq.ResourceLength += 1; + } + + /* Add optional ResSource string if present */ + + if (StringLength && ResSourceString) + { + + strcpy ((char *) Rover, (char *) ResSourceString); + Rover = ACPI_ADD_PTR ( + AML_RESOURCE, &(Rover->ByteItem), StringLength); + + Descriptor->ExtendedIrq.ResourceLength = (UINT16) + (Descriptor->ExtendedIrq.ResourceLength + StringLength); + } + + Rnode->BufferLength = (ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]) - + ASL_RESDESC_OFFSET (ExtendedIrq.DescriptorType)) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoVendorLargeDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "VendorLong" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoVendorLargeDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT8 *VendorData; + UINT32 i; + + + /* Count the number of data bytes */ + + InitializerOp = Op->Asl.Child; + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + + for (i = 0; InitializerOp; i++) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + break; + } + InitializerOp = InitializerOp->Asl.Next; + } + + InitializerOp = Op->Asl.Child; + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_LARGE) + i); + + Descriptor = Rnode->Buffer; + Descriptor->VendorLarge.DescriptorType = ACPI_RESOURCE_NAME_VENDOR_LARGE; + Descriptor->VendorLarge.ResourceLength = (UINT16) i; + + /* Point to end-of-descriptor for vendor data */ + + VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_LARGE_HEADER); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + break; + } + + VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer; + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} diff --git a/source/compiler/aslrestype2d.c b/source/compiler/aslrestype2d.c new file mode 100644 index 000000000000..8887e39028cf --- /dev/null +++ b/source/compiler/aslrestype2d.c @@ -0,0 +1,742 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2d - Large DWord address resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2d") + +/* + * This module contains the Dword (32-bit) address space descriptors: + * + * DwordIO + * DwordMemory + * DwordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoDwordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT8 *OptionalFields; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 3); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0, 2); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Found a valid ResourceSourceIndex */ + + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + /* Found a valid ResourceSource */ + + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address32.Minimum, + (UINT64) Descriptor->Address32.Maximum, + (UINT64) Descriptor->Address32.AddressLength, + (UINT64) Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoDwordMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 1, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 1, 2); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 14: /* Address Range */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 3, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 3, 2); + break; + + case 15: /* Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address32.Minimum, + (UINT64) Descriptor->Address32.Maximum, + (UINT64) Descriptor->Address32.AddressLength, + (UINT64) Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoDwordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address32.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address32.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, + InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address32.Minimum, + (UINT64) Descriptor->Address32.Maximum, + (UINT64) Descriptor->Address32.AddressLength, + (UINT64) Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/source/compiler/aslrestype2e.c b/source/compiler/aslrestype2e.c new file mode 100644 index 000000000000..5da52914e0c2 --- /dev/null +++ b/source/compiler/aslrestype2e.c @@ -0,0 +1,573 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2e - Large Extended address resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2e") + +/* + * This module contains the Extended (64-bit) address space descriptors: + * + * ExtendedIO + * ExtendedMemory + * ExtendedSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 3); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0, 2); + break; + + case 5: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 11: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 12: /* Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 4); + break; + + case 13: /* Translation Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 1, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 1, 2); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 13: /* Address Range */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 3, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 3, 2); + break; + + case 14: /* Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->ExtAddress64.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->ExtAddress64.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} diff --git a/source/compiler/aslrestype2q.c b/source/compiler/aslrestype2q.c new file mode 100644 index 000000000000..473f259d216a --- /dev/null +++ b/source/compiler/aslrestype2q.c @@ -0,0 +1,721 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2q - Large QWord address resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2q") + +/* + * This module contains the QWord (64-bit) address space descriptors: + * + * QWordIO + * QWordMemory + * QWordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoQwordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 3); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0, 2); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoQwordMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 1, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 1, 2); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 14: /* Address Range */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 3, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 3, 2); + break; + + case 15: /* Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoQwordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address64.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address64.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateQwordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/source/compiler/aslrestype2s.c b/source/compiler/aslrestype2s.c new file mode 100644 index 000000000000..6109aa391709 --- /dev/null +++ b/source/compiler/aslrestype2s.c @@ -0,0 +1,1187 @@ +/****************************************************************************** + * + * Module Name: aslrestype2s - Serial Large resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2s") + + +static UINT16 +RsGetBufferDataLength ( + ACPI_PARSE_OBJECT *InitializerOp); + +static UINT16 +RsGetInterruptDataLength ( + ACPI_PARSE_OBJECT *InitializerOp); + +static BOOLEAN +RsGetVendorData ( + ACPI_PARSE_OBJECT *InitializerOp, + UINT8 *VendorData, + ACPI_SIZE DescriptorOffset); + +/* + * This module contains descriptors for serial buses and GPIO: + * + * GpioInt + * GpioIo + * I2cSerialBus + * SpiSerialBus + * UartSerialBus + */ + + +/******************************************************************************* + * + * FUNCTION: RsGetBufferDataLength + * + * PARAMETERS: InitializerOp - Current parse op, start of the resource + * descriptor + * + * RETURN: Length of the data buffer + * + * DESCRIPTION: Get the length of a RawDataBuffer, used for vendor data. + * + ******************************************************************************/ + +static UINT16 +RsGetBufferDataLength ( + ACPI_PARSE_OBJECT *InitializerOp) +{ + UINT16 ExtraDataSize = 0; + ACPI_PARSE_OBJECT *DataList; + + + /* Find the byte-initializer list */ + + while (InitializerOp) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DATABUFFER) + { + /* First child is the optional length (ignore it here) */ + + DataList = InitializerOp->Asl.Child; + DataList = ASL_GET_PEER_NODE (DataList); + + /* Count the data items (each one is a byte of data) */ + + while (DataList) + { + ExtraDataSize++; + DataList = ASL_GET_PEER_NODE (DataList); + } + + return (ExtraDataSize); + } + + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + } + + return (ExtraDataSize); +} + + +/******************************************************************************* + * + * FUNCTION: RsGetInterruptDataLength + * + * PARAMETERS: InitializerOp - Current parse op, start of the resource + * descriptor + * + * RETURN: Length of the interrupt data list + * + * DESCRIPTION: Get the length of a list of interrupt DWORDs for the GPIO + * descriptors. + * + ******************************************************************************/ + +static UINT16 +RsGetInterruptDataLength ( + ACPI_PARSE_OBJECT *InitializerOp) +{ + UINT16 InterruptLength; + UINT32 i; + + + /* Count the interrupt numbers */ + + InterruptLength = 0; + for (i = 0; InitializerOp; i++) + { + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + + /* Interrupt list starts at offset 10 (Gpio descriptors) */ + + if (i >= 10) + { + InterruptLength += 2; + } + } + + return (InterruptLength); +} + + +/******************************************************************************* + * + * FUNCTION: RsGetVendorData + * + * PARAMETERS: InitializerOp - Current parse op, start of the resource + * descriptor. + * VendorData - Where the vendor data is returned + * DescriptorOffset - Where vendor data begins in descriptor + * + * RETURN: TRUE if valid vendor data was returned, FALSE otherwise. + * + * DESCRIPTION: Extract the vendor data and construct a vendor data buffer. + * + ******************************************************************************/ + +static BOOLEAN +RsGetVendorData ( + ACPI_PARSE_OBJECT *InitializerOp, + UINT8 *VendorData, + ACPI_SIZE DescriptorOffset) +{ + ACPI_PARSE_OBJECT *BufferOp; + UINT32 SpecifiedLength = ACPI_UINT32_MAX; + UINT16 ActualLength = 0; + + + /* Vendor Data field is always optional */ + + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + return (FALSE); + } + + BufferOp = InitializerOp->Asl.Child; + if (!BufferOp) + { + AslError (ASL_ERROR, ASL_MSG_SYNTAX, InitializerOp, ""); + return (FALSE); + } + + /* First child is the optional buffer length (WORD) */ + + if (BufferOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + SpecifiedLength = (UINT16) BufferOp->Asl.Value.Integer; + } + + /* Insert field tag _VEN */ + + RsCreateByteField (InitializerOp, ACPI_RESTAG_VENDORDATA, + (UINT16) DescriptorOffset); + + /* Walk the list of buffer initializers (each is one byte) */ + + BufferOp = RsCompleteNodeAndGetNext (BufferOp); + if (BufferOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + while (BufferOp) + { + *VendorData = (UINT8) BufferOp->Asl.Value.Integer; + VendorData++; + ActualLength++; + BufferOp = RsCompleteNodeAndGetNext (BufferOp); + } + } + + /* Length validation. Buffer cannot be of zero length */ + + if ((SpecifiedLength == 0) || + ((SpecifiedLength == ACPI_UINT32_MAX) && (ActualLength == 0))) + { + AslError (ASL_ERROR, ASL_MSG_BUFFER_LENGTH, InitializerOp, NULL); + return (FALSE); + } + + if (SpecifiedLength != ACPI_UINT32_MAX) + { + /* ActualLength > SpecifiedLength -> error */ + + if (ActualLength > SpecifiedLength) + { + AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG, InitializerOp, NULL); + return (FALSE); + } + + /* ActualLength < SpecifiedLength -> remark */ + + else if (ActualLength < SpecifiedLength) + { + AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT, InitializerOp, NULL); + return (FALSE); + } + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoGpioIntDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "GpioInt" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoGpioIntDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + char *ResourceSource = NULL; + UINT8 *VendorData = NULL; + UINT16 *InterruptList = NULL; + UINT16 ResSourceLength; + UINT16 VendorLength; + UINT16 InterruptLength; + UINT16 DescriptorSize; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* + * Calculate lengths for fields that have variable length: + * 1) Resource Source string + * 2) Vendor Data buffer + * 3) PIN (interrupt) list + */ + ResSourceLength = RsGetStringDataLength (InitializerOp); + VendorLength = RsGetBufferDataLength (InitializerOp); + InterruptLength = RsGetInterruptDataLength (InitializerOp); + + DescriptorSize = ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO) + + ResSourceLength + VendorLength + InterruptLength; + + /* Allocate the local resource node and initialize */ + + Rnode = RsAllocateResourceNode (DescriptorSize + sizeof (AML_RESOURCE_LARGE_HEADER)); + + Descriptor = Rnode->Buffer; + Descriptor->Gpio.ResourceLength = DescriptorSize; + Descriptor->Gpio.DescriptorType = ACPI_RESOURCE_NAME_GPIO; + Descriptor->Gpio.RevisionId = AML_RESOURCE_GPIO_REVISION; + Descriptor->Gpio.ConnectionType = AML_RESOURCE_GPIO_TYPE_INT; + + /* Build pointers to optional areas */ + + InterruptList = ACPI_ADD_PTR (UINT16, Descriptor, sizeof (AML_RESOURCE_GPIO)); + ResourceSource = ACPI_ADD_PTR (char, InterruptList, InterruptLength); + VendorData = ACPI_ADD_PTR (UINT8, ResourceSource, ResSourceLength); + + /* Setup offsets within the descriptor */ + + Descriptor->Gpio.PinTableOffset = (UINT16) + ACPI_PTR_DIFF (InterruptList, Descriptor); + + Descriptor->Gpio.ResSourceOffset = (UINT16) + ACPI_PTR_DIFF (ResourceSource, Descriptor); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%16s - Actual: %.2X, Base: %.2X, ResLen: %.2X, VendLen: %.2X, IntLen: %.2X\n", + "GpioInt", Descriptor->Gpio.ResourceLength, (UINT16) sizeof (AML_RESOURCE_GPIO), + ResSourceLength, VendorLength, InterruptLength); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Interrupt Mode - edge/level [Flag] (_MOD) */ + + RsSetFlagBits16 (&Descriptor->Gpio.IntFlags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.IntFlags), 0); + break; + + case 1: /* Interrupt Polarity - Active high/low [Flags] (_POL) */ + + RsSetFlagBits16 (&Descriptor->Gpio.IntFlags, InitializerOp, 1, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_POLARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.IntFlags), 1, 2); + break; + + case 2: /* Share Type - Default: exclusive (0) [Flags] (_SHR) */ + + RsSetFlagBits16 (&Descriptor->Gpio.IntFlags, InitializerOp, 3, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.IntFlags), 3, 2); + break; + + case 3: /* Pin Config [BYTE] (_PPI) */ + + Descriptor->Gpio.PinConfig = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_PINCONFIG, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.PinConfig)); + break; + + case 4: /* Debounce Timeout [WORD] (_DBT) */ + + Descriptor->Gpio.DebounceTimeout = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_DEBOUNCETIME, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.DebounceTimeout)); + break; + + case 5: /* ResSource [Optional Field - STRING] */ + + if (ResSourceLength) + { + /* Copy string to the descriptor */ + + strcpy (ResourceSource, + InitializerOp->Asl.Value.String); + } + break; + + case 6: /* Resource Index */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Descriptor->Gpio.ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 7: /* Resource Usage (consumer/producer) */ + + RsSetFlagBits16 (&Descriptor->Gpio.Flags, InitializerOp, 0, 1); + break; + + case 8: /* Resource Tag (Descriptor Name) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 9: /* Vendor Data (Optional - Buffer of BYTEs) (_VEN) */ + + /* + * Always set the VendorOffset even if there is no Vendor Data. + * This field is required in order to calculate the length + * of the ResourceSource at runtime. + */ + Descriptor->Gpio.VendorOffset = (UINT16) + ACPI_PTR_DIFF (VendorData, Descriptor); + + if (RsGetVendorData (InitializerOp, VendorData, + (CurrentByteOffset + Descriptor->Gpio.VendorOffset))) + { + Descriptor->Gpio.VendorLength = VendorLength; + } + break; + + default: + /* + * PINs come through here, repeatedly. Each PIN must be a DWORD. + * NOTE: there is no "length" field for this, so from ACPI spec: + * The number of pins in the table can be calculated from: + * PinCount = (Resource Source Name Offset - Pin Table Offset) / 2 + * (implies resource source must immediately follow the pin list.) + * Name: _PIN + */ + *InterruptList = (UINT16) InitializerOp->Asl.Value.Integer; + InterruptList++; + + /* Case 10: First interrupt number in list */ + + if (i == 10) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* Must be at least one interrupt */ + + AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN, + InitializerOp, NULL); + } + + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateDwordField (InitializerOp, ACPI_RESTAG_PIN, + CurrentByteOffset + Descriptor->Gpio.PinTableOffset); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoGpioIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "GpioIo" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoGpioIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + char *ResourceSource = NULL; + UINT8 *VendorData = NULL; + UINT16 *InterruptList = NULL; + UINT16 ResSourceLength; + UINT16 VendorLength; + UINT16 InterruptLength; + UINT16 DescriptorSize; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* + * Calculate lengths for fields that have variable length: + * 1) Resource Source string + * 2) Vendor Data buffer + * 3) PIN (interrupt) list + */ + ResSourceLength = RsGetStringDataLength (InitializerOp); + VendorLength = RsGetBufferDataLength (InitializerOp); + InterruptLength = RsGetInterruptDataLength (InitializerOp); + + DescriptorSize = ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO) + + ResSourceLength + VendorLength + InterruptLength; + + /* Allocate the local resource node and initialize */ + + Rnode = RsAllocateResourceNode (DescriptorSize + sizeof (AML_RESOURCE_LARGE_HEADER)); + + Descriptor = Rnode->Buffer; + Descriptor->Gpio.ResourceLength = DescriptorSize; + Descriptor->Gpio.DescriptorType = ACPI_RESOURCE_NAME_GPIO; + Descriptor->Gpio.RevisionId = AML_RESOURCE_GPIO_REVISION; + Descriptor->Gpio.ConnectionType = AML_RESOURCE_GPIO_TYPE_IO; + + /* Build pointers to optional areas */ + + InterruptList = ACPI_ADD_PTR (UINT16, Descriptor, sizeof (AML_RESOURCE_GPIO)); + ResourceSource = ACPI_ADD_PTR (char, InterruptList, InterruptLength); + VendorData = ACPI_ADD_PTR (UINT8, ResourceSource, ResSourceLength); + + /* Setup offsets within the descriptor */ + + Descriptor->Gpio.PinTableOffset = (UINT16) + ACPI_PTR_DIFF (InterruptList, Descriptor); + + Descriptor->Gpio.ResSourceOffset = (UINT16) + ACPI_PTR_DIFF (ResourceSource, Descriptor); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%16s - Actual: %.2X, Base: %.2X, ResLen: %.2X, VendLen: %.2X, IntLen: %.2X\n", + "GpioIo", Descriptor->Gpio.ResourceLength, (UINT16) sizeof (AML_RESOURCE_GPIO), + ResSourceLength, VendorLength, InterruptLength); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Share Type [Flags] (_SHR) */ + + RsSetFlagBits16 (&Descriptor->Gpio.IntFlags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.IntFlags), 3); + break; + + case 1: /* Pin Config [BYTE] (_PPI) */ + + Descriptor->Gpio.PinConfig = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_PINCONFIG, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.PinConfig)); + break; + + case 2: /* Debounce Timeout [WORD] (_DBT) */ + + Descriptor->Gpio.DebounceTimeout = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_DEBOUNCETIME, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.DebounceTimeout)); + break; + + case 3: /* Drive Strength [WORD] (_DRS) */ + + Descriptor->Gpio.DriveStrength = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_DRIVESTRENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.DriveStrength)); + break; + + case 4: /* I/O Restriction [Flag] (_IOR) */ + + RsSetFlagBits16 (&Descriptor->Gpio.IntFlags, InitializerOp, 0, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_IORESTRICTION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.IntFlags), 0, 2); + break; + + case 5: /* ResSource [Optional Field - STRING] */ + + if (ResSourceLength) + { + /* Copy string to the descriptor */ + + strcpy (ResourceSource, + InitializerOp->Asl.Value.String); + } + break; + + case 6: /* Resource Index */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Descriptor->Gpio.ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 7: /* Resource Usage (consumer/producer) */ + + RsSetFlagBits16 (&Descriptor->Gpio.Flags, InitializerOp, 0, 1); + break; + + case 8: /* Resource Tag (Descriptor Name) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 9: /* Vendor Data (Optional - Buffer of BYTEs) (_VEN) */ + + /* + * Always set the VendorOffset even if there is no Vendor Data. + * This field is required in order to calculate the length + * of the ResourceSource at runtime. + */ + Descriptor->Gpio.VendorOffset = (UINT16) + ACPI_PTR_DIFF (VendorData, Descriptor); + + if (RsGetVendorData (InitializerOp, VendorData, + (CurrentByteOffset + Descriptor->Gpio.VendorOffset))) + { + Descriptor->Gpio.VendorLength = VendorLength; + } + break; + + default: + /* + * PINs come through here, repeatedly. Each PIN must be a DWORD. + * NOTE: there is no "length" field for this, so from ACPI spec: + * The number of pins in the table can be calculated from: + * PinCount = (Resource Source Name Offset - Pin Table Offset) / 2 + * (implies resource source must immediately follow the pin list.) + * Name: _PIN + */ + *InterruptList = (UINT16) InitializerOp->Asl.Value.Integer; + InterruptList++; + + /* Case 10: First interrupt number in list */ + + if (i == 10) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + /* Must be at least one interrupt */ + + AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN, + InitializerOp, NULL); + } + + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateDwordField (InitializerOp, ACPI_RESTAG_PIN, + CurrentByteOffset + Descriptor->Gpio.PinTableOffset); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoI2cSerialBusDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "I2cSerialBus" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoI2cSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + char *ResourceSource = NULL; + UINT8 *VendorData = NULL; + UINT16 ResSourceLength; + UINT16 VendorLength; + UINT16 DescriptorSize; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* + * Calculate lengths for fields that have variable length: + * 1) Resource Source string + * 2) Vendor Data buffer + */ + ResSourceLength = RsGetStringDataLength (InitializerOp); + VendorLength = RsGetBufferDataLength (InitializerOp); + + DescriptorSize = ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS) + + ResSourceLength + VendorLength; + + /* Allocate the local resource node and initialize */ + + Rnode = RsAllocateResourceNode (DescriptorSize + sizeof (AML_RESOURCE_LARGE_HEADER)); + + Descriptor = Rnode->Buffer; + Descriptor->I2cSerialBus.ResourceLength = DescriptorSize; + Descriptor->I2cSerialBus.DescriptorType = ACPI_RESOURCE_NAME_SERIAL_BUS; + Descriptor->I2cSerialBus.RevisionId = AML_RESOURCE_I2C_REVISION; + Descriptor->I2cSerialBus.TypeRevisionId = AML_RESOURCE_I2C_TYPE_REVISION; + Descriptor->I2cSerialBus.Type = AML_RESOURCE_I2C_SERIALBUSTYPE; + Descriptor->I2cSerialBus.TypeDataLength = AML_RESOURCE_I2C_MIN_DATA_LEN + VendorLength; + + /* Build pointers to optional areas */ + + VendorData = ACPI_ADD_PTR (UINT8, Descriptor, sizeof (AML_RESOURCE_I2C_SERIALBUS)); + ResourceSource = ACPI_ADD_PTR (char, VendorData, VendorLength); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%16s - Actual: %.2X, Base: %.2X, ResLen: %.2X, VendLen: %.2X, TypLen: %.2X\n", + "I2cSerialBus", Descriptor->I2cSerialBus.ResourceLength, + (UINT16) sizeof (AML_RESOURCE_I2C_SERIALBUS), ResSourceLength, + VendorLength, Descriptor->I2cSerialBus.TypeDataLength); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Slave Address [WORD] (_ADR) */ + + Descriptor->I2cSerialBus.SlaveAddress = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_ADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.SlaveAddress)); + break; + + case 1: /* Slave Mode [Flag] (_SLV) */ + + RsSetFlagBits (&Descriptor->I2cSerialBus.Flags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_SLAVEMODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.Flags), 0); + break; + + case 2: /* Connection Speed [DWORD] (_SPE) */ + + Descriptor->I2cSerialBus.ConnectionSpeed = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, + CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.ConnectionSpeed)); + break; + + case 3: /* Addressing Mode [Flag] (_MOD) */ + + RsSetFlagBits16 (&Descriptor->I2cSerialBus.TypeSpecificFlags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.TypeSpecificFlags), 0); + break; + + case 4: /* ResSource [Optional Field - STRING] */ + + if (ResSourceLength) + { + /* Copy string to the descriptor */ + + strcpy (ResourceSource, + InitializerOp->Asl.Value.String); + } + break; + + case 5: /* Resource Index */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Descriptor->I2cSerialBus.ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 6: /* Resource Usage (consumer/producer) */ + + RsSetFlagBits (&Descriptor->I2cSerialBus.Flags, InitializerOp, 1, 1); + break; + + case 7: /* Resource Tag (Descriptor Name) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 8: /* Vendor Data (Optional - Buffer of BYTEs) (_VEN) */ + + RsGetVendorData (InitializerOp, VendorData, + CurrentByteOffset + sizeof (AML_RESOURCE_I2C_SERIALBUS)); + break; + + default: /* Ignore any extra nodes */ + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoSpiSerialBusDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "SPI Serial Bus" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoSpiSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + char *ResourceSource = NULL; + UINT8 *VendorData = NULL; + UINT16 ResSourceLength; + UINT16 VendorLength; + UINT16 DescriptorSize; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* + * Calculate lengths for fields that have variable length: + * 1) Resource Source string + * 2) Vendor Data buffer + */ + ResSourceLength = RsGetStringDataLength (InitializerOp); + VendorLength = RsGetBufferDataLength (InitializerOp); + + DescriptorSize = ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS) + + ResSourceLength + VendorLength; + + /* Allocate the local resource node and initialize */ + + Rnode = RsAllocateResourceNode (DescriptorSize + sizeof (AML_RESOURCE_LARGE_HEADER)); + + Descriptor = Rnode->Buffer; + Descriptor->SpiSerialBus.ResourceLength = DescriptorSize; + Descriptor->SpiSerialBus.DescriptorType = ACPI_RESOURCE_NAME_SERIAL_BUS; + Descriptor->SpiSerialBus.RevisionId = AML_RESOURCE_SPI_REVISION; + Descriptor->SpiSerialBus.TypeRevisionId = AML_RESOURCE_SPI_TYPE_REVISION; + Descriptor->SpiSerialBus.Type = AML_RESOURCE_SPI_SERIALBUSTYPE; + Descriptor->SpiSerialBus.TypeDataLength = AML_RESOURCE_SPI_MIN_DATA_LEN + VendorLength; + + /* Build pointers to optional areas */ + + VendorData = ACPI_ADD_PTR (UINT8, Descriptor, sizeof (AML_RESOURCE_SPI_SERIALBUS)); + ResourceSource = ACPI_ADD_PTR (char, VendorData, VendorLength); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%16s - Actual: %.2X, Base: %.2X, ResLen: %.2X, VendLen: %.2X, TypLen: %.2X\n", + "SpiSerialBus", Descriptor->SpiSerialBus.ResourceLength, + (UINT16) sizeof (AML_RESOURCE_SPI_SERIALBUS), ResSourceLength, + VendorLength, Descriptor->SpiSerialBus.TypeDataLength); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Device Selection [WORD] (_ADR) */ + + Descriptor->SpiSerialBus.DeviceSelection = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_ADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.DeviceSelection)); + break; + + case 1: /* Device Polarity [Flag] (_DPL) */ + + RsSetFlagBits16 (&Descriptor->SpiSerialBus.TypeSpecificFlags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DEVICEPOLARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.TypeSpecificFlags), 1); + break; + + case 2: /* Wire Mode [Flag] (_MOD) */ + + RsSetFlagBits16 (&Descriptor->SpiSerialBus.TypeSpecificFlags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.TypeSpecificFlags), 0); + break; + + case 3: /* Device Bit Length [BYTE] (_LEN) */ + + Descriptor->SpiSerialBus.DataBitLength = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.DataBitLength)); + break; + + case 4: /* Slave Mode [Flag] (_SLV) */ + + RsSetFlagBits (&Descriptor->SpiSerialBus.Flags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_SLAVEMODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.Flags), 0); + break; + + case 5: /* Connection Speed [DWORD] (_SPE) */ + + Descriptor->SpiSerialBus.ConnectionSpeed = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.ConnectionSpeed)); + break; + + case 6: /* Clock Polarity [BYTE] (_POL) */ + + Descriptor->SpiSerialBus.ClockPolarity = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_POLARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.ClockPolarity)); + break; + + case 7: /* Clock Phase [BYTE] (_PHA) */ + + Descriptor->SpiSerialBus.ClockPhase = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_PHASE, + CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.ClockPhase)); + break; + + case 8: /* ResSource [Optional Field - STRING] */ + + if (ResSourceLength) + { + /* Copy string to the descriptor */ + + strcpy (ResourceSource, + InitializerOp->Asl.Value.String); + } + break; + + case 9: /* Resource Index */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Descriptor->SpiSerialBus.ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 10: /* Resource Usage (consumer/producer) */ + + RsSetFlagBits (&Descriptor->SpiSerialBus.Flags, InitializerOp, 1, 1); + break; + + case 11: /* Resource Tag (Descriptor Name) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 12: /* Vendor Data (Optional - Buffer of BYTEs) (_VEN) */ + + RsGetVendorData (InitializerOp, VendorData, + CurrentByteOffset + sizeof (AML_RESOURCE_SPI_SERIALBUS)); + break; + + default: /* Ignore any extra nodes */ + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoUartSerialBusDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "UART Serial Bus" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoUartSerialBusDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + char *ResourceSource = NULL; + UINT8 *VendorData = NULL; + UINT16 ResSourceLength; + UINT16 VendorLength; + UINT16 DescriptorSize; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + + /* + * Calculate lengths for fields that have variable length: + * 1) Resource Source string + * 2) Vendor Data buffer + */ + ResSourceLength = RsGetStringDataLength (InitializerOp); + VendorLength = RsGetBufferDataLength (InitializerOp); + + DescriptorSize = ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS) + + ResSourceLength + VendorLength; + + /* Allocate the local resource node and initialize */ + + Rnode = RsAllocateResourceNode (DescriptorSize + sizeof (AML_RESOURCE_LARGE_HEADER)); + + Descriptor = Rnode->Buffer; + Descriptor->UartSerialBus.ResourceLength = DescriptorSize; + Descriptor->UartSerialBus.DescriptorType = ACPI_RESOURCE_NAME_SERIAL_BUS; + Descriptor->UartSerialBus.RevisionId = AML_RESOURCE_UART_REVISION; + Descriptor->UartSerialBus.TypeRevisionId = AML_RESOURCE_UART_TYPE_REVISION; + Descriptor->UartSerialBus.Type = AML_RESOURCE_UART_SERIALBUSTYPE; + Descriptor->UartSerialBus.TypeDataLength = AML_RESOURCE_UART_MIN_DATA_LEN + VendorLength; + + /* Build pointers to optional areas */ + + VendorData = ACPI_ADD_PTR (UINT8, Descriptor, sizeof (AML_RESOURCE_UART_SERIALBUS)); + ResourceSource = ACPI_ADD_PTR (char, VendorData, VendorLength); + + DbgPrint (ASL_DEBUG_OUTPUT, + "%16s - Actual: %.2X, Base: %.2X, ResLen: %.2X, VendLen: %.2X, TypLen: %.2X\n", + "UartSerialBus", Descriptor->UartSerialBus.ResourceLength, + (UINT16) sizeof (AML_RESOURCE_UART_SERIALBUS), ResSourceLength, + VendorLength, Descriptor->UartSerialBus.TypeDataLength); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Connection Speed (Baud Rate) [DWORD] (_SPE) */ + + Descriptor->UartSerialBus.DefaultBaudRate = (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.DefaultBaudRate)); + break; + + case 1: /* Bits Per Byte [Flags] (_LEN) */ + + RsSetFlagBits16 (&Descriptor->UartSerialBus.TypeSpecificFlags, InitializerOp, 4, 3); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.TypeSpecificFlags), 4, 3); + break; + + case 2: /* Stop Bits [Flags] (_STB) */ + + RsSetFlagBits16 (&Descriptor->UartSerialBus.TypeSpecificFlags, InitializerOp, 2, 1); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_STOPBITS, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.TypeSpecificFlags), 2, 2); + break; + + case 3: /* Lines In Use [BYTE] (_LIN) */ + + Descriptor->UartSerialBus.LinesEnabled = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LINE, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.LinesEnabled)); + break; + + case 4: /* Endianness [Flag] (_END) */ + + RsSetFlagBits16 (&Descriptor->UartSerialBus.TypeSpecificFlags, InitializerOp, 7, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_ENDIANNESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.TypeSpecificFlags), 7); + break; + + case 5: /* Parity [BYTE] (_PAR) */ + + Descriptor->UartSerialBus.Parity = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_PARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.Parity)); + break; + + case 6: /* Flow Control [Flags] (_FLC) */ + + RsSetFlagBits16 (&Descriptor->UartSerialBus.TypeSpecificFlags, InitializerOp, 0, 0); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_FLOWCONTROL, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.TypeSpecificFlags), 0, 2); + break; + + case 7: /* Rx Buffer Size [WORD] (_RXL) */ + + Descriptor->UartSerialBus.RxFifoSize = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH_RX, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.RxFifoSize)); + break; + + case 8: /* Tx Buffer Size [WORD] (_TXL) */ + + Descriptor->UartSerialBus.TxFifoSize = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH_TX, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.TxFifoSize)); + break; + + case 9: /* ResSource [Optional Field - STRING] */ + + if (ResSourceLength) + { + /* Copy string to the descriptor */ + + strcpy (ResourceSource, + InitializerOp->Asl.Value.String); + } + break; + + case 10: /* Resource Index */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + Descriptor->UartSerialBus.ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; + } + break; + + case 11: /* Resource Usage (consumer/producer) */ + + RsSetFlagBits (&Descriptor->UartSerialBus.Flags, InitializerOp, 1, 1); + + /* + * Slave Mode [Flag] (_SLV) + * + * Note: There is no SlaveMode argument to the UartSerialBus macro, but + * we add this name anyway to allow the flag to be set by ASL in the + * rare case where there is a slave mode associated with the UART. + */ + RsCreateBitField (InitializerOp, ACPI_RESTAG_SLAVEMODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.Flags), 0); + break; + + case 12: /* Resource Tag (Descriptor Name) */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Vendor Data (Optional - Buffer of BYTEs) (_VEN) */ + + RsGetVendorData (InitializerOp, VendorData, + CurrentByteOffset + sizeof (AML_RESOURCE_UART_SERIALBUS)); + break; + + default: /* Ignore any extra nodes */ + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + return (Rnode); +} diff --git a/source/compiler/aslrestype2w.c b/source/compiler/aslrestype2w.c new file mode 100644 index 000000000000..154de2f07fb4 --- /dev/null +++ b/source/compiler/aslrestype2w.c @@ -0,0 +1,702 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2w - Large Word address resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2w") + +/* + * This module contains the Word (16-bit) address space descriptors: + * + * WordIO + * WordMemory + * WordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoWordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 0, 3); + RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 0, 2); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address16.Granularity = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address16.Minimum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address16.Maximum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address16.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address16.Minimum, + (UINT64) Descriptor->Address16.Maximum, + (UINT64) Descriptor->Address16.AddressLength, + (UINT64) Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoWordBusNumberDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordBusNumber" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordBusNumberDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 4: /* Address Granularity */ + + Descriptor->Address16.Granularity = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 5: /* Min Address */ + + Descriptor->Address16.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 6: /* Max Address */ + + Descriptor->Address16.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 7: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 8: /* Address Length */ + + Descriptor->Address16.AddressLength = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 9: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 10: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 11: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address16.Minimum, + (UINT64) Descriptor->Address16.Maximum, + (UINT64) Descriptor->Address16.AddressLength, + (UINT64) Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoWordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address16.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address16.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address16.Granularity = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address16.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address16.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address16.AddressLength = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateWordField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + (UINT64) Descriptor->Address16.Minimum, + (UINT64) Descriptor->Address16.Maximum, + (UINT64) Descriptor->Address16.AddressLength, + (UINT64) Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp, Op); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/source/compiler/aslstartup.c b/source/compiler/aslstartup.c new file mode 100644 index 000000000000..cbaf06281379 --- /dev/null +++ b/source/compiler/aslstartup.c @@ -0,0 +1,513 @@ + +/****************************************************************************** + * + * Module Name: aslstartup - Compiler startup routines, called from main + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "actables.h" +#include "acapps.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslstartup") + + +#define ASL_MAX_FILES 256 +static char *FileList[ASL_MAX_FILES]; +static BOOLEAN AslToFile = TRUE; + + +/* Local prototypes */ + +static char ** +AsDoWildcard ( + char *DirectoryPathname, + char *FileSpecifier); + +static UINT8 +AslDetectSourceFileType ( + ASL_FILE_INFO *Info); + + +/******************************************************************************* + * + * FUNCTION: AslInitializeGlobals + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Re-initialize globals needed to restart the compiler. This + * allows multiple files to be disassembled and/or compiled. + * + ******************************************************************************/ + +void +AslInitializeGlobals ( + void) +{ + UINT32 i; + + + /* Init compiler globals */ + + Gbl_CurrentColumn = 0; + Gbl_CurrentLineNumber = 1; + Gbl_LogicalLineNumber = 1; + Gbl_CurrentLineOffset = 0; + Gbl_InputFieldCount = 0; + Gbl_LineBufPtr = Gbl_CurrentLineBuffer; + + Gbl_ErrorLog = NULL; + Gbl_NextError = NULL; + Gbl_Signature = NULL; + Gbl_FileType = 0; + + AslGbl_NextEvent = 0; + for (i = 0; i < ASL_NUM_REPORT_LEVELS; i++) + { + Gbl_ExceptionCount[i] = 0; + } + + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL; + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle = NULL; + + Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename = NULL; + Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL; +} + + +/****************************************************************************** + * + * FUNCTION: AsDoWildcard + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Process files via wildcards. This function is for the Windows + * case only. + * + ******************************************************************************/ + +static char ** +AsDoWildcard ( + char *DirectoryPathname, + char *FileSpecifier) +{ +#ifdef WIN32 + void *DirInfo; + char *Filename; + int FileCount; + + + FileCount = 0; + + /* Open parent directory */ + + DirInfo = AcpiOsOpenDirectory (DirectoryPathname, FileSpecifier, REQUEST_FILE_ONLY); + if (!DirInfo) + { + /* Either the directory of file does not exist */ + + Gbl_Files[ASL_FILE_INPUT].Filename = FileSpecifier; + FlFileError (ASL_FILE_INPUT, ASL_MSG_OPEN); + AslAbort (); + } + + /* Process each file that matches the wildcard specification */ + + while ((Filename = AcpiOsGetNextFilename (DirInfo))) + { + /* Add the filename to the file list */ + + FileList[FileCount] = AcpiOsAllocate (strlen (Filename) + 1); + strcpy (FileList[FileCount], Filename); + FileCount++; + + if (FileCount >= ASL_MAX_FILES) + { + printf ("Max files reached\n"); + FileList[0] = NULL; + return (FileList); + } + } + + /* Cleanup */ + + AcpiOsCloseDirectory (DirInfo); + FileList[FileCount] = NULL; + return (FileList); + +#else + /* + * Linux/Unix cases - Wildcards are expanded by the shell automatically. + * Just return the filename in a null terminated list + */ + FileList[0] = AcpiOsAllocate (strlen (FileSpecifier) + 1); + strcpy (FileList[0], FileSpecifier); + FileList[1] = NULL; + + return (FileList); +#endif +} + + +/******************************************************************************* + * + * FUNCTION: AslDetectSourceFileType + * + * PARAMETERS: Info - Name/Handle for the file (must be open) + * + * RETURN: File Type + * + * DESCRIPTION: Determine the type of the input file. Either binary (contains + * non-ASCII characters), ASL file, or an ACPI Data Table file. + * + ******************************************************************************/ + +static UINT8 +AslDetectSourceFileType ( + ASL_FILE_INFO *Info) +{ + char *FileChar; + UINT8 Type; + ACPI_STATUS Status; + + + /* Check for 100% ASCII source file (comments are ignored) */ + + Status = FlCheckForAscii (Info); + if (ACPI_FAILURE (Status)) + { + printf ("Non-ascii input file - %s\n", Info->Filename); + Type = ASL_INPUT_TYPE_BINARY; + goto Cleanup; + } + + /* + * File is ASCII. Determine if this is an ASL file or an ACPI data + * table file. + */ + while (fgets (Gbl_CurrentLineBuffer, ASL_LINE_BUFFER_SIZE, Info->Handle)) + { + /* Uppercase the buffer for caseless compare */ + + FileChar = Gbl_CurrentLineBuffer; + while (*FileChar) + { + *FileChar = (char) toupper ((int) *FileChar); + FileChar++; + } + + /* Presence of "DefinitionBlock" indicates actual ASL code */ + + if (strstr (Gbl_CurrentLineBuffer, "DEFINITIONBLOCK")) + { + /* Appears to be an ASL file */ + + Type = ASL_INPUT_TYPE_ASCII_ASL; + goto Cleanup; + } + } + + /* Not an ASL source file, default to a data table source file */ + + Type = ASL_INPUT_TYPE_ASCII_DATA; + +Cleanup: + + /* Must seek back to the start of the file */ + + fseek (Info->Handle, 0, SEEK_SET); + return (Type); +} + + +/******************************************************************************* + * + * FUNCTION: AslDoOneFile + * + * PARAMETERS: Filename - Name of the file + * + * RETURN: Status + * + * DESCRIPTION: Process a single file - either disassemble, compile, or both + * + ******************************************************************************/ + +ACPI_STATUS +AslDoOneFile ( + char *Filename) +{ + ACPI_STATUS Status; + + + Gbl_Files[ASL_FILE_INPUT].Filename = Filename; + + /* Re-initialize "some" compiler globals */ + + AslInitializeGlobals (); + + /* + * AML Disassembly (Optional) + */ + if (Gbl_DisasmFlag || Gbl_GetAllTables) + { + /* ACPICA subsystem initialization */ + + Status = AdInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiAllocateRootTable (4); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n", + AcpiFormatException (Status)); + return (Status); + } + + /* This is where the disassembly happens */ + + AcpiGbl_DbOpt_disasm = TRUE; + Status = AdAmlDisassemble (AslToFile, + Gbl_Files[ASL_FILE_INPUT].Filename, + Gbl_OutputFilenamePrefix, + &Gbl_Files[ASL_FILE_INPUT].Filename, + Gbl_GetAllTables); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Shutdown compiler and ACPICA subsystem */ + + AeClearErrorLog (); + (void) AcpiTerminate (); + + /* + * Gbl_Files[ASL_FILE_INPUT].Filename was replaced with the + * .DSL disassembly file, which can now be compiled if requested + */ + if (Gbl_DoCompile) + { + AcpiOsPrintf ("\nCompiling \"%s\"\n", + Gbl_Files[ASL_FILE_INPUT].Filename); + } + else + { + Gbl_Files[ASL_FILE_INPUT].Filename = NULL; + return (AE_OK); + } + } + + /* + * Open the input file. Here, this should be an ASCII source file, + * either an ASL file or a Data Table file + */ + Status = FlOpenInputFile (Gbl_Files[ASL_FILE_INPUT].Filename); + if (ACPI_FAILURE (Status)) + { + AePrintErrorLog (ASL_FILE_STDERR); + return (AE_ERROR); + } + + /* Determine input file type */ + + Gbl_FileType = AslDetectSourceFileType (&Gbl_Files[ASL_FILE_INPUT]); + if (Gbl_FileType == ASL_INPUT_TYPE_BINARY) + { + return (AE_ERROR); + } + + /* + * If -p not specified, we will use the input filename as the + * output filename prefix + */ + if (Gbl_UseDefaultAmlFilename) + { + Gbl_OutputFilenamePrefix = Gbl_Files[ASL_FILE_INPUT].Filename; + } + + /* Open the optional output files (listings, etc.) */ + + Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); + if (ACPI_FAILURE (Status)) + { + AePrintErrorLog (ASL_FILE_STDERR); + return (AE_ERROR); + } + + /* + * Compilation of ASL source versus DataTable source uses different + * compiler subsystems + */ + switch (Gbl_FileType) + { + /* + * Data Table Compilation + */ + case ASL_INPUT_TYPE_ASCII_DATA: + + Status = DtDoCompile (); + + if (Gbl_Signature) + { + ACPI_FREE (Gbl_Signature); + Gbl_Signature = NULL; + } + AeClearErrorLog (); + return (Status); + + /* + * ASL Compilation (Optional) + */ + case ASL_INPUT_TYPE_ASCII_ASL: + + /* ACPICA subsystem initialization */ + + Status = AdInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = CmDoCompile (); + (void) AcpiTerminate (); + + /* + * Return non-zero exit code if there have been errors, unless the + * global ignore error flag has been set + */ + if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors)) + { + return (AE_ERROR); + } + + AeClearErrorLog (); + return (AE_OK); + + case ASL_INPUT_TYPE_BINARY: + + AePrintErrorLog (ASL_FILE_STDERR); + return (AE_ERROR); + + default: + printf ("Unknown file type %X\n", Gbl_FileType); + return (AE_ERROR); + } +} + + +/******************************************************************************* + * + * FUNCTION: AslDoOnePathname + * + * PARAMETERS: Pathname - Full pathname, possibly with wildcards + * + * RETURN: Status + * + * DESCRIPTION: Process one pathname, possible terminated with a wildcard + * specification. If a wildcard, it is expanded and the multiple + * files are processed. + * + ******************************************************************************/ + +ACPI_STATUS +AslDoOnePathname ( + char *Pathname, + ASL_PATHNAME_CALLBACK PathCallback) +{ + ACPI_STATUS Status = AE_OK; + char **WildcardList; + char *Filename; + char *FullPathname; + + + /* Split incoming path into a directory/filename combo */ + + Status = FlSplitInputPathname (Pathname, &Gbl_DirectoryPath, &Filename); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Expand possible wildcard into a file list (Windows/DOS only) */ + + WildcardList = AsDoWildcard (Gbl_DirectoryPath, Filename); + while (*WildcardList) + { + FullPathname = ACPI_ALLOCATE ( + strlen (Gbl_DirectoryPath) + strlen (*WildcardList) + 1); + + /* Construct a full path to the file */ + + strcpy (FullPathname, Gbl_DirectoryPath); + strcat (FullPathname, *WildcardList); + + /* + * If -p not specified, we will use the input filename as the + * output filename prefix + */ + if (Gbl_UseDefaultAmlFilename) + { + Gbl_OutputFilenamePrefix = FullPathname; + } + + /* Save status from all compiles */ + + Status |= (*PathCallback) (FullPathname); + + ACPI_FREE (FullPathname); + ACPI_FREE (*WildcardList); + *WildcardList = NULL; + WildcardList++; + } + + ACPI_FREE (Gbl_DirectoryPath); + ACPI_FREE (Filename); + return (Status); +} + diff --git a/source/compiler/aslstubs.c b/source/compiler/aslstubs.c new file mode 100644 index 000000000000..cf6e410699b4 --- /dev/null +++ b/source/compiler/aslstubs.c @@ -0,0 +1,253 @@ + +/****************************************************************************** + * + * Module Name: aslstubs - Stubs used to link to Aml interpreter + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "acdispat.h" +#include "actables.h" +#include "acevents.h" +#include "acinterp.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslstubs") + + +/* + * Stubs to simplify linkage to the ACPI CA core subsystem. + * Things like Events, Global Lock, etc. are not used + * by the compiler, so they are stubbed out here. + */ +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void) +{ + return 0; +} + +void +AcpiNsExecModuleCodeList ( + void) +{ +} + +ACPI_STATUS +AcpiHwReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiHwWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState) +{ + return (Status); +} + +ACPI_STATUS +AcpiDsMethodDataGetValue ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **DestDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsMethodDataGetNode ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **Node) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsStoreObjectToLocal ( + UINT8 Type, + UINT32 Index, + ACPI_OPERAND_OBJECT *SrcDesc, + ACPI_WALK_STATE *WalkState) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvQueueNotifyRequest ( + ACPI_NAMESPACE_NODE *Node, + UINT32 NotifyValue) +{ + return (AE_OK); +} + +BOOLEAN +AcpiEvIsNotifyObject ( + ACPI_NAMESPACE_NODE *Node) +{ + return (FALSE); +} + +#if (!ACPI_REDUCED_HARDWARE) +ACPI_STATUS +AcpiEvDeleteGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvAcquireGlobalLock ( + UINT16 Timeout) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvReleaseGlobalLock ( + void) +{ + return (AE_OK); +} +#endif /* !ACPI_REDUCED_HARDWARE */ + +ACPI_STATUS +AcpiEvInitializeRegion ( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsLocked) +{ + return (AE_OK); +} + +void +AcpiExDoDebugObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + UINT32 Level, + UINT32 Index) +{ + return; +} + +ACPI_STATUS +AcpiExReadDataFromField ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **RetBufferDesc) +{ + return (AE_SUPPORT); +} + +ACPI_STATUS +AcpiExWriteDataToField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc) +{ + return (AE_SUPPORT); +} + +ACPI_STATUS +AcpiExLoadTableOp ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **ReturnDesc) +{ + return (AE_SUPPORT); +} + +ACPI_STATUS +AcpiExUnloadTable ( + ACPI_OPERAND_OBJECT *DdbHandle) +{ + return (AE_SUPPORT); +} + +ACPI_STATUS +AcpiExLoadOp ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *Target, + ACPI_WALK_STATE *WalkState) +{ + return (AE_SUPPORT); +} + +ACPI_STATUS +AcpiTbFindTable ( + char *Signature, + char *OemId, + char *OemTableId, + UINT32 *TableIndex) +{ + return (AE_SUPPORT); +} + +/* OSL interfaces */ + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (0xFFFF); +} + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + return (AE_SUPPORT); +} diff --git a/source/compiler/asltransform.c b/source/compiler/asltransform.c new file mode 100644 index 000000000000..4a5900f37cd0 --- /dev/null +++ b/source/compiler/asltransform.c @@ -0,0 +1,782 @@ + +/****************************************************************************** + * + * Module Name: asltransform - Parse tree transforms + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asltransform") + +/* Local prototypes */ + +static void +TrTransformSubtree ( + ACPI_PARSE_OBJECT *Op); + +static char * +TrAmlGetNextTempName ( + ACPI_PARSE_OBJECT *Op, + UINT8 *TempCount); + +static void +TrAmlInitLineNumbers ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *Neighbor); + +static void +TrAmlInitNode ( + ACPI_PARSE_OBJECT *Op, + UINT16 ParseOpcode); + +static void +TrAmlSetSubtreeParent ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *Parent); + +static void +TrAmlInsertPeer ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *NewPeer); + +static void +TrDoDefinitionBlock ( + ACPI_PARSE_OBJECT *Op); + +static void +TrDoSwitch ( + ACPI_PARSE_OBJECT *StartNode); + + +/******************************************************************************* + * + * FUNCTION: TrAmlGetNextTempName + * + * PARAMETERS: Op - Current parse op + * TempCount - Current temporary counter. Was originally + * per-module; Currently per method, could be + * expanded to per-scope. + * + * RETURN: A pointer to name (allocated here). + * + * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are + * reserved for use by the ASL compiler. (_T_0 through _T_Z) + * + ******************************************************************************/ + +static char * +TrAmlGetNextTempName ( + ACPI_PARSE_OBJECT *Op, + UINT8 *TempCount) +{ + char *TempName; + + + if (*TempCount >= (10+26)) /* 0-35 valid: 0-9 and A-Z for TempName[3] */ + { + /* Too many temps */ + + AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL); + return (NULL); + } + + TempName = UtLocalCalloc (5); + + if (*TempCount < 10) /* 0-9 */ + { + TempName[3] = (char) (*TempCount + '0'); + } + else /* 10-35: A-Z */ + { + TempName[3] = (char) (*TempCount + ('A' - 10)); + } + (*TempCount)++; + + /* First three characters are always "_T_" */ + + TempName[0] = '_'; + TempName[1] = 'T'; + TempName[2] = '_'; + + return (TempName); +} + + +/******************************************************************************* + * + * FUNCTION: TrAmlInitLineNumbers + * + * PARAMETERS: Op - Op to be initialized + * Neighbor - Op used for initialization values + * + * RETURN: None + * + * DESCRIPTION: Initialized the various line numbers for a parse node. + * + ******************************************************************************/ + +static void +TrAmlInitLineNumbers ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *Neighbor) +{ + + Op->Asl.EndLine = Neighbor->Asl.EndLine; + Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; + Op->Asl.LineNumber = Neighbor->Asl.LineNumber; + Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; + Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; +} + + +/******************************************************************************* + * + * FUNCTION: TrAmlInitNode + * + * PARAMETERS: Op - Op to be initialized + * ParseOpcode - Opcode for this node + * + * RETURN: None + * + * DESCRIPTION: Initialize a node with the parse opcode and opcode name. + * + ******************************************************************************/ + +static void +TrAmlInitNode ( + ACPI_PARSE_OBJECT *Op, + UINT16 ParseOpcode) +{ + + Op->Asl.ParseOpcode = ParseOpcode; + UtSetParseOpName (Op); +} + + +/******************************************************************************* + * + * FUNCTION: TrAmlSetSubtreeParent + * + * PARAMETERS: Op - First node in a list of peer nodes + * Parent - Parent of the subtree + * + * RETURN: None + * + * DESCRIPTION: Set the parent for all peer nodes in a subtree + * + ******************************************************************************/ + +static void +TrAmlSetSubtreeParent ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *Parent) +{ + ACPI_PARSE_OBJECT *Next; + + + Next = Op; + while (Next) + { + Next->Asl.Parent = Parent; + Next = Next->Asl.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: TrAmlInsertPeer + * + * PARAMETERS: Op - First node in a list of peer nodes + * NewPeer - Peer node to insert + * + * RETURN: None + * + * DESCRIPTION: Insert a new peer node into a list of peers. + * + ******************************************************************************/ + +static void +TrAmlInsertPeer ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *NewPeer) +{ + + NewPeer->Asl.Next = Op->Asl.Next; + Op->Asl.Next = NewPeer; +} + + +/******************************************************************************* + * + * FUNCTION: TrAmlTransformWalk + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: None + * + * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML + * operands. + * + ******************************************************************************/ + +ACPI_STATUS +TrAmlTransformWalk ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + + TrTransformSubtree (Op); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: TrTransformSubtree + * + * PARAMETERS: Op - The parent parse node + * + * RETURN: None + * + * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more + * complex AML opcodes require processing of the child nodes + * (arguments/operands). + * + ******************************************************************************/ + +static void +TrTransformSubtree ( + ACPI_PARSE_OBJECT *Op) +{ + + if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) + { + return; + } + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + TrDoDefinitionBlock (Op); + break; + + case PARSEOP_SWITCH: + TrDoSwitch (Op); + break; + + case PARSEOP_METHOD: + + /* + * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global, + * however + */ + Gbl_TempCount = 0; + break; + + default: + /* Nothing to do here for other opcodes */ + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: TrDoDefinitionBlock + * + * PARAMETERS: Op - Parse node + * + * RETURN: None + * + * DESCRIPTION: Find the end of the definition block and set a global to this + * node. It is used by the compiler to insert compiler-generated + * names at the root level of the namespace. + * + ******************************************************************************/ + +static void +TrDoDefinitionBlock ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + UINT32 i; + + + Next = Op->Asl.Child; + for (i = 0; i < 5; i++) + { + Next = Next->Asl.Next; + if (i == 0) + { + /* + * This is the table signature. Only the DSDT can be assumed + * to be at the root of the namespace; Therefore, namepath + * optimization can only be performed on the DSDT. + */ + if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT)) + { + Gbl_ReferenceOptimizationFlag = FALSE; + } + } + } + + Gbl_FirstLevelInsertionNode = Next; +} + + +/******************************************************************************* + * + * FUNCTION: TrDoSwitch + * + * PARAMETERS: StartNode - Parse node for SWITCH + * + * RETURN: None + * + * + * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is + * no actual AML opcode for SWITCH -- it must be simulated. + * + ******************************************************************************/ + +static void +TrDoSwitch ( + ACPI_PARSE_OBJECT *StartNode) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_PARSE_OBJECT *CaseOp = NULL; + ACPI_PARSE_OBJECT *CaseBlock = NULL; + ACPI_PARSE_OBJECT *DefaultOp = NULL; + ACPI_PARSE_OBJECT *CurrentParentNode; + ACPI_PARSE_OBJECT *Conditional = NULL; + ACPI_PARSE_OBJECT *Predicate; + ACPI_PARSE_OBJECT *Peer; + ACPI_PARSE_OBJECT *NewOp; + ACPI_PARSE_OBJECT *NewOp2; + ACPI_PARSE_OBJECT *MethodOp; + ACPI_PARSE_OBJECT *StoreOp; + ACPI_PARSE_OBJECT *BreakOp; + ACPI_PARSE_OBJECT *BufferOp; + char *PredicateValueName; + UINT16 Index; + UINT32 Btype; + + + /* Start node is the Switch() node */ + + CurrentParentNode = StartNode; + + /* Create a new temp name of the form _T_x */ + + PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount); + if (!PredicateValueName) + { + return; + } + + /* First child is the Switch() predicate */ + + Next = StartNode->Asl.Child; + + /* + * Examine the return type of the Switch Value - + * must be Integer/Buffer/String + */ + Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); + Btype = AslKeywordMapping[Index].AcpiBtype; + if ((Btype != ACPI_BTYPE_INTEGER) && + (Btype != ACPI_BTYPE_STRING) && + (Btype != ACPI_BTYPE_BUFFER)) + { + AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL); + Btype = ACPI_BTYPE_INTEGER; + } + + /* CASE statements start at next child */ + + Peer = Next->Asl.Next; + while (Peer) + { + Next = Peer; + Peer = Next->Asl.Next; + + if (Next->Asl.ParseOpcode == PARSEOP_CASE) + { + if (CaseOp) + { + /* Add an ELSE to complete the previous CASE */ + + if (!Conditional) + { + return; + } + NewOp = TrCreateLeafNode (PARSEOP_ELSE); + NewOp->Asl.Parent = Conditional->Asl.Parent; + TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); + + /* Link ELSE node as a peer to the previous IF */ + + TrAmlInsertPeer (Conditional, NewOp); + CurrentParentNode = NewOp; + } + + CaseOp = Next; + Conditional = CaseOp; + CaseBlock = CaseOp->Asl.Child->Asl.Next; + Conditional->Asl.Child->Asl.Next = NULL; + Predicate = CaseOp->Asl.Child; + + if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) || + (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) + { + /* + * Convert the package declaration to this form: + * + * If (LNotEqual (Match (Package(){}, + * MEQ, _T_x, MTR, Zero, Zero), Ones)) + */ + NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ); + Predicate->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Conditional); + + NewOp = NewOp2; + NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, + (UINT64) ACPI_TO_INTEGER (PredicateValueName)); + NewOp->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Predicate); + + NewOp = NewOp2; + NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR); + NewOp->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Predicate); + + NewOp = NewOp2; + NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); + NewOp->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Predicate); + + NewOp = NewOp2; + NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); + NewOp->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Predicate); + + NewOp2 = TrCreateLeafNode (PARSEOP_MATCH); + NewOp2->Asl.Child = Predicate; /* PARSEOP_PACKAGE */ + TrAmlInitLineNumbers (NewOp2, Conditional); + TrAmlSetSubtreeParent (Predicate, NewOp2); + + NewOp = NewOp2; + NewOp2 = TrCreateLeafNode (PARSEOP_ONES); + NewOp->Asl.Next = NewOp2; + TrAmlInitLineNumbers (NewOp2, Conditional); + + NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); + NewOp2->Asl.Child = NewOp; + NewOp->Asl.Parent = NewOp2; + TrAmlInitLineNumbers (NewOp2, Conditional); + TrAmlSetSubtreeParent (NewOp, NewOp2); + + NewOp = NewOp2; + NewOp2 = TrCreateLeafNode (PARSEOP_LNOT); + NewOp2->Asl.Child = NewOp; + NewOp2->Asl.Parent = Conditional; + NewOp->Asl.Parent = NewOp2; + TrAmlInitLineNumbers (NewOp2, Conditional); + + Conditional->Asl.Child = NewOp2; + NewOp2->Asl.Next = CaseBlock; + } + else + { + /* + * Integer and Buffer case. + * + * Change CaseOp() to: If (LEqual (SwitchValue, CaseValue)) {...} + * Note: SwitchValue is first to allow the CaseValue to be implicitly + * converted to the type of SwitchValue if necessary. + * + * CaseOp->Child is the case value + * CaseOp->Child->Peer is the beginning of the case block + */ + NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, + (UINT64) ACPI_TO_INTEGER (PredicateValueName)); + NewOp->Asl.Next = Predicate; + TrAmlInitLineNumbers (NewOp, Predicate); + + NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); + NewOp2->Asl.Parent = Conditional; + NewOp2->Asl.Child = NewOp; + TrAmlInitLineNumbers (NewOp2, Conditional); + + TrAmlSetSubtreeParent (NewOp, NewOp2); + + Predicate = NewOp2; + Predicate->Asl.Next = CaseBlock; + + TrAmlSetSubtreeParent (Predicate, Conditional); + Conditional->Asl.Child = Predicate; + } + + /* Reinitialize the CASE node to an IF node */ + + TrAmlInitNode (Conditional, PARSEOP_IF); + + /* + * The first CASE(IF) is not nested under an ELSE. + * All other CASEs are children of a parent ELSE. + */ + if (CurrentParentNode == StartNode) + { + Conditional->Asl.Next = NULL; + } + else + { + /* + * The IF is a child of previous IF/ELSE. It + * is therefore without peer. + */ + CurrentParentNode->Asl.Child = Conditional; + Conditional->Asl.Parent = CurrentParentNode; + Conditional->Asl.Next = NULL; + } + } + else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) + { + if (DefaultOp) + { + /* + * More than one Default + * (Parser does not catch this, must check here) + */ + AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL); + } + else + { + /* Save the DEFAULT node for later, after CASEs */ + + DefaultOp = Next; + } + } + else + { + /* Unknown peer opcode */ + + AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n", + Next->Asl.ParseOpName, Next->Asl.ParseOpcode); + } + } + + /* Add the default case at the end of the if/else construct */ + + if (DefaultOp) + { + /* If no CASE statements, this is an error - see below */ + + if (CaseOp) + { + /* Convert the DEFAULT node to an ELSE */ + + if (!Conditional) + { + return; + } + + TrAmlInitNode (DefaultOp, PARSEOP_ELSE); + DefaultOp->Asl.Parent = Conditional->Asl.Parent; + + /* Link ELSE node as a peer to the previous IF */ + + TrAmlInsertPeer (Conditional, DefaultOp); + } + } + + if (!CaseOp) + { + AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL); + } + + + /* + * Create a Name(_T_x, ...) statement. This statement must appear at the + * method level, in case a loop surrounds the switch statement and could + * cause the name to be created twice (error). + */ + + /* Create the Name node */ + + Predicate = StartNode->Asl.Child; + NewOp = TrCreateLeafNode (PARSEOP_NAME); + TrAmlInitLineNumbers (NewOp, StartNode); + + /* Find the parent method */ + + Next = StartNode; + while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) && + (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK)) + { + Next = Next->Asl.Parent; + } + MethodOp = Next; + + NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED; + NewOp->Asl.Parent = Next; + + /* Insert name after the method name and arguments */ + + Next = Next->Asl.Child; /* Name */ + Next = Next->Asl.Next; /* NumArgs */ + Next = Next->Asl.Next; /* SerializeRule */ + + /* + * If method is not Serialized, we must make is so, because of the way + * that Switch() must be implemented -- we cannot allow multiple threads + * to execute this method concurrently since we need to create local + * temporary name(s). + */ + if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL) + { + AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, "Due to use of Switch operator"); + Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL; + } + + Next = Next->Asl.Next; /* SyncLevel */ + Next = Next->Asl.Next; /* ReturnType */ + Next = Next->Asl.Next; /* ParameterTypes */ + + TrAmlInsertPeer (Next, NewOp); + TrAmlInitLineNumbers (NewOp, Next); + + /* Create the NameSeg child for the Name node */ + + NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG, + (UINT64) ACPI_TO_INTEGER (PredicateValueName)); + TrAmlInitLineNumbers (NewOp2, NewOp); + NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION; + NewOp->Asl.Child = NewOp2; + + /* Create the initial value for the Name. Btype was already validated above */ + + switch (Btype) + { + case ACPI_BTYPE_INTEGER: + NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO, + (UINT64) 0); + TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp); + break; + + case ACPI_BTYPE_STRING: + NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, + (UINT64) ACPI_TO_INTEGER ("")); + TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp); + break; + + case ACPI_BTYPE_BUFFER: + (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER, + (UINT64) 0)); + Next = NewOp2->Asl.Next; + TrAmlInitLineNumbers (Next, NewOp2); + (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO, + (UINT64) 1)); + TrAmlInitLineNumbers (Next->Asl.Child, Next); + + BufferOp = TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0); + TrAmlInitLineNumbers (BufferOp, Next->Asl.Child); + (void) TrLinkPeerNode (Next->Asl.Child, BufferOp); + + TrAmlSetSubtreeParent (Next->Asl.Child, Next); + break; + + default: + break; + } + + TrAmlSetSubtreeParent (NewOp2, NewOp); + + /* + * Transform the Switch() into a While(One)-Break node. + * And create a Store() node which will be used to save the + * Switch() value. The store is of the form: Store (Value, _T_x) + * where _T_x is the temp variable. + */ + TrAmlInitNode (StartNode, PARSEOP_WHILE); + NewOp = TrCreateLeafNode (PARSEOP_ONE); + TrAmlInitLineNumbers (NewOp, StartNode); + NewOp->Asl.Next = Predicate->Asl.Next; + NewOp->Asl.Parent = StartNode; + StartNode->Asl.Child = NewOp; + + /* Create a Store() node */ + + StoreOp = TrCreateLeafNode (PARSEOP_STORE); + TrAmlInitLineNumbers (StoreOp, NewOp); + StoreOp->Asl.Parent = StartNode; + TrAmlInsertPeer (NewOp, StoreOp); + + /* Complete the Store subtree */ + + StoreOp->Asl.Child = Predicate; + Predicate->Asl.Parent = StoreOp; + + NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG, + (UINT64) ACPI_TO_INTEGER (PredicateValueName)); + TrAmlInitLineNumbers (NewOp, StoreOp); + NewOp->Asl.Parent = StoreOp; + Predicate->Asl.Next = NewOp; + + /* Create a Break() node and insert it into the end of While() */ + + Conditional = StartNode->Asl.Child; + while (Conditional->Asl.Next) + { + Conditional = Conditional->Asl.Next; + } + + BreakOp = TrCreateLeafNode (PARSEOP_BREAK); + TrAmlInitLineNumbers (BreakOp, NewOp); + BreakOp->Asl.Parent = StartNode; + TrAmlInsertPeer (Conditional, BreakOp); +} + + diff --git a/source/compiler/asltree.c b/source/compiler/asltree.c new file mode 100644 index 000000000000..dc6cb44b374a --- /dev/null +++ b/source/compiler/asltree.c @@ -0,0 +1,1202 @@ + +/****************************************************************************** + * + * Module Name: asltree - parse tree management + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "acapps.h" +#include + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asltree") + +/* Local prototypes */ + +static ACPI_PARSE_OBJECT * +TrGetNextNode ( + void); + +static char * +TrGetNodeFlagName ( + UINT32 Flags); + + +/******************************************************************************* + * + * FUNCTION: TrGetNextNode + * + * PARAMETERS: None + * + * RETURN: New parse node. Aborts on allocation failure + * + * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local + * dynamic memory manager for performance reasons (This has a + * major impact on the speed of the compiler.) + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +TrGetNextNode ( + void) +{ + + if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast) + { + Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) * + ASL_NODE_CACHE_SIZE); + Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE; + } + + return (Gbl_NodeCacheNext++); +} + + +/******************************************************************************* + * + * FUNCTION: TrAllocateNode + * + * PARAMETERS: ParseOpcode - Opcode to be assigned to the node + * + * RETURN: New parse node. Aborts on allocation failure + * + * DESCRIPTION: Allocate and initialize a new parse node for the parse tree + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrAllocateNode ( + UINT32 ParseOpcode) +{ + ACPI_PARSE_OBJECT *Op; + + + Op = TrGetNextNode (); + + Op->Asl.ParseOpcode = (UINT16) ParseOpcode; + Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; + Op->Asl.LineNumber = Gbl_CurrentLineNumber; + Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; + Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; + Op->Asl.Column = Gbl_CurrentColumn; + + UtSetParseOpName (Op); + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrReleaseNode + * + * PARAMETERS: Op - Op to be released + * + * RETURN: None + * + * DESCRIPTION: "release" a node. In truth, nothing is done since the node + * is part of a larger buffer + * + ******************************************************************************/ + +void +TrReleaseNode ( + ACPI_PARSE_OBJECT *Op) +{ + + return; +} + + +/******************************************************************************* + * + * FUNCTION: TrUpdateNode + * + * PARAMETERS: ParseOpcode - New opcode to be assigned to the node + * Op - An existing parse node + * + * RETURN: The updated node + * + * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to + * change an opcode to DEFAULT_ARG so that the node is ignored + * during the code generation. Also used to set generic integers + * to a specific size (8, 16, 32, or 64 bits) + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrUpdateNode ( + UINT32 ParseOpcode, + ACPI_PARSE_OBJECT *Op) +{ + + if (!Op) + { + return NULL; + } + + DbgPrint (ASL_PARSE_OUTPUT, + "\nUpdateNode: Old - %s, New - %s\n\n", + UtGetOpName (Op->Asl.ParseOpcode), + UtGetOpName (ParseOpcode)); + + /* Assign new opcode and name */ + + if (Op->Asl.ParseOpcode == PARSEOP_ONES) + { + switch (ParseOpcode) + { + case PARSEOP_BYTECONST: + Op->Asl.Value.Integer = 0xFF; + break; + + case PARSEOP_WORDCONST: + Op->Asl.Value.Integer = 0xFFFF; + break; + + case PARSEOP_DWORDCONST: + Op->Asl.Value.Integer = 0xFFFFFFFF; + break; + + default: + /* Don't care about others, don't need to check QWORD */ + break; + } + } + + Op->Asl.ParseOpcode = (UINT16) ParseOpcode; + UtSetParseOpName (Op); + + /* + * For the BYTE, WORD, and DWORD constants, make sure that the integer + * that was passed in will actually fit into the data type + */ + switch (ParseOpcode) + { + case PARSEOP_BYTECONST: + Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); + break; + + case PARSEOP_WORDCONST: + Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); + break; + + case PARSEOP_DWORDCONST: + Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); + break; + + default: + /* Don't care about others, don't need to check QWORD */ + break; + } + + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrGetNodeFlagName + * + * PARAMETERS: Flags - Flags word to be decoded + * + * RETURN: Name string. Always returns a valid string pointer. + * + * DESCRIPTION: Decode a flags word + * + ******************************************************************************/ + +static char * +TrGetNodeFlagName ( + UINT32 Flags) +{ + + switch (Flags) + { + case NODE_VISITED: + return ("NODE_VISITED"); + + case NODE_AML_PACKAGE: + return ("NODE_AML_PACKAGE"); + + case NODE_IS_TARGET: + return ("NODE_IS_TARGET"); + + case NODE_IS_RESOURCE_DESC: + return ("NODE_IS_RESOURCE_DESC"); + + case NODE_IS_RESOURCE_FIELD: + return ("NODE_IS_RESOURCE_FIELD"); + + case NODE_HAS_NO_EXIT: + return ("NODE_HAS_NO_EXIT"); + + case NODE_IF_HAS_NO_EXIT: + return ("NODE_IF_HAS_NO_EXIT"); + + case NODE_NAME_INTERNALIZED: + return ("NODE_NAME_INTERNALIZED"); + + case NODE_METHOD_NO_RETVAL: + return ("NODE_METHOD_NO_RETVAL"); + + case NODE_METHOD_SOME_NO_RETVAL: + return ("NODE_METHOD_SOME_NO_RETVAL"); + + case NODE_RESULT_NOT_USED: + return ("NODE_RESULT_NOT_USED"); + + case NODE_METHOD_TYPED: + return ("NODE_METHOD_TYPED"); + + case NODE_COMPILE_TIME_CONST: + return ("NODE_COMPILE_TIME_CONST"); + + case NODE_IS_TERM_ARG: + return ("NODE_IS_TERM_ARG"); + + case NODE_WAS_ONES_OP: + return ("NODE_WAS_ONES_OP"); + + case NODE_IS_NAME_DECLARATION: + return ("NODE_IS_NAME_DECLARATION"); + + default: + return ("Multiple Flags (or unknown flag) set"); + } +} + + +/******************************************************************************* + * + * FUNCTION: TrSetNodeFlags + * + * PARAMETERS: Op - An existing parse node + * Flags - New flags word + * + * RETURN: The updated parser op + * + * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrSetNodeFlags ( + ACPI_PARSE_OBJECT *Op, + UINT32 Flags) +{ + + DbgPrint (ASL_PARSE_OUTPUT, + "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags, + TrGetNodeFlagName (Flags)); + + if (!Op) + { + return NULL; + } + + Op->Asl.CompileFlags |= Flags; + + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrSetEndLineNumber + * + * PARAMETERS: Op - An existing parse node + * + * RETURN: None. + * + * DESCRIPTION: Set the ending line numbers (file line and logical line) of a + * parse node to the current line numbers. + * + ******************************************************************************/ + +void +TrSetEndLineNumber ( + ACPI_PARSE_OBJECT *Op) +{ + + /* If the end line # is already set, just return */ + + if (Op->Asl.EndLine) + { + return; + } + + Op->Asl.EndLine = Gbl_CurrentLineNumber; + Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; +} + + +/******************************************************************************* + * + * FUNCTION: TrCreateLeafNode + * + * PARAMETERS: ParseOpcode - New opcode to be assigned to the node + * + * RETURN: Pointer to the new node. Aborts on allocation failure + * + * DESCRIPTION: Create a simple leaf node (no children or peers, and no value + * assigned to the node) + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrCreateLeafNode ( + UINT32 ParseOpcode) +{ + ACPI_PARSE_OBJECT *Op; + + + Op = TrAllocateNode (ParseOpcode); + + DbgPrint (ASL_PARSE_OUTPUT, + "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", + Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode)); + + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrCreateConstantLeafNode + * + * PARAMETERS: ParseOpcode - The constant opcode + * + * RETURN: Pointer to the new node. Aborts on allocation failure + * + * DESCRIPTION: Create a leaf node (no children or peers) for one of the + * special constants - __LINE__, __FILE__, and __DATE__. + * + * Note: An implemenation of __FUNC__ cannot happen here because we don't + * have a full parse tree at this time and cannot find the parent control + * method. If it is ever needed, __FUNC__ must be implemented later, after + * the parse tree has been fully constructed. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrCreateConstantLeafNode ( + UINT32 ParseOpcode) +{ + ACPI_PARSE_OBJECT *Op = NULL; + time_t CurrentTime; + char *StaticTimeString; + char *TimeString; + char *Path; + char *Filename; + + + switch (ParseOpcode) + { + case PARSEOP___LINE__: + Op = TrAllocateNode (PARSEOP_INTEGER); + Op->Asl.Value.Integer = Op->Asl.LineNumber; + break; + + case PARSEOP___PATH__: + Op = TrAllocateNode (PARSEOP_STRING_LITERAL); + + /* Op.Asl.Filename contains the full pathname to the file */ + + Op->Asl.Value.String = Op->Asl.Filename; + break; + + case PARSEOP___FILE__: + Op = TrAllocateNode (PARSEOP_STRING_LITERAL); + + /* Get the simple filename from the full path */ + + FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename); + ACPI_FREE (Path); + Op->Asl.Value.String = Filename; + break; + + case PARSEOP___DATE__: + Op = TrAllocateNode (PARSEOP_STRING_LITERAL); + + /* Get a copy of the current time */ + + CurrentTime = time (NULL); + StaticTimeString = ctime (&CurrentTime); + TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); + strcpy (TimeString, StaticTimeString); + + TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ + Op->Asl.Value.String = TimeString; + break; + + default: /* This would be an internal error */ + return (NULL); + } + + DbgPrint (ASL_PARSE_OUTPUT, + "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", + Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), + ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); + return (Op); +} + + +/******************************************************************************* + * + * FUNCTION: TrCreateValuedLeafNode + * + * PARAMETERS: ParseOpcode - New opcode to be assigned to the node + * Value - Value to be assigned to the node + * + * RETURN: Pointer to the new node. Aborts on allocation failure + * + * DESCRIPTION: Create a leaf node (no children or peers) with a value + * assigned to it + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrCreateValuedLeafNode ( + UINT32 ParseOpcode, + UINT64 Value) +{ + ACPI_PARSE_OBJECT *Op; + + + Op = TrAllocateNode (ParseOpcode); + + DbgPrint (ASL_PARSE_OUTPUT, + "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", + Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), + ACPI_FORMAT_UINT64 (Value)); + Op->Asl.Value.Integer = Value; + + switch (ParseOpcode) + { + case PARSEOP_STRING_LITERAL: + DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); + break; + + case PARSEOP_NAMESEG: + DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); + break; + + case PARSEOP_NAMESTRING: + DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); + break; + + case PARSEOP_EISAID: + DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); + break; + + case PARSEOP_METHOD: + DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); + break; + + case PARSEOP_INTEGER: + DbgPrint (ASL_PARSE_OUTPUT, "INTEGER"); + break; + + default: + break; + } + + DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrCreateNode + * + * PARAMETERS: ParseOpcode - Opcode to be assigned to the node + * NumChildren - Number of children to follow + * ... - A list of child nodes to link to the new + * node. NumChildren long. + * + * RETURN: Pointer to the new node. Aborts on allocation failure + * + * DESCRIPTION: Create a new parse node and link together a list of child + * nodes underneath the new node. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrCreateNode ( + UINT32 ParseOpcode, + UINT32 NumChildren, + ...) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_PARSE_OBJECT *Child; + ACPI_PARSE_OBJECT *PrevChild; + va_list ap; + UINT32 i; + BOOLEAN FirstChild; + + + va_start (ap, NumChildren); + + /* Allocate one new node */ + + Op = TrAllocateNode (ParseOpcode); + + DbgPrint (ASL_PARSE_OUTPUT, + "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", + Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode)); + + /* Some extra debug output based on the parse opcode */ + + switch (ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + RootNode = Op; + DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); + break; + + case PARSEOP_OPERATIONREGION: + DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); + break; + + case PARSEOP_OR: + DbgPrint (ASL_PARSE_OUTPUT, "OR->"); + break; + + default: + /* Nothing to do for other opcodes */ + break; + } + + /* Link the new node to its children */ + + PrevChild = NULL; + FirstChild = TRUE; + for (i = 0; i < NumChildren; i++) + { + /* Get the next child */ + + Child = va_arg (ap, ACPI_PARSE_OBJECT *); + DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); + + /* + * If child is NULL, this means that an optional argument + * was omitted. We must create a placeholder with a special + * opcode (DEFAULT_ARG) so that the code generator will know + * that it must emit the correct default for this argument + */ + if (!Child) + { + Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); + } + + /* Link first child to parent */ + + if (FirstChild) + { + FirstChild = FALSE; + Op->Asl.Child = Child; + } + + /* Point all children to parent */ + + Child->Asl.Parent = Op; + + /* Link children in a peer list */ + + if (PrevChild) + { + PrevChild->Asl.Next = Child; + }; + + /* + * This child might be a list, point all nodes in the list + * to the same parent + */ + while (Child->Asl.Next) + { + Child = Child->Asl.Next; + Child->Asl.Parent = Op; + } + + PrevChild = Child; + } + va_end(ap); + + DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrLinkChildren + * + * PARAMETERS: Op - An existing parse node + * NumChildren - Number of children to follow + * ... - A list of child nodes to link to the new + * node. NumChildren long. + * + * RETURN: The updated (linked) node + * + * DESCRIPTION: Link a group of nodes to an existing parse node + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrLinkChildren ( + ACPI_PARSE_OBJECT *Op, + UINT32 NumChildren, + ...) +{ + ACPI_PARSE_OBJECT *Child; + ACPI_PARSE_OBJECT *PrevChild; + va_list ap; + UINT32 i; + BOOLEAN FirstChild; + + + va_start (ap, NumChildren); + + + TrSetEndLineNumber (Op); + + DbgPrint (ASL_PARSE_OUTPUT, + "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", + Op->Asl.LineNumber, Op->Asl.EndLine, + Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_DEFINITIONBLOCK: + RootNode = Op; + DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); + break; + + case PARSEOP_OPERATIONREGION: + DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); + break; + + case PARSEOP_OR: + DbgPrint (ASL_PARSE_OUTPUT, "OR->"); + break; + + default: + /* Nothing to do for other opcodes */ + break; + } + + /* Link the new node to it's children */ + + PrevChild = NULL; + FirstChild = TRUE; + for (i = 0; i < NumChildren; i++) + { + Child = va_arg (ap, ACPI_PARSE_OBJECT *); + + if ((Child == PrevChild) && (Child != NULL)) + { + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, + "Child node list invalid"); + return Op; + } + + DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); + + /* + * If child is NULL, this means that an optional argument + * was omitted. We must create a placeholder with a special + * opcode (DEFAULT_ARG) so that the code generator will know + * that it must emit the correct default for this argument + */ + if (!Child) + { + Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); + } + + /* Link first child to parent */ + + if (FirstChild) + { + FirstChild = FALSE; + Op->Asl.Child = Child; + } + + /* Point all children to parent */ + + Child->Asl.Parent = Op; + + /* Link children in a peer list */ + + if (PrevChild) + { + PrevChild->Asl.Next = Child; + }; + + /* + * This child might be a list, point all nodes in the list + * to the same parent + */ + while (Child->Asl.Next) + { + Child = Child->Asl.Next; + Child->Asl.Parent = Op; + } + PrevChild = Child; + } + va_end(ap); + + DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: TrLinkPeerNode + * + * PARAMETERS: Op1 - First peer + * Op2 - Second peer + * + * RETURN: Op1 or the non-null node. + * + * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrLinkPeerNode ( + ACPI_PARSE_OBJECT *Op1, + ACPI_PARSE_OBJECT *Op2) +{ + ACPI_PARSE_OBJECT *Next; + + + DbgPrint (ASL_PARSE_OUTPUT, + "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n", + Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, + Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); + + + if ((!Op1) && (!Op2)) + { + DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); + return Op1; + } + + /* If one of the nodes is null, just return the non-null node */ + + if (!Op2) + { + return Op1; + } + + if (!Op1) + { + return Op2; + } + + if (Op1 == Op2) + { + DbgPrint (ASL_DEBUG_OUTPUT, + "\n\n************* Internal error, linking node to itself %p\n\n\n", + Op1); + AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, + "Linking node to itself"); + return Op1; + } + + Op1->Asl.Parent = Op2->Asl.Parent; + + /* + * Op 1 may already have a peer list (such as an IF/ELSE pair), + * so we must walk to the end of the list and attach the new + * peer at the end + */ + Next = Op1; + while (Next->Asl.Next) + { + Next = Next->Asl.Next; + } + + Next->Asl.Next = Op2; + return Op1; +} + + +/******************************************************************************* + * + * FUNCTION: TrLinkPeerNodes + * + * PARAMETERS: NumPeers - The number of nodes in the list to follow + * ... - A list of nodes to link together as peers + * + * RETURN: The first node in the list (head of the peer list) + * + * DESCRIPTION: Link together an arbitrary number of peer nodes. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrLinkPeerNodes ( + UINT32 NumPeers, + ...) +{ + ACPI_PARSE_OBJECT *This; + ACPI_PARSE_OBJECT *Next; + va_list ap; + UINT32 i; + ACPI_PARSE_OBJECT *Start; + + + DbgPrint (ASL_PARSE_OUTPUT, + "\nLinkPeerNodes: (%u) ", NumPeers); + + va_start (ap, NumPeers); + This = va_arg (ap, ACPI_PARSE_OBJECT *); + Start = This; + + /* + * Link all peers + */ + for (i = 0; i < (NumPeers -1); i++) + { + DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); + + while (This->Asl.Next) + { + This = This->Asl.Next; + } + + /* Get another peer node */ + + Next = va_arg (ap, ACPI_PARSE_OBJECT *); + if (!Next) + { + Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); + } + + /* link new node to the current node */ + + This->Asl.Next = Next; + This = Next; + } + va_end (ap); + + DbgPrint (ASL_PARSE_OUTPUT,"\n\n"); + return (Start); +} + + +/******************************************************************************* + * + * FUNCTION: TrLinkChildNode + * + * PARAMETERS: Op1 - Parent node + * Op2 - Op to become a child + * + * RETURN: The parent node + * + * DESCRIPTION: Link two nodes together as a parent and child + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +TrLinkChildNode ( + ACPI_PARSE_OBJECT *Op1, + ACPI_PARSE_OBJECT *Op2) +{ + ACPI_PARSE_OBJECT *Next; + + + DbgPrint (ASL_PARSE_OUTPUT, + "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n", + Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, + Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); + + if (!Op1 || !Op2) + { + return Op1; + } + + Op1->Asl.Child = Op2; + + /* Set the child and all peers of the child to point to the parent */ + + Next = Op2; + while (Next) + { + Next->Asl.Parent = Op1; + Next = Next->Asl.Next; + } + + return Op1; +} + + +/******************************************************************************* + * + * FUNCTION: TrWalkParseTree + * + * PARAMETERS: Visitation - Type of walk + * DescendingCallback - Called during tree descent + * AscendingCallback - Called during tree ascent + * Context - To be passed to the callbacks + * + * RETURN: Status from callback(s) + * + * DESCRIPTION: Walk the entire parse tree. + * + ******************************************************************************/ + +ACPI_STATUS +TrWalkParseTree ( + ACPI_PARSE_OBJECT *Op, + UINT32 Visitation, + ASL_WALK_CALLBACK DescendingCallback, + ASL_WALK_CALLBACK AscendingCallback, + void *Context) +{ + UINT32 Level; + BOOLEAN NodePreviouslyVisited; + ACPI_PARSE_OBJECT *StartOp = Op; + ACPI_STATUS Status; + + + if (!RootNode) + { + return (AE_OK); + } + + Level = 0; + NodePreviouslyVisited = FALSE; + + switch (Visitation) + { + case ASL_WALK_VISIT_DOWNWARD: + + while (Op) + { + if (!NodePreviouslyVisited) + { + /* Let the callback process the node. */ + + Status = DescendingCallback (Op, Level, Context); + if (ACPI_SUCCESS (Status)) + { + /* Visit children first, once */ + + if (Op->Asl.Child) + { + Level++; + Op = Op->Asl.Child; + continue; + } + } + else if (Status != AE_CTRL_DEPTH) + { + /* Exit immediately on any error */ + + return (Status); + } + } + + /* Terminate walk at start op */ + + if (Op == StartOp) + { + break; + } + + /* No more children, visit peers */ + + if (Op->Asl.Next) + { + Op = Op->Asl.Next; + NodePreviouslyVisited = FALSE; + } + else + { + /* No children or peers, re-visit parent */ + + if (Level != 0 ) + { + Level--; + } + Op = Op->Asl.Parent; + NodePreviouslyVisited = TRUE; + } + } + break; + + + case ASL_WALK_VISIT_UPWARD: + + while (Op) + { + /* Visit leaf node (no children) or parent node on return trip */ + + if ((!Op->Asl.Child) || + (NodePreviouslyVisited)) + { + /* Let the callback process the node. */ + + Status = AscendingCallback (Op, Level, Context); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else + { + /* Visit children first, once */ + + Level++; + Op = Op->Asl.Child; + continue; + } + + /* Terminate walk at start op */ + + if (Op == StartOp) + { + break; + } + + /* No more children, visit peers */ + + if (Op->Asl.Next) + { + Op = Op->Asl.Next; + NodePreviouslyVisited = FALSE; + } + else + { + /* No children or peers, re-visit parent */ + + if (Level != 0 ) + { + Level--; + } + Op = Op->Asl.Parent; + NodePreviouslyVisited = TRUE; + } + } + break; + + + case ASL_WALK_VISIT_TWICE: + + while (Op) + { + if (NodePreviouslyVisited) + { + Status = AscendingCallback (Op, Level, Context); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else + { + /* Let the callback process the node. */ + + Status = DescendingCallback (Op, Level, Context); + if (ACPI_SUCCESS (Status)) + { + /* Visit children first, once */ + + if (Op->Asl.Child) + { + Level++; + Op = Op->Asl.Child; + continue; + } + } + else if (Status != AE_CTRL_DEPTH) + { + /* Exit immediately on any error */ + + return (Status); + } + } + + /* Terminate walk at start op */ + + if (Op == StartOp) + { + break; + } + + /* No more children, visit peers */ + + if (Op->Asl.Next) + { + Op = Op->Asl.Next; + NodePreviouslyVisited = FALSE; + } + else + { + /* No children or peers, re-visit parent */ + + if (Level != 0 ) + { + Level--; + } + Op = Op->Asl.Parent; + NodePreviouslyVisited = TRUE; + } + } + break; + + default: + /* No other types supported */ + break; + } + + /* If we get here, the walk completed with no errors */ + + return (AE_OK); +} + + diff --git a/source/compiler/asltypes.h b/source/compiler/asltypes.h new file mode 100644 index 000000000000..0205181d227c --- /dev/null +++ b/source/compiler/asltypes.h @@ -0,0 +1,236 @@ + +/****************************************************************************** + * + * Module Name: asltypes.h - compiler data types and struct definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ASLTYPES_H +#define __ASLTYPES_H + + +/******************************************************************************* + * + * Structure definitions + * + ******************************************************************************/ + + +/* Op flags for the ACPI_PARSE_OBJECT */ + +#define NODE_VISITED 0x00000001 +#define NODE_AML_PACKAGE 0x00000002 +#define NODE_IS_TARGET 0x00000004 +#define NODE_IS_RESOURCE_DESC 0x00000008 +#define NODE_IS_RESOURCE_FIELD 0x00000010 +#define NODE_HAS_NO_EXIT 0x00000020 +#define NODE_IF_HAS_NO_EXIT 0x00000040 +#define NODE_NAME_INTERNALIZED 0x00000080 +#define NODE_METHOD_NO_RETVAL 0x00000100 +#define NODE_METHOD_SOME_NO_RETVAL 0x00000200 +#define NODE_RESULT_NOT_USED 0x00000400 +#define NODE_METHOD_TYPED 0x00000800 +#define NODE_UNUSED_FLAG 0x00001000 +#define NODE_COMPILE_TIME_CONST 0x00002000 +#define NODE_IS_TERM_ARG 0x00004000 +#define NODE_WAS_ONES_OP 0x00008000 +#define NODE_IS_NAME_DECLARATION 0x00010000 +#define NODE_COMPILER_EMITTED 0x00020000 +#define NODE_IS_DUPLICATE 0x00040000 +#define NODE_IS_RESOURCE_DATA 0x00080000 +#define NODE_IS_NULL_RETURN 0x00100000 + +/* Keeps information about individual control methods */ + +typedef struct asl_method_info +{ + UINT8 NumArguments; + UINT8 LocalInitialized[ACPI_METHOD_NUM_LOCALS]; + UINT8 ArgInitialized[ACPI_METHOD_NUM_ARGS]; + UINT32 ValidArgTypes[ACPI_METHOD_NUM_ARGS]; + UINT32 ValidReturnTypes; + UINT32 NumReturnNoValue; + UINT32 NumReturnWithValue; + ACPI_PARSE_OBJECT *Op; + struct asl_method_info *Next; + UINT8 HasBeenTyped; + +} ASL_METHOD_INFO; + + +/* Parse tree walk info for control method analysis */ + +typedef struct asl_analysis_walk_info +{ + ASL_METHOD_INFO *MethodStack; + +} ASL_ANALYSIS_WALK_INFO; + + +/* An entry in the ParseOpcode to AmlOpcode mapping table */ + +typedef struct asl_mapping_entry +{ + UINT32 Value; + UINT32 AcpiBtype; /* Object type or return type */ + UINT16 AmlOpcode; + UINT8 Flags; + +} ASL_MAPPING_ENTRY; + + +/* Parse tree walk info structure */ + +typedef struct asl_walk_info +{ + ACPI_PARSE_OBJECT **NodePtr; + UINT32 *LevelPtr; + +} ASL_WALK_INFO; + + +/* File info */ + +typedef struct asl_file_info +{ + FILE *Handle; + char *Filename; + +} ASL_FILE_INFO; + +typedef struct asl_file_status +{ + UINT32 Line; + UINT32 Offset; + +} ASL_FILE_STATUS; + + +/* + * File types. Note: Any changes to this table must also be reflected + * in the AslFileTypeNames array. + */ +typedef enum +{ + ASL_FILE_STDOUT = 0, + ASL_FILE_STDERR, + ASL_FILE_INPUT, + ASL_FILE_AML_OUTPUT, + ASL_FILE_SOURCE_OUTPUT, + ASL_FILE_LISTING_OUTPUT, + ASL_FILE_HEX_OUTPUT, + ASL_FILE_NAMESPACE_OUTPUT, + ASL_FILE_DEBUG_OUTPUT, + ASL_FILE_ASM_SOURCE_OUTPUT, + ASL_FILE_C_SOURCE_OUTPUT, + ASL_FILE_ASM_INCLUDE_OUTPUT, + ASL_FILE_C_INCLUDE_OUTPUT + +} ASL_FILE_TYPES; + + +#define ASL_MAX_FILE_TYPE 12 +#define ASL_NUM_FILES (ASL_MAX_FILE_TYPE + 1) + + +typedef struct asl_include_dir +{ + char *Dir; + struct asl_include_dir *Next; + +} ASL_INCLUDE_DIR; + + +/* An entry in the exception list, one for each error/warning */ + +typedef struct asl_error_msg +{ + UINT32 LineNumber; + UINT32 LogicalLineNumber; + UINT32 LogicalByteOffset; + UINT32 Column; + char *Message; + struct asl_error_msg *Next; + char *Filename; + UINT32 FilenameLength; + UINT8 MessageId; + UINT8 Level; + +} ASL_ERROR_MSG; + + +/* An entry in the listing file stack (for include files) */ + +typedef struct asl_listing_node +{ + char *Filename; + UINT32 LineNumber; + struct asl_listing_node *Next; + +} ASL_LISTING_NODE; + + +/* Callback interface for a parse tree walk */ + +/* + * TBD - another copy of this is in adisasm.h, fix + */ +#ifndef ASL_WALK_CALLBACK_DEFINED +typedef +ACPI_STATUS (*ASL_WALK_CALLBACK) ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); +#define ASL_WALK_CALLBACK_DEFINED +#endif + + +typedef struct asl_event_info +{ + UINT64 StartTime; + UINT64 EndTime; + char *EventName; + BOOLEAN Valid; + +} ASL_EVENT_INFO; + + +#endif /* __ASLTYPES_H */ diff --git a/source/compiler/aslutils.c b/source/compiler/aslutils.c new file mode 100644 index 000000000000..4edc8c4bb8b8 --- /dev/null +++ b/source/compiler/aslutils.c @@ -0,0 +1,1068 @@ + +/****************************************************************************** + * + * Module Name: aslutils -- compiler utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "acdisasm.h" +#include "acnamesp.h" +#include "amlcode.h" +#include + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslutils") + + +char AslHexLookup[] = +{ + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' +}; + +/* Table below must match ASL_FILE_TYPES in asltypes.h */ + +static const char *AslFileTypeNames [ASL_NUM_FILES] = +{ + "stdout: ", + "stderr: ", + "Table Input: ", + "Binary Output:", + "Source Output:", + "Listing File: ", + "Hex Dump: ", + "Namespace: ", + "Debug File: ", + "ASM Source: ", + "C Source: ", + "ASM Include: ", + "C Include: " +}; + + +/* Local prototypes */ + +static void +UtPadNameWithUnderscores ( + char *NameSeg, + char *PaddedNameSeg); + +static void +UtAttachNameseg ( + ACPI_PARSE_OBJECT *Op, + char *Name); + + +/******************************************************************************* + * + * FUNCTION: UtDisplaySupportedTables + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print all supported ACPI table names. + * + ******************************************************************************/ + +void +UtDisplaySupportedTables ( + void) +{ + ACPI_DMTABLE_DATA *TableData; + UINT32 i = 6; + + + printf ("\nACPI tables supported by iASL subsystems in " + "version %8.8X:\n" + " ASL and Data Table compilers\n" + " AML and Data Table disassemblers\n" + " ACPI table template generator\n\n", ACPI_CA_VERSION); + + /* Special tables */ + + printf ("%8u) %s %s\n", 1, ACPI_SIG_DSDT, "Differentiated System Description Table"); + printf ("%8u) %s %s\n", 2, ACPI_SIG_SSDT, "Secondary System Description Table"); + printf ("%8u) %s %s\n", 3, ACPI_SIG_FADT, "Fixed ACPI Description Table (FADT)"); + printf ("%8u) %s %s\n", 4, ACPI_SIG_FACS, "Firmware ACPI Control Structure"); + printf ("%8u) %s %s\n", 5, ACPI_RSDP_NAME, "Root System Description Pointer"); + + /* All data tables with common table header */ + + for (TableData = AcpiDmTableData; TableData->Signature; TableData++) + { + printf ("%8u) %s %s\n", i, TableData->Signature, TableData->Name); + i++; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsDisplayConstantOpcodes + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print AML opcodes that can be used in constant expressions. + * + ******************************************************************************/ + +void +UtDisplayConstantOpcodes ( + void) +{ + UINT32 i; + + + printf ("Constant expression opcode information\n\n"); + + for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++) + { + if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT) + { + printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: UtLocalCalloc + * + * PARAMETERS: Size - Bytes to be allocated + * + * RETURN: Pointer to the allocated memory. Guaranteed to be valid. + * + * DESCRIPTION: Allocate zero-initialized memory. Aborts the compile on an + * allocation failure, on the assumption that nothing more can be + * accomplished. + * + ******************************************************************************/ + +void * +UtLocalCalloc ( + UINT32 Size) +{ + void *Allocated; + + + Allocated = ACPI_ALLOCATE_ZEROED (Size); + if (!Allocated) + { + AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, + Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, + Gbl_InputByteCount, Gbl_CurrentColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, NULL); + + CmCleanupAndExit (); + exit (1); + } + + TotalAllocations++; + TotalAllocated += Size; + return (Allocated); +} + + +/******************************************************************************* + * + * FUNCTION: UtBeginEvent + * + * PARAMETERS: Name - Ascii name of this event + * + * RETURN: Event - Event number (integer index) + * + * DESCRIPTION: Saves the current time with this event + * + ******************************************************************************/ + +UINT8 +UtBeginEvent ( + char *Name) +{ + + if (AslGbl_NextEvent >= ASL_NUM_EVENTS) + { + AcpiOsPrintf ("Ran out of compiler event structs!\n"); + return (AslGbl_NextEvent); + } + + /* Init event with current (start) time */ + + AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer (); + AslGbl_Events[AslGbl_NextEvent].EventName = Name; + AslGbl_Events[AslGbl_NextEvent].Valid = TRUE; + + return (AslGbl_NextEvent++); +} + + +/******************************************************************************* + * + * FUNCTION: UtEndEvent + * + * PARAMETERS: Event - Event number (integer index) + * + * RETURN: None + * + * DESCRIPTION: Saves the current time (end time) with this event + * + ******************************************************************************/ + +void +UtEndEvent ( + UINT8 Event) +{ + + if (Event >= ASL_NUM_EVENTS) + { + return; + } + + /* Insert end time for event */ + + AslGbl_Events[Event].EndTime = AcpiOsGetTimer (); +} + + +/******************************************************************************* + * + * FUNCTION: UtHexCharToValue + * + * PARAMETERS: HexChar - Hex character in Ascii + * + * RETURN: The binary value of the hex character + * + * DESCRIPTION: Perform ascii-to-hex translation + * + ******************************************************************************/ + +UINT8 +UtHexCharToValue ( + int HexChar) +{ + + if (HexChar <= 0x39) + { + return ((UINT8) (HexChar - 0x30)); + } + + if (HexChar <= 0x46) + { + return ((UINT8) (HexChar - 0x37)); + } + + return ((UINT8) (HexChar - 0x57)); +} + + +/******************************************************************************* + * + * FUNCTION: UtConvertByteToHex + * + * PARAMETERS: RawByte - Binary data + * Buffer - Pointer to where the hex bytes will be stored + * + * RETURN: Ascii hex byte is stored in Buffer. + * + * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed + * with "0x" + * + ******************************************************************************/ + +void +UtConvertByteToHex ( + UINT8 RawByte, + UINT8 *Buffer) +{ + + Buffer[0] = '0'; + Buffer[1] = 'x'; + + Buffer[2] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF]; + Buffer[3] = (UINT8) AslHexLookup[RawByte & 0xF]; +} + + +/******************************************************************************* + * + * FUNCTION: UtConvertByteToAsmHex + * + * PARAMETERS: RawByte - Binary data + * Buffer - Pointer to where the hex bytes will be stored + * + * RETURN: Ascii hex byte is stored in Buffer. + * + * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed + * with "0x" + * + ******************************************************************************/ + +void +UtConvertByteToAsmHex ( + UINT8 RawByte, + UINT8 *Buffer) +{ + + Buffer[0] = '0'; + Buffer[1] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF]; + Buffer[2] = (UINT8) AslHexLookup[RawByte & 0xF]; + Buffer[3] = 'h'; +} + + +/******************************************************************************* + * + * FUNCTION: DbgPrint + * + * PARAMETERS: Type - Type of output + * Fmt - Printf format string + * ... - variable printf list + * + * RETURN: None + * + * DESCRIPTION: Conditional print statement. Prints to stderr only if the + * debug flag is set. + * + ******************************************************************************/ + +void +DbgPrint ( + UINT32 Type, + char *Fmt, + ...) +{ + va_list Args; + + + va_start (Args, Fmt); + + if (!Gbl_DebugFlag) + { + return; + } + + if ((Type == ASL_PARSE_OUTPUT) && + (!(AslCompilerdebug))) + { + return; + } + + (void) vfprintf (stderr, Fmt, Args); + va_end (Args); + return; +} + + +/******************************************************************************* + * + * FUNCTION: UtPrintFormattedName + * + * PARAMETERS: ParseOpcode - Parser keyword ID + * Level - Indentation level + * + * RETURN: None + * + * DESCRIPTION: Print the ascii name of the parse opcode. + * + ******************************************************************************/ + +#define TEXT_OFFSET 10 + +void +UtPrintFormattedName ( + UINT16 ParseOpcode, + UINT32 Level) +{ + + if (Level) + { + DbgPrint (ASL_TREE_OUTPUT, + "%*s", (3 * Level), " "); + } + DbgPrint (ASL_TREE_OUTPUT, + " %-20.20s", UtGetOpName (ParseOpcode)); + + if (Level < TEXT_OFFSET) + { + DbgPrint (ASL_TREE_OUTPUT, + "%*s", (TEXT_OFFSET - Level) * 3, " "); + } +} + + +/******************************************************************************* + * + * FUNCTION: UtSetParseOpName + * + * PARAMETERS: Op + * + * RETURN: None + * + * DESCRIPTION: Insert the ascii name of the parse opcode + * + ******************************************************************************/ + +void +UtSetParseOpName ( + ACPI_PARSE_OBJECT *Op) +{ + + strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode), + ACPI_MAX_PARSEOP_NAME); +} + + +/******************************************************************************* + * + * FUNCTION: UtDisplaySummary + * + * PARAMETERS: FileID - ID of outpout file + * + * RETURN: None + * + * DESCRIPTION: Display compilation statistics + * + ******************************************************************************/ + +void +UtDisplaySummary ( + UINT32 FileId) +{ + UINT32 i; + + + if (FileId != ASL_FILE_STDOUT) + { + /* Compiler name and version number */ + + FlPrintFile (FileId, "%s version %X%s [%s]\n\n", + ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH, __DATE__); + } + + /* Summary of main input and output files */ + + if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) + { + FlPrintFile (FileId, + "%-14s %s - %u lines, %u bytes, %u fields\n", + "Table Input:", + Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, + Gbl_InputByteCount, Gbl_InputFieldCount); + + if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) + { + FlPrintFile (FileId, + "%-14s %s - %u bytes\n", + "Binary Output:", + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength); + } + } + else + { + FlPrintFile (FileId, + "%-14s %s - %u lines, %u bytes, %u keywords\n", + "ASL Input:", + Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, + Gbl_InputByteCount, TotalKeywords); + + /* AML summary */ + + if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) + { + FlPrintFile (FileId, + "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n", + "AML Output:", + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength, + TotalNamedObjects, TotalExecutableOpcodes); + } + } + + /* Display summary of any optional files */ + + for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++) + { + if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle) + { + continue; + } + + /* .SRC is a temp file unless specifically requested */ + + if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag)) + { + continue; + } + + FlPrintFile (FileId, "%14s %s - %u bytes\n", + AslFileTypeNames [i], + Gbl_Files[i].Filename, FlGetFileSize (i)); + } + + /* Error summary */ + + FlPrintFile (FileId, + "\nCompilation complete. %u Errors, %u Warnings, %u Remarks", + Gbl_ExceptionCount[ASL_ERROR], + Gbl_ExceptionCount[ASL_WARNING] + + Gbl_ExceptionCount[ASL_WARNING2] + + Gbl_ExceptionCount[ASL_WARNING3], + Gbl_ExceptionCount[ASL_REMARK]); + + if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA) + { + FlPrintFile (FileId, + ", %u Optimizations", Gbl_ExceptionCount[ASL_OPTIMIZATION]); + } + + FlPrintFile (FileId, "\n"); +} + + +/******************************************************************************* + * + * FUNCTION: UtDisplaySummary + * + * PARAMETERS: Op - Integer parse node + * LowValue - Smallest allowed value + * HighValue - Largest allowed value + * + * RETURN: Op if OK, otherwise NULL + * + * DESCRIPTION: Check integer for an allowable range + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +UtCheckIntegerRange ( + ACPI_PARSE_OBJECT *Op, + UINT32 LowValue, + UINT32 HighValue) +{ + char *ParseError = NULL; + char Buffer[64]; + + + if (!Op) + { + return NULL; + } + + if (Op->Asl.Value.Integer < LowValue) + { + ParseError = "Value below valid range"; + Op->Asl.Value.Integer = LowValue; + } + + if (Op->Asl.Value.Integer > HighValue) + { + ParseError = "Value above valid range"; + Op->Asl.Value.Integer = HighValue; + } + + if (ParseError) + { + sprintf (Buffer, "%s 0x%X-0x%X", ParseError, LowValue, HighValue); + AslCompilererror (Buffer); + + return NULL; + } + + return Op; +} + + +/******************************************************************************* + * + * FUNCTION: UtGetStringBuffer + * + * PARAMETERS: Length - Size of buffer requested + * + * RETURN: Pointer to the buffer. Aborts on allocation failure + * + * DESCRIPTION: Allocate a string buffer. Bypass the local + * dynamic memory manager for performance reasons (This has a + * major impact on the speed of the compiler.) + * + ******************************************************************************/ + +char * +UtGetStringBuffer ( + UINT32 Length) +{ + char *Buffer; + + + if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast) + { + Gbl_StringCacheNext = UtLocalCalloc (ASL_STRING_CACHE_SIZE + Length); + Gbl_StringCacheLast = Gbl_StringCacheNext + ASL_STRING_CACHE_SIZE + + Length; + } + + Buffer = Gbl_StringCacheNext; + Gbl_StringCacheNext += Length; + + return (Buffer); +} + + +/******************************************************************************* + * + * FUNCTION: UtInternalizeName + * + * PARAMETERS: ExternalName - Name to convert + * ConvertedName - Where the converted name is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name + * + ******************************************************************************/ + +ACPI_STATUS +UtInternalizeName ( + char *ExternalName, + char **ConvertedName) +{ + ACPI_NAMESTRING_INFO Info; + ACPI_STATUS Status; + + + if (!ExternalName) + { + return (AE_OK); + } + + /* Get the length of the new internal name */ + + Info.ExternalName = ExternalName; + AcpiNsGetInternalNameLength (&Info); + + /* We need a segment to store the internal name */ + + Info.InternalName = UtGetStringBuffer (Info.Length); + if (!Info.InternalName) + { + return (AE_NO_MEMORY); + } + + /* Build the name */ + + Status = AcpiNsBuildInternalName (&Info); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *ConvertedName = Info.InternalName; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: UtPadNameWithUnderscores + * + * PARAMETERS: NameSeg - Input nameseg + * PaddedNameSeg - Output padded nameseg + * + * RETURN: Padded nameseg. + * + * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full + * ACPI_NAME. + * + ******************************************************************************/ + +static void +UtPadNameWithUnderscores ( + char *NameSeg, + char *PaddedNameSeg) +{ + UINT32 i; + + + for (i = 0; (i < ACPI_NAME_SIZE); i++) + { + if (*NameSeg) + { + *PaddedNameSeg = *NameSeg; + NameSeg++; + } + else + { + *PaddedNameSeg = '_'; + } + PaddedNameSeg++; + } +} + + +/******************************************************************************* + * + * FUNCTION: UtAttachNameseg + * + * PARAMETERS: Op - Parent parse node + * Name - Full ExternalName + * + * RETURN: None; Sets the NameSeg field in parent node + * + * DESCRIPTION: Extract the last nameseg of the ExternalName and store it + * in the NameSeg field of the Op. + * + ******************************************************************************/ + +static void +UtAttachNameseg ( + ACPI_PARSE_OBJECT *Op, + char *Name) +{ + char *NameSeg; + char PaddedNameSeg[4]; + + + if (!Name) + { + return; + } + + /* Look for the last dot in the namepath */ + + NameSeg = strrchr (Name, '.'); + if (NameSeg) + { + /* Found last dot, we have also found the final nameseg */ + + NameSeg++; + UtPadNameWithUnderscores (NameSeg, PaddedNameSeg); + } + else + { + /* No dots in the namepath, there is only a single nameseg. */ + /* Handle prefixes */ + + while ((*Name == '\\') || (*Name == '^')) + { + Name++; + } + + /* Remaing string should be one single nameseg */ + + UtPadNameWithUnderscores (Name, PaddedNameSeg); + } + + strncpy (Op->Asl.NameSeg, PaddedNameSeg, 4); +} + + +/******************************************************************************* + * + * FUNCTION: UtAttachNamepathToOwner + * + * PARAMETERS: Op - Parent parse node + * NameOp - Node that contains the name + * + * RETURN: Sets the ExternalName and Namepath in the parent node + * + * DESCRIPTION: Store the name in two forms in the parent node: The original + * (external) name, and the internalized name that is used within + * the ACPI namespace manager. + * + ******************************************************************************/ + +void +UtAttachNamepathToOwner ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *NameOp) +{ + ACPI_STATUS Status; + + + /* Full external path */ + + Op->Asl.ExternalName = NameOp->Asl.Value.String; + + /* Save the NameOp for possible error reporting later */ + + Op->Asl.ParentMethod = (void *) NameOp; + + /* Last nameseg of the path */ + + UtAttachNameseg (Op, Op->Asl.ExternalName); + + /* Create internalized path */ + + Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath); + if (ACPI_FAILURE (Status)) + { + /* TBD: abort on no memory */ + } +} + + +/******************************************************************************* + * + * FUNCTION: UtDoConstant + * + * PARAMETERS: String - Hex, Octal, or Decimal string + * + * RETURN: Converted Integer + * + * DESCRIPTION: Convert a string to an integer. With error checking. + * + ******************************************************************************/ + +UINT64 +UtDoConstant ( + char *String) +{ + ACPI_STATUS Status; + UINT64 Converted; + char ErrBuf[64]; + + + Status = UtStrtoul64 (String, 0, &Converted); + if (ACPI_FAILURE (Status)) + { + sprintf (ErrBuf, "%s %s\n", "Conversion error:", + AcpiFormatException (Status)); + AslCompilererror (ErrBuf); + } + + return (Converted); +} + + +/* TBD: use version in ACPI CA main code base? */ + +/******************************************************************************* + * + * FUNCTION: UtStrtoul64 + * + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte is + * returned + * Base - Radix of the string + * + * RETURN: Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. + * + ******************************************************************************/ + +ACPI_STATUS +UtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger) +{ + UINT32 Index; + UINT32 Sign; + UINT64 ReturnValue = 0; + ACPI_STATUS Status = AE_OK; + + + *RetInteger = 0; + + switch (Base) + { + case 0: + case 8: + case 10: + case 16: + break; + + default: + /* + * The specified Base parameter is not in the domain of + * this function: + */ + return (AE_BAD_PARAMETER); + } + + /* Skip over any white space in the buffer: */ + + while (isspace ((int) *String) || *String == '\t') + { + ++String; + } + + /* + * The buffer may contain an optional plus or minus sign. + * If it does, then skip over it but remember what is was: + */ + if (*String == '-') + { + Sign = NEGATIVE; + ++String; + } + else if (*String == '+') + { + ++String; + Sign = POSITIVE; + } + else + { + Sign = POSITIVE; + } + + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (Base == 0) + { + if (*String == '0') + { + if (tolower ((int) *(++String)) == 'x') + { + Base = 16; + ++String; + } + else + { + Base = 8; + } + } + else + { + Base = 10; + } + } + + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (Base == 8 && *String == '0') + { + String++; + } + + if (Base == 16 && + *String == '0' && + tolower ((int) *(++String)) == 'x') + { + String++; + } + + /* Main loop: convert the string to an unsigned long */ + + while (*String) + { + if (isdigit ((int) *String)) + { + Index = ((UINT8) *String) - '0'; + } + else + { + Index = (UINT8) toupper ((int) *String); + if (isupper ((int) Index)) + { + Index = Index - 'A' + 10; + } + else + { + goto ErrorExit; + } + } + + if (Index >= Base) + { + goto ErrorExit; + } + + /* Check to see if value is out of range: */ + + if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) / + (UINT64) Base)) + { + goto ErrorExit; + } + else + { + ReturnValue *= Base; + ReturnValue += Index; + } + + ++String; + } + + + /* If a minus sign was present, then "the conversion is negated": */ + + if (Sign == NEGATIVE) + { + ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; + } + + *RetInteger = ReturnValue; + return (Status); + + +ErrorExit: + switch (Base) + { + case 8: + Status = AE_BAD_OCTAL_CONSTANT; + break; + + case 10: + Status = AE_BAD_DECIMAL_CONSTANT; + break; + + case 16: + Status = AE_BAD_HEX_CONSTANT; + break; + + default: + /* Base validated above */ + break; + } + + return (Status); +} + + diff --git a/source/compiler/asluuid.c b/source/compiler/asluuid.c new file mode 100644 index 000000000000..bb29a79bf1b6 --- /dev/null +++ b/source/compiler/asluuid.c @@ -0,0 +1,216 @@ +/****************************************************************************** + * + * Module Name: asluuid-- compiler UUID support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("asluuid") + + +/* + * UUID support functions. + * + * This table is used to convert an input UUID ascii string to a 16 byte + * buffer and the reverse. The table maps a UUID buffer index 0-15 to + * the index within the 36-byte UUID string where the associated 2-byte + * hex value can be found. + * + * 36-byte UUID strings are of the form: + * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + * Where aa-pp are one byte hex numbers, made up of two hex digits + * + * Note: This table is basically the inverse of the string-to-offset table + * found in the ACPI spec in the description of the ToUUID macro. + */ +static UINT8 Gbl_MapToUuidOffset[16] = +{ + 6,4,2,0,11,9,16,14,19,21,24,26,28,30,32,34 +}; + +#define UUID_BUFFER_LENGTH 16 +#define UUID_STRING_LENGTH 36 + +/* Positions for required hyphens (dashes) in UUID strings */ + +#define UUID_HYPHEN1_OFFSET 8 +#define UUID_HYPHEN2_OFFSET 13 +#define UUID_HYPHEN3_OFFSET 18 +#define UUID_HYPHEN4_OFFSET 23 + + +/******************************************************************************* + * + * FUNCTION: AuValiduateUuid + * + * PARAMETERS: InString - 36-byte formatted UUID string + * + * RETURN: Status + * + * DESCRIPTION: Check all 36 characters for correct format + * + ******************************************************************************/ + +ACPI_STATUS +AuValidateUuid ( + char *InString) +{ + UINT32 i; + + + if (!InString || (ACPI_STRLEN (InString) != UUID_STRING_LENGTH)) + { + return (AE_BAD_PARAMETER); + } + + /* Check all 36 characters for correct format */ + + for (i = 0; i < UUID_STRING_LENGTH; i++) + { + /* Must have 4 hyphens (dashes) in these positions: */ + + if ((i == UUID_HYPHEN1_OFFSET) || + (i == UUID_HYPHEN2_OFFSET) || + (i == UUID_HYPHEN3_OFFSET) || + (i == UUID_HYPHEN4_OFFSET)) + { + if (InString[i] != '-') + { + return (AE_BAD_PARAMETER); + } + } + + /* All other positions must contain hex digits */ + + else + { + if (!isxdigit ((int) InString[i])) + { + return (AE_BAD_PARAMETER); + } + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AuConvertStringToUuid + * + * PARAMETERS: InString - 36-byte formatted UUID string + * UuidBuffer - 16-byte UUID buffer + * + * RETURN: Status + * + * DESCRIPTION: Convert 36-byte formatted UUID string to 16-byte UUID buffer + * + ******************************************************************************/ + +ACPI_STATUS +AuConvertStringToUuid ( + char *InString, + char *UuidBuffer) +{ + UINT32 i; + + + if (!InString || !UuidBuffer) + { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) + { + UuidBuffer[i] = (char) (UtHexCharToValue (InString[Gbl_MapToUuidOffset[i]]) << 4); + UuidBuffer[i] |= (char) UtHexCharToValue (InString[Gbl_MapToUuidOffset[i] + 1]); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AuConvertUuidToString + * + * PARAMETERS: UuidBuffer - 16-byte UUID buffer + * OutString - 36-byte formatted UUID string + * + * RETURN: Status + * + * DESCRIPTION: Convert 16-byte UUID buffer to 36-byte formatted UUID string + * OutString must be 37 bytes to include null terminator. + * + ******************************************************************************/ + +ACPI_STATUS +AuConvertUuidToString ( + char *UuidBuffer, + char *OutString) +{ + UINT32 i; + + + if (!UuidBuffer || !OutString) + { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) + { + OutString[Gbl_MapToUuidOffset[i]] = (UINT8) AslHexLookup[(UuidBuffer[i] >> 4) & 0xF]; + OutString[Gbl_MapToUuidOffset[i] + 1] = (UINT8) AslHexLookup[UuidBuffer[i] & 0xF]; + } + + /* Insert required hyphens (dashes) */ + + OutString[UUID_HYPHEN1_OFFSET] = + OutString[UUID_HYPHEN2_OFFSET] = + OutString[UUID_HYPHEN3_OFFSET] = + OutString[UUID_HYPHEN4_OFFSET] = '-'; + + OutString[UUID_STRING_LENGTH] = 0; /* Null terminate */ + return (AE_OK); +} diff --git a/source/compiler/aslwalks.c b/source/compiler/aslwalks.c new file mode 100644 index 000000000000..d98806caa38a --- /dev/null +++ b/source/compiler/aslwalks.c @@ -0,0 +1,1237 @@ +/****************************************************************************** + * + * Module Name: aslwalks.c - major analytical parse tree walks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "acparser.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslwalks") + + +/******************************************************************************* + * + * FUNCTION: AnMethodAnalysisWalkBegin + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback for the analysis walk. Check methods for: + * 1) Initialized local variables + * 2) Valid arguments + * 3) Return types + * + ******************************************************************************/ + +ACPI_STATUS +AnMethodAnalysisWalkBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; + ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; + ACPI_PARSE_OBJECT *Next; + UINT32 RegisterNumber; + UINT32 i; + char LocalName[] = "Local0"; + char ArgName[] = "Arg0"; + ACPI_PARSE_OBJECT *ArgNode; + ACPI_PARSE_OBJECT *NextType; + ACPI_PARSE_OBJECT *NextParamType; + UINT8 ActualArgs = 0; + + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_METHOD: + + TotalMethods++; + + /* Create and init method info */ + + MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); + MethodInfo->Next = WalkInfo->MethodStack; + MethodInfo->Op = Op; + + WalkInfo->MethodStack = MethodInfo; + + /* Get the name node, ignored here */ + + Next = Op->Asl.Child; + + /* Get the NumArguments node */ + + Next = Next->Asl.Next; + MethodInfo->NumArguments = (UINT8) + (((UINT8) Next->Asl.Value.Integer) & 0x07); + + /* Get the SerializeRule and SyncLevel nodes, ignored here */ + + Next = Next->Asl.Next; + Next = Next->Asl.Next; + ArgNode = Next; + + /* Get the ReturnType node */ + + Next = Next->Asl.Next; + + NextType = Next->Asl.Child; + while (NextType) + { + /* Get and map each of the ReturnTypes */ + + MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); + NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + NextType = NextType->Asl.Next; + } + + /* Get the ParameterType node */ + + Next = Next->Asl.Next; + + NextType = Next->Asl.Child; + while (NextType) + { + if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) + { + NextParamType = NextType->Asl.Child; + while (NextParamType) + { + MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); + NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + NextParamType = NextParamType->Asl.Next; + } + } + else + { + MethodInfo->ValidArgTypes[ActualArgs] = + AnMapObjTypeToBtype (NextType); + NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; + ActualArgs++; + } + + NextType = NextType->Asl.Next; + } + + if ((MethodInfo->NumArguments) && + (MethodInfo->NumArguments != ActualArgs)) + { + /* error: Param list did not match number of args */ + } + + /* Allow numarguments == 0 for Function() */ + + if ((!MethodInfo->NumArguments) && (ActualArgs)) + { + MethodInfo->NumArguments = ActualArgs; + ArgNode->Asl.Value.Integer |= ActualArgs; + } + + /* + * Actual arguments are initialized at method entry. + * All other ArgX "registers" can be used as locals, so we + * track their initialization. + */ + for (i = 0; i < MethodInfo->NumArguments; i++) + { + MethodInfo->ArgInitialized[i] = TRUE; + } + break; + + + case PARSEOP_METHODCALL: + + if (MethodInfo && + (Op->Asl.Node == MethodInfo->Op->Asl.Node)) + { + AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); + } + break; + + + case PARSEOP_LOCAL0: + case PARSEOP_LOCAL1: + case PARSEOP_LOCAL2: + case PARSEOP_LOCAL3: + case PARSEOP_LOCAL4: + case PARSEOP_LOCAL5: + case PARSEOP_LOCAL6: + case PARSEOP_LOCAL7: + + if (!MethodInfo) + { + /* + * Local was used outside a control method, or there was an error + * in the method declaration. + */ + AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); + return (AE_ERROR); + } + + RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); + + /* + * If the local is being used as a target, mark the local + * initialized + */ + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + MethodInfo->LocalInitialized[RegisterNumber] = TRUE; + } + + /* + * Otherwise, this is a reference, check if the local + * has been previously initialized. + * + * The only operator that accepts an uninitialized value is ObjectType() + */ + else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && + (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) + { + LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); + AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); + } + break; + + + case PARSEOP_ARG0: + case PARSEOP_ARG1: + case PARSEOP_ARG2: + case PARSEOP_ARG3: + case PARSEOP_ARG4: + case PARSEOP_ARG5: + case PARSEOP_ARG6: + + if (!MethodInfo) + { + /* + * Arg was used outside a control method, or there was an error + * in the method declaration. + */ + AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); + return (AE_ERROR); + } + + RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; + ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); + + /* + * If the Arg is being used as a target, mark the local + * initialized + */ + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + MethodInfo->ArgInitialized[RegisterNumber] = TRUE; + } + + /* + * Otherwise, this is a reference, check if the Arg + * has been previously initialized. + * + * The only operator that accepts an uninitialized value is ObjectType() + */ + else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && + (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) + { + AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); + } + + /* Flag this arg if it is not a "real" argument to the method */ + + if (RegisterNumber >= MethodInfo->NumArguments) + { + AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); + } + break; + + + case PARSEOP_RETURN: + + if (!MethodInfo) + { + /* + * Probably was an error in the method declaration, + * no additional error here + */ + ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); + return (AE_ERROR); + } + + /* + * A child indicates a possible return value. A simple Return or + * Return() is marked with NODE_IS_NULL_RETURN by the parser so + * that it is not counted as a "real" return-with-value, although + * the AML code that is actually emitted is Return(0). The AML + * definition of Return has a required parameter, so we are + * forced to convert a null return to Return(0). + */ + if ((Op->Asl.Child) && + (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) + { + MethodInfo->NumReturnWithValue++; + } + else + { + MethodInfo->NumReturnNoValue++; + } + break; + + + case PARSEOP_BREAK: + case PARSEOP_CONTINUE: + + Next = Op->Asl.Parent; + while (Next) + { + if (Next->Asl.ParseOpcode == PARSEOP_WHILE) + { + break; + } + Next = Next->Asl.Parent; + } + + if (!Next) + { + AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); + } + break; + + + case PARSEOP_STALL: + + /* We can range check if the argument is an integer */ + + if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && + (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); + } + break; + + + case PARSEOP_DEVICE: + case PARSEOP_EVENT: + case PARSEOP_MUTEX: + case PARSEOP_OPERATIONREGION: + case PARSEOP_POWERRESOURCE: + case PARSEOP_PROCESSOR: + case PARSEOP_THERMALZONE: + + /* + * The first operand is a name to be created in the namespace. + * Check against the reserved list. + */ + i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); + if (i < ACPI_VALID_RESERVED_NAME_MAX) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); + } + break; + + + case PARSEOP_NAME: + + /* Typecheck any predefined names statically defined with Name() */ + + ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); + + /* Special typechecking for _HID */ + + if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) + { + Next = Op->Asl.Child->Asl.Next; + AnCheckId (Next, ASL_TYPE_HID); + } + + /* Special typechecking for _CID */ + + else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) + { + Next = Op->Asl.Child->Asl.Next; + + if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || + (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) + { + Next = Next->Asl.Child; + while (Next) + { + AnCheckId (Next, ASL_TYPE_CID); + Next = Next->Asl.Next; + } + } + else + { + AnCheckId (Next, ASL_TYPE_CID); + } + } + break; + + + default: + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AnMethodAnalysisWalkEnd + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback for analysis walk. Complete method + * return analysis. + * + ******************************************************************************/ + +ACPI_STATUS +AnMethodAnalysisWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; + ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; + + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_METHOD: + case PARSEOP_RETURN: + if (!MethodInfo) + { + printf ("No method info for method! [%s]\n", Op->Asl.Namepath); + AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, + "No method info for this method"); + + CmCleanupAndExit (); + return (AE_AML_INTERNAL); + } + break; + + default: + break; + } + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_METHOD: + + WalkInfo->MethodStack = MethodInfo->Next; + + /* + * Check if there is no return statement at the end of the + * method AND we can actually get there -- i.e., the execution + * of the method can possibly terminate without a return statement. + */ + if ((!AnLastStatementIsReturn (Op)) && + (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) + { + /* + * No return statement, and execution can possibly exit + * via this path. This is equivalent to Return () + */ + MethodInfo->NumReturnNoValue++; + } + + /* + * Check for case where some return statements have a return value + * and some do not. Exit without a return statement is a return with + * no value + */ + if (MethodInfo->NumReturnNoValue && + MethodInfo->NumReturnWithValue) + { + AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, + Op->Asl.ExternalName); + } + + /* + * If there are any RETURN() statements with no value, or there is a + * control path that allows the method to exit without a return value, + * we mark the method as a method that does not return a value. This + * knowledge can be used to check method invocations that expect a + * returned value. + */ + if (MethodInfo->NumReturnNoValue) + { + if (MethodInfo->NumReturnWithValue) + { + Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; + } + else + { + Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; + } + } + + /* + * Check predefined method names for correct return behavior + * and correct number of arguments. Also, some special checks + * For GPE and _REG methods. + */ + if (ApCheckForPredefinedMethod (Op, MethodInfo)) + { + /* Special check for two names like _L01 and _E01 in same scope */ + + ApCheckForGpeNameConflict (Op); + + /* + * Special check for _REG: Must have an operation region definition + * within the same scope! + */ + ApCheckRegMethod (Op); + } + + ACPI_FREE (MethodInfo); + break; + + + case PARSEOP_NAME: + + /* Special check for two names like _L01 and _E01 in same scope */ + + ApCheckForGpeNameConflict (Op); + break; + + + case PARSEOP_RETURN: + + /* + * If the parent is a predefined method name, attempt to typecheck + * the return value. Only static types can be validated. + */ + ApCheckPredefinedReturnValue (Op, MethodInfo); + + /* + * The parent block does not "exit" and continue execution -- the + * method is terminated here with the Return() statement. + */ + Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; + + /* Used in the "typing" pass later */ + + Op->Asl.ParentMethod = MethodInfo->Op; + + /* + * If there is a peer node after the return statement, then this + * node is unreachable code -- i.e., it won't be executed because of + * the preceeding Return() statement. + */ + if (Op->Asl.Next) + { + AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); + } + break; + + + case PARSEOP_IF: + + if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && + (Op->Asl.Next) && + (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) + { + /* + * This IF has a corresponding ELSE. The IF block has no exit, + * (it contains an unconditional Return) + * mark the ELSE block to remember this fact. + */ + Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; + } + break; + + + case PARSEOP_ELSE: + + if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && + (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) + { + /* + * This ELSE block has no exit and the corresponding IF block + * has no exit either. Therefore, the parent node has no exit. + */ + Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; + } + break; + + + default: + + if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && + (Op->Asl.Parent)) + { + /* If this node has no exit, then the parent has no exit either */ + + Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; + } + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AnMethodTypingWalkEnd + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback for typing walk. Complete the method + * return analysis. Check methods for: + * 1) Initialized local variables + * 2) Valid arguments + * 3) Return types + * + ******************************************************************************/ + +ACPI_STATUS +AnMethodTypingWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + UINT32 ThisNodeBtype; + + + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_METHOD: + + Op->Asl.CompileFlags |= NODE_METHOD_TYPED; + break; + + case PARSEOP_RETURN: + + if ((Op->Asl.Child) && + (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) + { + ThisNodeBtype = AnGetBtype (Op->Asl.Child); + + if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && + (ThisNodeBtype == (ACPI_UINT32_MAX -1))) + { + /* + * The called method is untyped at this time (typically a + * forward reference). + * + * Check for a recursive method call first. + */ + if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) + { + /* We must type the method here */ + + TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, + ASL_WALK_VISIT_UPWARD, NULL, + AnMethodTypingWalkEnd, NULL); + + ThisNodeBtype = AnGetBtype (Op->Asl.Child); + } + } + + /* Returns a value, save the value type */ + + if (Op->Asl.ParentMethod) + { + Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; + } + } + break; + + default: + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AnOperandTypecheckWalkEnd + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback for analysis walk. Complete method + * return analysis. + * + ******************************************************************************/ + +ACPI_STATUS +AnOperandTypecheckWalkEnd ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + const ACPI_OPCODE_INFO *OpInfo; + UINT32 RuntimeArgTypes; + UINT32 RuntimeArgTypes2; + UINT32 RequiredBtypes; + UINT32 ThisNodeBtype; + UINT32 CommonBtypes; + UINT32 OpcodeClass; + ACPI_PARSE_OBJECT *ArgOp; + UINT32 ArgType; + + + switch (Op->Asl.AmlOpcode) + { + case AML_RAW_DATA_BYTE: + case AML_RAW_DATA_WORD: + case AML_RAW_DATA_DWORD: + case AML_RAW_DATA_QWORD: + case AML_RAW_DATA_BUFFER: + case AML_RAW_DATA_CHAIN: + case AML_PACKAGE_LENGTH: + case AML_UNASSIGNED_OPCODE: + case AML_DEFAULT_ARG_OP: + + /* Ignore the internal (compiler-only) AML opcodes */ + + return (AE_OK); + + default: + break; + } + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + if (!OpInfo) + { + return (AE_OK); + } + + ArgOp = Op->Asl.Child; + RuntimeArgTypes = OpInfo->RuntimeArgs; + OpcodeClass = OpInfo->Class; + +#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE + /* + * Update 11/2008: In practice, we can't perform this check. A simple + * analysis is not sufficient. Also, it can cause errors when compiling + * disassembled code because of the way Switch operators are implemented + * (a While(One) loop with a named temp variable created within.) + */ + + /* + * If we are creating a named object, check if we are within a while loop + * by checking if the parent is a WHILE op. This is a simple analysis, but + * probably sufficient for many cases. + * + * Allow Scope(), Buffer(), and Package(). + */ + if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || + ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) + { + if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) + { + AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); + } + } +#endif + + /* + * Special case for control opcodes IF/RETURN/WHILE since they + * have no runtime arg list (at this time) + */ + switch (Op->Asl.AmlOpcode) + { + case AML_IF_OP: + case AML_WHILE_OP: + case AML_RETURN_OP: + + if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) + { + /* Check for an internal method */ + + if (AnIsInternalMethod (ArgOp)) + { + return (AE_OK); + } + + /* The lone arg is a method call, check it */ + + RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); + if (Op->Asl.AmlOpcode == AML_RETURN_OP) + { + RequiredBtypes = 0xFFFFFFFF; + } + + ThisNodeBtype = AnGetBtype (ArgOp); + if (ThisNodeBtype == ACPI_UINT32_MAX) + { + return (AE_OK); + } + AnCheckMethodReturnValue (Op, OpInfo, ArgOp, + RequiredBtypes, ThisNodeBtype); + } + return (AE_OK); + + default: + break; + } + + /* Ignore the non-executable opcodes */ + + if (RuntimeArgTypes == ARGI_INVALID_OPCODE) + { + return (AE_OK); + } + + switch (OpcodeClass) + { + case AML_CLASS_EXECUTE: + case AML_CLASS_CREATE: + case AML_CLASS_CONTROL: + case AML_CLASS_RETURN_VALUE: + + /* TBD: Change class or fix typechecking for these */ + + if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || + (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || + (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) + { + break; + } + + /* Reverse the runtime argument list */ + + RuntimeArgTypes2 = 0; + while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) + { + RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; + RuntimeArgTypes2 |= ArgType; + INCREMENT_ARG_LIST (RuntimeArgTypes); + } + + while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) + { + RequiredBtypes = AnMapArgTypeToBtype (ArgType); + + ThisNodeBtype = AnGetBtype (ArgOp); + if (ThisNodeBtype == ACPI_UINT32_MAX) + { + goto NextArgument; + } + + /* Examine the arg based on the required type of the arg */ + + switch (ArgType) + { + case ARGI_TARGETREF: + + if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) + { + /* ZERO is the placeholder for "don't store result" */ + + ThisNodeBtype = RequiredBtypes; + break; + } + + if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) + { + /* + * This is the case where an original reference to a resource + * descriptor field has been replaced by an (Integer) offset. + * These named fields are supported at compile-time only; + * the names are not passed to the interpreter (via the AML). + */ + if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || + (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); + } + else + { + AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); + } + break; + } + + if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || + (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) + { + break; + } + + ThisNodeBtype = RequiredBtypes; + break; + + + case ARGI_REFERENCE: /* References */ + case ARGI_INTEGER_REF: + case ARGI_OBJECT_REF: + case ARGI_DEVICE_REF: + + switch (ArgOp->Asl.ParseOpcode) + { + case PARSEOP_LOCAL0: + case PARSEOP_LOCAL1: + case PARSEOP_LOCAL2: + case PARSEOP_LOCAL3: + case PARSEOP_LOCAL4: + case PARSEOP_LOCAL5: + case PARSEOP_LOCAL6: + case PARSEOP_LOCAL7: + + /* TBD: implement analysis of current value (type) of the local */ + /* For now, just treat any local as a typematch */ + + /*ThisNodeBtype = RequiredBtypes;*/ + break; + + case PARSEOP_ARG0: + case PARSEOP_ARG1: + case PARSEOP_ARG2: + case PARSEOP_ARG3: + case PARSEOP_ARG4: + case PARSEOP_ARG5: + case PARSEOP_ARG6: + + /* Hard to analyze argument types, sow we won't */ + /* For now, just treat any arg as a typematch */ + + /* ThisNodeBtype = RequiredBtypes; */ + break; + + case PARSEOP_DEBUG: + break; + + case PARSEOP_REFOF: + case PARSEOP_INDEX: + default: + break; + + } + break; + + case ARGI_INTEGER: + default: + break; + } + + + CommonBtypes = ThisNodeBtype & RequiredBtypes; + + if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) + { + if (AnIsInternalMethod (ArgOp)) + { + return (AE_OK); + } + + /* Check a method call for a valid return value */ + + AnCheckMethodReturnValue (Op, OpInfo, ArgOp, + RequiredBtypes, ThisNodeBtype); + } + + /* + * Now check if the actual type(s) match at least one + * bit to the required type + */ + else if (!CommonBtypes) + { + /* No match -- this is a type mismatch error */ + + AnFormatBtype (StringBuffer, ThisNodeBtype); + AnFormatBtype (StringBuffer2, RequiredBtypes); + + sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", + StringBuffer, OpInfo->Name, StringBuffer2); + + AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); + } + + NextArgument: + ArgOp = ArgOp->Asl.Next; + INCREMENT_ARG_LIST (RuntimeArgTypes2); + } + break; + + default: + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AnOtherSemanticAnalysisWalkBegin + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Descending callback for the analysis walk. Checks for + * miscellaneous issues in the code. + * + ******************************************************************************/ + +ACPI_STATUS +AnOtherSemanticAnalysisWalkBegin ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_PARSE_OBJECT *ArgNode; + ACPI_PARSE_OBJECT *PrevArgNode = NULL; + const ACPI_OPCODE_INFO *OpInfo; + ACPI_NAMESPACE_NODE *Node; + + + OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + + /* + * Determine if an execution class operator actually does something by + * checking if it has a target and/or the function return value is used. + * (Target is optional, so a standalone statement can actually do nothing.) + */ + if ((OpInfo->Class == AML_CLASS_EXECUTE) && + (OpInfo->Flags & AML_HAS_RETVAL) && + (!AnIsResultUsed (Op))) + { + if (OpInfo->Flags & AML_HAS_TARGET) + { + /* + * Find the target node, it is always the last child. If the traget + * is not specified in the ASL, a default node of type Zero was + * created by the parser. + */ + ArgNode = Op->Asl.Child; + while (ArgNode->Asl.Next) + { + PrevArgNode = ArgNode; + ArgNode = ArgNode->Asl.Next; + } + + /* Divide() is the only weird case, it has two targets */ + + if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) + { + if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && + (PrevArgNode) && + (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) + { + AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, + Op, Op->Asl.ExternalName); + } + } + else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) + { + AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, + Op, Op->Asl.ExternalName); + } + } + else + { + /* + * Has no target and the result is not used. Only a couple opcodes + * can have this combination. + */ + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_ACQUIRE: + case PARSEOP_WAIT: + case PARSEOP_LOADTABLE: + break; + + default: + AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, + Op, Op->Asl.ExternalName); + break; + } + } + } + + + /* + * Semantic checks for individual ASL operators + */ + switch (Op->Asl.ParseOpcode) + { + case PARSEOP_ACQUIRE: + case PARSEOP_WAIT: + /* + * Emit a warning if the timeout parameter for these operators is not + * ACPI_WAIT_FOREVER, and the result value from the operator is not + * checked, meaning that a timeout could happen, but the code + * would not know about it. + */ + + /* First child is the namepath, 2nd child is timeout */ + + ArgNode = Op->Asl.Child; + ArgNode = ArgNode->Asl.Next; + + /* + * Check for the WAIT_FOREVER case - defined by the ACPI spec to be + * 0xFFFF or greater + */ + if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || + (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && + (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) + { + break; + } + + /* + * The operation could timeout. If the return value is not used + * (indicates timeout occurred), issue a warning + */ + if (!AnIsResultUsed (Op)) + { + AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, + Op->Asl.ExternalName); + } + break; + + case PARSEOP_CREATEFIELD: + /* + * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand + */ + ArgNode = Op->Asl.Child; + ArgNode = ArgNode->Asl.Next; + ArgNode = ArgNode->Asl.Next; + + if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || + ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && + (ArgNode->Asl.Value.Integer == 0))) + { + AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); + } + break; + + case PARSEOP_CONNECTION: + /* + * Ensure that the referenced operation region has the correct SPACE_ID. + * From the grammar/parser, we know the parent is a FIELD definition. + */ + ArgNode = Op->Asl.Parent; /* Field definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + Node = ArgNode->Asl.Node; /* OpRegion namespace node */ + + ArgNode = Node->Op; /* OpRegion definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ + + /* + * The Connection() operator is only valid for the following operation + * region SpaceIds: GeneralPurposeIo and GenericSerialBus. + */ + if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && + (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) + { + AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); + } + break; + + case PARSEOP_FIELD: + /* + * Ensure that fields for GeneralPurposeIo and GenericSerialBus + * contain at least one Connection() operator + */ + ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ + Node = ArgNode->Asl.Node; /* OpRegion namespace node */ + if (!Node) + { + break; + } + + ArgNode = Node->Op; /* OpRegion definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ + + /* We are only interested in GeneralPurposeIo and GenericSerialBus */ + + if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && + (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) + { + break; + } + + ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* AccessType */ + ArgNode = ArgNode->Asl.Next; /* LockRule */ + ArgNode = ArgNode->Asl.Next; /* UpdateRule */ + ArgNode = ArgNode->Asl.Next; /* Start of FieldUnitList */ + + /* Walk the FieldUnitList */ + + while (ArgNode) + { + if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION) + { + break; + } + else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG) + { + AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL); + break; + } + + ArgNode = ArgNode->Asl.Next; + } + break; + + default: + break; + } + + return (AE_OK); +} diff --git a/source/compiler/dtcompile.c b/source/compiler/dtcompile.c new file mode 100644 index 000000000000..78a6d3dcb229 --- /dev/null +++ b/source/compiler/dtcompile.c @@ -0,0 +1,589 @@ +/****************************************************************************** + * + * Module Name: dtcompile.c - Front-end for data table compiler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTCOMPILE_C__ +#define _DECLARE_DT_GLOBALS + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtcompile") + +static char VersionString[9]; + + +/* Local prototypes */ + +static ACPI_STATUS +DtInitialize ( + void); + +static ACPI_STATUS +DtCompileDataTable ( + DT_FIELD **Field); + +static void +DtInsertCompilerIds ( + DT_FIELD *FieldList); + + +/****************************************************************************** + * + * FUNCTION: DtDoCompile + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Main entry point for the data table compiler. + * + * Note: Assumes Gbl_Files[ASL_FILE_INPUT] is initialized and the file is + * open at seek offset zero. + * + *****************************************************************************/ + +ACPI_STATUS +DtDoCompile ( + void) +{ + ACPI_STATUS Status; + UINT8 Event; + DT_FIELD *FieldList; + + + /* Initialize globals */ + + Status = DtInitialize (); + if (ACPI_FAILURE (Status)) + { + printf ("Error during compiler initialization, 0x%X\n", Status); + return (Status); + } + + /* + * Scan the input file (file is already open) and + * build the parse tree + */ + Event = UtBeginEvent ("Scan and parse input file"); + FieldList = DtScanFile (Gbl_Files[ASL_FILE_INPUT].Handle); + UtEndEvent (Event); + + /* Did the parse tree get successfully constructed? */ + + if (!FieldList) + { + /* TBD: temporary error message. Msgs should come from function above */ + + DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, + "Input file does not appear to be an ASL or data table source file"); + + Status = AE_ERROR; + goto CleanupAndExit; + } + + Event = UtBeginEvent ("Compile parse tree"); + + /* + * Compile the parse tree + */ + Status = DtCompileDataTable (&FieldList); + UtEndEvent (Event); + + DtFreeFieldList (); + + if (ACPI_FAILURE (Status)) + { + /* TBD: temporary error message. Msgs should come from function above */ + + DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, + "Could not compile input file"); + + goto CleanupAndExit; + } + + /* Create/open the binary output file */ + + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL; + Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); + if (ACPI_FAILURE (Status)) + { + goto CleanupAndExit; + } + + /* Write the binary, then the optional hex file */ + + DtOutputBinary (Gbl_RootTable); + LsDoHexOutput (); + DtWriteTableToListing (); + +CleanupAndExit: + + CmCleanupAndExit (); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize data table compiler globals. Enables multiple + * compiles per invocation. + * + *****************************************************************************/ + +static ACPI_STATUS +DtInitialize ( + void) +{ + ACPI_STATUS Status; + + + Status = AcpiOsInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtInitGlobals (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Gbl_FieldList = NULL; + Gbl_RootTable = NULL; + Gbl_SubtableStack = NULL; + + sprintf (VersionString, "%X", (UINT32) ACPI_CA_VERSION); + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtInsertCompilerIds + * + * PARAMETERS: FieldList - Current field list pointer + * + * RETURN: None + * + * DESCRIPTION: Insert the IDs (Name, Version) of the current compiler into + * the original ACPI table header. + * + *****************************************************************************/ + +static void +DtInsertCompilerIds ( + DT_FIELD *FieldList) +{ + DT_FIELD *Next; + UINT32 i; + + + /* + * Don't insert current compiler ID if requested. Used for compiler + * debug/validation only. + */ + if (Gbl_UseOriginalCompilerId) + { + return; + } + + /* Walk to the Compiler fields at the end of the header */ + + Next = FieldList; + for (i = 0; i < 7; i++) + { + Next = Next->Next; + } + + Next->Value = ASL_CREATOR_ID; + Next->Flags = DT_FIELD_NOT_ALLOCATED; + + Next = Next->Next; + Next->Value = VersionString; + Next->Flags = DT_FIELD_NOT_ALLOCATED; +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileDataTable + * + * PARAMETERS: FieldList - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Entry point to compile one data table + * + *****************************************************************************/ + +static ACPI_STATUS +DtCompileDataTable ( + DT_FIELD **FieldList) +{ + ACPI_DMTABLE_DATA *TableData; + DT_SUBTABLE *Subtable; + char *Signature; + ACPI_TABLE_HEADER *AcpiTableHeader; + ACPI_STATUS Status; + + + /* Verify that we at least have a table signature and save it */ + + Signature = DtGetFieldValue (*FieldList); + if (!Signature) + { + sprintf (MsgBuffer, "Expected \"%s\"", "Signature"); + DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME, + *FieldList, MsgBuffer); + return (AE_ERROR); + } + + Gbl_Signature = UtLocalCalloc (ACPI_STRLEN (Signature) + 1); + strcpy (Gbl_Signature, Signature); + + /* + * Handle tables that don't use the common ACPI table header structure. + * Currently, these are the FACS and RSDP. Also check for an OEMx table, + * these tables have user-defined contents. + */ + if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) + { + Status = DtCompileFacs (FieldList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtSetTableLength (); + return (Status); + } + else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDP)) + { + Status = DtCompileRsdp (FieldList); + return (Status); + } + else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_S3PT)) + { + Status = DtCompileS3pt (FieldList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtSetTableLength (); + return (Status); + } + + /* + * All other tables must use the common ACPI table header. Insert the + * current iASL IDs (name, version), and compile the header now. + */ + DtInsertCompilerIds (*FieldList); + + Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader, + &Gbl_RootTable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtPushSubtable (Gbl_RootTable); + + /* Validate the signature via the ACPI table list */ + + TableData = AcpiDmGetTableData (Signature); + if (!TableData || Gbl_CompileGeneric) + { + DtCompileGeneric ((void **) FieldList); + goto Out; + } + + /* Dispatch to per-table compile */ + + if (TableData->CmTableHandler) + { + /* Complex table, has a handler */ + + Status = TableData->CmTableHandler ((void **) FieldList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else if (TableData->TableInfo) + { + /* Simple table, just walk the info table */ + + Subtable = NULL; + Status = DtCompileTable (FieldList, TableData->TableInfo, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (Gbl_RootTable, Subtable); + DtPopSubtable (); + } + else + { + DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList, + "Missing table dispatch info"); + return (AE_ERROR); + } + +Out: + /* Set the final table length and then the checksum */ + + DtSetTableLength (); + AcpiTableHeader = ACPI_CAST_PTR ( + ACPI_TABLE_HEADER, Gbl_RootTable->Buffer); + DtSetTableChecksum (&AcpiTableHeader->Checksum); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileTable + * + * PARAMETERS: Field - Current field list pointer + * Info - Info table for this ACPI table + * RetSubtable - Compile result of table + * Required - If this subtable must exist + * + * RETURN: Status + * + * DESCRIPTION: Compile a subtable + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileTable ( + DT_FIELD **Field, + ACPI_DMTABLE_INFO *Info, + DT_SUBTABLE **RetSubtable, + BOOLEAN Required) +{ + DT_FIELD *LocalField; + UINT32 Length; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *InlineSubtable; + UINT32 FieldLength = 0; + UINT8 FieldType; + UINT8 *Buffer; + UINT8 *FlagBuffer = NULL; + UINT32 CurrentFlagByteOffset = 0; + ACPI_STATUS Status; + + + if (!Field || !*Field) + { + return (AE_BAD_PARAMETER); + } + + Length = DtGetSubtableLength (*Field, Info); + if (Length == ASL_EOF) + { + return (AE_ERROR); + } + + Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); + + if (Length > 0) + { + Subtable->Buffer = UtLocalCalloc (Length); + } + Subtable->Length = Length; + Subtable->TotalLength = Length; + Buffer = Subtable->Buffer; + + LocalField = *Field; + + /* + * Main loop walks the info table for this ACPI table or subtable + */ + for (; Info->Name; Info++) + { + if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) + { + continue; + } + + if (!LocalField) + { + sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", + Info->Name); + DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); + Status = AE_BAD_DATA; + goto Error; + } + + /* Maintain table offsets */ + + LocalField->TableOffset = Gbl_CurrentTableOffset; + FieldLength = DtGetFieldLength (LocalField, Info); + Gbl_CurrentTableOffset += FieldLength; + + FieldType = DtGetFieldType (Info); + Gbl_InputFieldCount++; + + switch (FieldType) + { + case DT_FIELD_TYPE_FLAGS_INTEGER: + /* + * Start of the definition of a flags field. + * This master flags integer starts at value zero, in preparation + * to compile and insert the flag fields from the individual bits + */ + LocalField = LocalField->Next; + *Field = LocalField; + + FlagBuffer = Buffer; + CurrentFlagByteOffset = Info->Offset; + break; + + case DT_FIELD_TYPE_FLAG: + + /* Individual Flag field, can be multiple bits */ + + if (FlagBuffer) + { + /* + * We must increment the FlagBuffer when we have crossed + * into the next flags byte within the flags field + * of type DT_FIELD_TYPE_FLAGS_INTEGER. + */ + FlagBuffer += (Info->Offset - CurrentFlagByteOffset); + CurrentFlagByteOffset = Info->Offset; + + DtCompileFlag (FlagBuffer, LocalField, Info); + } + else + { + /* TBD - this is an internal error */ + } + + LocalField = LocalField->Next; + *Field = LocalField; + break; + + case DT_FIELD_TYPE_INLINE_SUBTABLE: + /* + * Recursion (one level max): compile GAS (Generic Address) + * or Notify in-line subtable + */ + *Field = LocalField; + + if (Info->Opcode == ACPI_DMT_GAS) + { + Status = DtCompileTable (Field, AcpiDmTableInfoGas, + &InlineSubtable, TRUE); + } + else + { + Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify, + &InlineSubtable, TRUE); + } + + if (ACPI_FAILURE (Status)) + { + goto Error; + } + + DtSetSubtableLength (InlineSubtable); + + ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength); + ACPI_FREE (InlineSubtable->Buffer); + ACPI_FREE (InlineSubtable); + LocalField = *Field; + break; + + case DT_FIELD_TYPE_LABEL: + + DtWriteFieldToListing (Buffer, LocalField, 0); + LocalField = LocalField->Next; + break; + + default: + + /* Normal case for most field types (Integer, String, etc.) */ + + DtCompileOneField (Buffer, LocalField, + FieldLength, FieldType, Info->Flags); + + DtWriteFieldToListing (Buffer, LocalField, FieldLength); + LocalField = LocalField->Next; + + if (Info->Flags & DT_LENGTH) + { + /* Field is an Integer that will contain a subtable length */ + + Subtable->LengthField = Buffer; + Subtable->SizeOfLengthField = FieldLength; + } + + break; + } + + Buffer += FieldLength; + } + + *Field = LocalField; + *RetSubtable = Subtable; + return (AE_OK); + +Error: + ACPI_FREE (Subtable->Buffer); + ACPI_FREE (Subtable); + return (Status); +} diff --git a/source/compiler/dtcompiler.h b/source/compiler/dtcompiler.h new file mode 100644 index 000000000000..c47254f61e6a --- /dev/null +++ b/source/compiler/dtcompiler.h @@ -0,0 +1,513 @@ +/****************************************************************************** + * + * Module Name: dtcompiler.h - header for data table compiler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTCOMPILER_H__ + +#ifndef _DTCOMPILER +#define _DTCOMPILER + +#include +#include "acdisasm.h" + + +#undef DT_EXTERN + +#ifdef _DECLARE_DT_GLOBALS +#define DT_EXTERN +#define DT_INIT_GLOBAL(a,b) (a)=(b) +#else +#define DT_EXTERN extern +#define DT_INIT_GLOBAL(a,b) (a) +#endif + + +/* Types for individual fields (one per input line) */ + +#define DT_FIELD_TYPE_STRING 0 +#define DT_FIELD_TYPE_INTEGER 1 +#define DT_FIELD_TYPE_BUFFER 2 +#define DT_FIELD_TYPE_PCI_PATH 3 +#define DT_FIELD_TYPE_FLAG 4 +#define DT_FIELD_TYPE_FLAGS_INTEGER 5 +#define DT_FIELD_TYPE_INLINE_SUBTABLE 6 +#define DT_FIELD_TYPE_UUID 7 +#define DT_FIELD_TYPE_UNICODE 8 +#define DT_FIELD_TYPE_DEVICE_PATH 9 +#define DT_FIELD_TYPE_LABEL 10 + + +/* + * Structure used for each individual field within an ACPI table + */ +typedef struct dt_field +{ + char *Name; /* Field name (from name : value) */ + char *Value; /* Field value (from name : value) */ + struct dt_field *Next; /* Next field */ + struct dt_field *NextLabel; /* If field is a label, next label */ + UINT32 Line; /* Line number for this field */ + UINT32 ByteOffset; /* Offset in source file for field */ + UINT32 NameColumn; /* Start column for field name */ + UINT32 Column; /* Start column for field value */ + UINT32 TableOffset;/* Binary offset within ACPI table */ + UINT8 Flags; + +} DT_FIELD; + +/* Flags for above */ + +#define DT_FIELD_NOT_ALLOCATED 1 + + +/* + * Structure used for individual subtables within an ACPI table + */ +typedef struct dt_subtable +{ + struct dt_subtable *Parent; + struct dt_subtable *Child; + struct dt_subtable *Peer; + struct dt_subtable *StackTop; + UINT8 *Buffer; + UINT8 *LengthField; + UINT32 Length; + UINT32 TotalLength; + UINT32 SizeOfLengthField; + UINT8 Flags; + +} DT_SUBTABLE; + + +/* + * Globals + */ + +/* List of all field names and values from the input source */ + +DT_EXTERN DT_FIELD DT_INIT_GLOBAL (*Gbl_FieldList, NULL); + +/* List of all compiled tables and subtables */ + +DT_EXTERN DT_SUBTABLE DT_INIT_GLOBAL (*Gbl_RootTable, NULL); + +/* Stack for subtables */ + +DT_EXTERN DT_SUBTABLE DT_INIT_GLOBAL (*Gbl_SubtableStack, NULL); + +/* List for defined labels */ + +DT_EXTERN DT_FIELD DT_INIT_GLOBAL (*Gbl_LabelList, NULL); + +/* Current offset within the binary output table */ + +DT_EXTERN UINT32 DT_INIT_GLOBAL (Gbl_CurrentTableOffset, 0); + + +/* dtcompiler - main module */ + +ACPI_STATUS +DtCompileTable ( + DT_FIELD **Field, + ACPI_DMTABLE_INFO *Info, + DT_SUBTABLE **RetSubtable, + BOOLEAN Required); + + +/* dtio - binary and text input/output */ + +DT_FIELD * +DtScanFile ( + FILE *Handle); + +void +DtOutputBinary ( + DT_SUBTABLE *RootTable); + +void +DtWriteFieldToListing ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 Length); + +void +DtWriteTableToListing ( + void); + + +/* dtsubtable - compile subtables */ + +void +DtCreateSubtable ( + UINT8 *Buffer, + UINT32 Length, + DT_SUBTABLE **RetSubtable); + +UINT32 +DtGetSubtableLength ( + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info); + +void +DtSetSubtableLength ( + DT_SUBTABLE *Subtable); + +void +DtPushSubtable ( + DT_SUBTABLE *Subtable); + +void +DtPopSubtable ( + void); + +DT_SUBTABLE * +DtPeekSubtable ( + void); + +void +DtInsertSubtable ( + DT_SUBTABLE *ParentTable, + DT_SUBTABLE *Subtable); + +DT_SUBTABLE * +DtGetNextSubtable ( + DT_SUBTABLE *ParentTable, + DT_SUBTABLE *ChildTable); + +DT_SUBTABLE * +DtGetParentSubtable ( + DT_SUBTABLE *Subtable); + + +/* dtexpress - Integer expressions and labels */ + +ACPI_STATUS +DtResolveIntegerExpression ( + DT_FIELD *Field, + UINT64 *ReturnValue); + +UINT64 +DtDoOperator ( + UINT64 LeftValue, + UINT32 Operator, + UINT64 RightValue); + +UINT64 +DtResolveLabel ( + char *LabelString); + +void +DtDetectAllLabels ( + DT_FIELD *FieldList); + + +/* dtfield - Compile individual fields within a table */ + +void +DtCompileOneField ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength, + UINT8 Type, + UINT8 Flags); + +void +DtCompileInteger ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength, + UINT8 Flags); + +UINT32 +DtCompileBuffer ( + UINT8 *Buffer, + char *Value, + DT_FIELD *Field, + UINT32 ByteLength); + +void +DtCompileFlag ( + UINT8 *Buffer, + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info); + + +/* dtparser - lex/yacc files */ + +UINT64 +DtEvaluateExpression ( + char *ExprString); + +int +DtInitLexer ( + char *String); + +void +DtTerminateLexer ( + void); + +char * +DtGetOpName ( + UINT32 ParseOpcode); + + +/* dtutils - Miscellaneous utilities */ + +typedef +void (*DT_WALK_CALLBACK) ( + DT_SUBTABLE *Subtable, + void *Context, + void *ReturnValue); + +void +DtWalkTableTree ( + DT_SUBTABLE *StartTable, + DT_WALK_CALLBACK UserFunction, + void *Context, + void *ReturnValue); + +void +DtError ( + UINT8 Level, + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage); + +void +DtNameError ( + UINT8 Level, + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage); + +void +DtFatal ( + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage); + +ACPI_STATUS +DtStrtoul64 ( + char *String, + UINT64 *ReturnInteger); + +UINT32 +DtGetFileSize ( + FILE *Handle); + +char* +DtGetFieldValue ( + DT_FIELD *Field); + +UINT8 +DtGetFieldType ( + ACPI_DMTABLE_INFO *Info); + +UINT32 +DtGetBufferLength ( + char *Buffer); + +UINT32 +DtGetFieldLength ( + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info); + +void +DtSetTableChecksum ( + UINT8 *ChecksumPointer); + +void +DtSetTableLength( + void); + +void +DtFreeFieldList ( + void); + + +/* dttable - individual table compilation */ + +ACPI_STATUS +DtCompileFacs ( + DT_FIELD **PFieldList); + +ACPI_STATUS +DtCompileRsdp ( + DT_FIELD **PFieldList); + +ACPI_STATUS +DtCompileAsf ( + void **PFieldList); + +ACPI_STATUS +DtCompileCpep ( + void **PFieldList); + +ACPI_STATUS +DtCompileDmar ( + void **PFieldList); + +ACPI_STATUS +DtCompileEinj ( + void **PFieldList); + +ACPI_STATUS +DtCompileErst ( + void **PFieldList); + +ACPI_STATUS +DtCompileFadt ( + void **PFieldList); + +ACPI_STATUS +DtCompileFpdt ( + void **PFieldList); + +ACPI_STATUS +DtCompileHest ( + void **PFieldList); + +ACPI_STATUS +DtCompileIvrs ( + void **PFieldList); + +ACPI_STATUS +DtCompileMadt ( + void **PFieldList); + +ACPI_STATUS +DtCompileMcfg ( + void **PFieldList); + +ACPI_STATUS +DtCompileMpst ( + void **PFieldList); + +ACPI_STATUS +DtCompileMsct ( + void **PFieldList); + +ACPI_STATUS +DtCompilePmtt ( + void **PFieldList); + +ACPI_STATUS +DtCompileRsdt ( + void **PFieldList); + +ACPI_STATUS +DtCompileS3pt ( + DT_FIELD **PFieldList); + +ACPI_STATUS +DtCompileSlic ( + void **PFieldList); + +ACPI_STATUS +DtCompileSlit ( + void **PFieldList); + +ACPI_STATUS +DtCompileSrat ( + void **PFieldList); + +ACPI_STATUS +DtCompileUefi ( + void **PFieldList); + +ACPI_STATUS +DtCompileWdat ( + void **PFieldList); + +ACPI_STATUS +DtCompileXsdt ( + void **PFieldList); + +ACPI_STATUS +DtCompileGeneric ( + void **PFieldList); + +ACPI_DMTABLE_INFO * +DtGetGenericTableInfo ( + char *Name); + +/* ACPI Table templates */ + +extern const unsigned char TemplateAsf[]; +extern const unsigned char TemplateBoot[]; +extern const unsigned char TemplateBert[]; +extern const unsigned char TemplateBgrt[]; +extern const unsigned char TemplateCpep[]; +extern const unsigned char TemplateDbgp[]; +extern const unsigned char TemplateDmar[]; +extern const unsigned char TemplateEcdt[]; +extern const unsigned char TemplateEinj[]; +extern const unsigned char TemplateErst[]; +extern const unsigned char TemplateFadt[]; +extern const unsigned char TemplateFpdt[]; +extern const unsigned char TemplateGtdt[]; +extern const unsigned char TemplateHest[]; +extern const unsigned char TemplateHpet[]; +extern const unsigned char TemplateIvrs[]; +extern const unsigned char TemplateMadt[]; +extern const unsigned char TemplateMcfg[]; +extern const unsigned char TemplateMchi[]; +extern const unsigned char TemplateMpst[]; +extern const unsigned char TemplateMsct[]; +extern const unsigned char TemplatePmtt[]; +extern const unsigned char TemplateRsdt[]; +extern const unsigned char TemplateS3pt[]; +extern const unsigned char TemplateSbst[]; +extern const unsigned char TemplateSlic[]; +extern const unsigned char TemplateSlit[]; +extern const unsigned char TemplateSpcr[]; +extern const unsigned char TemplateSpmi[]; +extern const unsigned char TemplateSrat[]; +extern const unsigned char TemplateTcpa[]; +extern const unsigned char TemplateUefi[]; +extern const unsigned char TemplateWaet[]; +extern const unsigned char TemplateWdat[]; +extern const unsigned char TemplateWddt[]; +extern const unsigned char TemplateWdrt[]; +extern const unsigned char TemplateXsdt[]; + +#endif diff --git a/source/compiler/dtexpress.c b/source/compiler/dtexpress.c new file mode 100644 index 000000000000..9773d886c23a --- /dev/null +++ b/source/compiler/dtexpress.c @@ -0,0 +1,408 @@ +/****************************************************************************** + * + * Module Name: dtexpress.c - Support for integer expressions and labels + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTEXPRESS_C__ + +#include "aslcompiler.h" +#include "dtcompiler.h" +#include "dtparser.y.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtexpress") + + +/* Local prototypes */ + +static void +DtInsertLabelField ( + DT_FIELD *Field); + +static DT_FIELD * +DtLookupLabel ( + char *Name); + +/* Global used for errors during parse and related functions */ + +DT_FIELD *Gbl_CurrentField; + + +/****************************************************************************** + * + * FUNCTION: DtResolveIntegerExpression + * + * PARAMETERS: Field - Field object with Integer expression + * ReturnValue - Where the integer is returned + * + * RETURN: Status, and the resolved 64-bit integer value + * + * DESCRIPTION: Resolve an integer expression to a single value. Supports + * both integer constants and labels. + * + *****************************************************************************/ + +ACPI_STATUS +DtResolveIntegerExpression ( + DT_FIELD *Field, + UINT64 *ReturnValue) +{ + UINT64 Result; + + + DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", + Field->Value); + + Gbl_CurrentField = Field; + + Result = DtEvaluateExpression (Field->Value); + *ReturnValue = Result; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtDoOperator + * + * PARAMETERS: LeftValue - First 64-bit operand + * Operator - Parse token for the operator (EXPOP_*) + * RightValue - Second 64-bit operand + * + * RETURN: 64-bit result of the requested operation + * + * DESCRIPTION: Perform the various 64-bit integer math functions + * + *****************************************************************************/ + +UINT64 +DtDoOperator ( + UINT64 LeftValue, + UINT32 Operator, + UINT64 RightValue) +{ + UINT64 Result; + + + /* Perform the requested operation */ + + switch (Operator) + { + case EXPOP_ONES_COMPLIMENT: + Result = ~RightValue; + break; + + case EXPOP_LOGICAL_NOT: + Result = !RightValue; + break; + + case EXPOP_MULTIPLY: + Result = LeftValue * RightValue; + break; + + case EXPOP_DIVIDE: + if (!RightValue) + { + DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, + Gbl_CurrentField, Gbl_CurrentField->Value); + return (0); + } + Result = LeftValue / RightValue; + break; + + case EXPOP_MODULO: + if (!RightValue) + { + DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, + Gbl_CurrentField, Gbl_CurrentField->Value); + return (0); + } + Result = LeftValue % RightValue; + break; + + case EXPOP_ADD: + Result = LeftValue + RightValue; + break; + + case EXPOP_SUBTRACT: + Result = LeftValue - RightValue; + break; + + case EXPOP_SHIFT_RIGHT: + Result = LeftValue >> RightValue; + break; + + case EXPOP_SHIFT_LEFT: + Result = LeftValue << RightValue; + break; + + case EXPOP_LESS: + Result = LeftValue < RightValue; + break; + + case EXPOP_GREATER: + Result = LeftValue > RightValue; + break; + + case EXPOP_LESS_EQUAL: + Result = LeftValue <= RightValue; + break; + + case EXPOP_GREATER_EQUAL: + Result = LeftValue >= RightValue; + break; + + case EXPOP_EQUAL: + Result = LeftValue = RightValue; + break; + + case EXPOP_NOT_EQUAL: + Result = LeftValue != RightValue; + break; + + case EXPOP_AND: + Result = LeftValue & RightValue; + break; + + case EXPOP_XOR: + Result = LeftValue ^ RightValue; + break; + + case EXPOP_OR: + Result = LeftValue | RightValue; + break; + + case EXPOP_LOGICAL_AND: + Result = LeftValue && RightValue; + break; + + case EXPOP_LOGICAL_OR: + Result = LeftValue || RightValue; + break; + + default: + + /* Unknown operator */ + + DtFatal (ASL_MSG_INVALID_EXPRESSION, + Gbl_CurrentField, Gbl_CurrentField->Value); + return (0); + } + + DbgPrint (ASL_DEBUG_OUTPUT, + "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", + Gbl_CurrentField->Value, + ACPI_FORMAT_UINT64 (LeftValue), + DtGetOpName (Operator), + ACPI_FORMAT_UINT64 (RightValue), + ACPI_FORMAT_UINT64 (Result)); + + return (Result); +} + + +/****************************************************************************** + * + * FUNCTION: DtResolveLabel + * + * PARAMETERS: LabelString - Contains the label + * + * RETURN: Table offset associated with the label + * + * DESCRIPTION: Lookup a lable and return its value. + * + *****************************************************************************/ + +UINT64 +DtResolveLabel ( + char *LabelString) +{ + DT_FIELD *LabelField; + + + DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); + + /* Resolve a label reference to an integer (table offset) */ + + if (*LabelString != '$') + { + return (0); + } + + LabelField = DtLookupLabel (LabelString); + if (!LabelField) + { + DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, + Gbl_CurrentField, LabelString); + return (0); + } + + /* All we need from the label is the offset in the table */ + + DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", + LabelField->TableOffset); + + return (LabelField->TableOffset); +} + + +/****************************************************************************** + * + * FUNCTION: DtDetectAllLabels + * + * PARAMETERS: FieldList - Field object at start of generic list + * + * RETURN: None + * + * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as + * a UEFI table.) and insert them into the global label list. + * + *****************************************************************************/ + +void +DtDetectAllLabels ( + DT_FIELD *FieldList) +{ + ACPI_DMTABLE_INFO *Info; + DT_FIELD *GenericField; + UINT32 TableOffset; + + + TableOffset = Gbl_CurrentTableOffset; + GenericField = FieldList; + + /* + * Process all "Label:" fields within the parse tree. We need + * to know the offsets for all labels before we can compile + * the parse tree in order to handle forward references. Traverse + * tree and get/set all field lengths of all operators in order to + * determine the label offsets. + */ + while (GenericField) + { + Info = DtGetGenericTableInfo (GenericField->Name); + if (Info) + { + /* Maintain table offsets */ + + GenericField->TableOffset = TableOffset; + TableOffset += DtGetFieldLength (GenericField, Info); + + /* Insert all labels in the global label list */ + + if (Info->Opcode == ACPI_DMT_LABEL) + { + DtInsertLabelField (GenericField); + } + } + + GenericField = GenericField->Next; + } +} + + +/****************************************************************************** + * + * FUNCTION: DtInsertLabelField + * + * PARAMETERS: Field - Field object with Label to be inserted + * + * RETURN: None + * + * DESCRIPTION: Insert a label field into the global label list + * + *****************************************************************************/ + +static void +DtInsertLabelField ( + DT_FIELD *Field) +{ + + DbgPrint (ASL_DEBUG_OUTPUT, + "DtInsertLabelField: Found Label : %s at output table offset %X\n", + Field->Value, Field->TableOffset); + + Field->NextLabel = Gbl_LabelList; + Gbl_LabelList = Field; +} + + +/****************************************************************************** + * + * FUNCTION: DtLookupLabel + * + * PARAMETERS: Name - Label to be resolved + * + * RETURN: Field object associated with the label + * + * DESCRIPTION: Lookup a label in the global label list. Used during the + * resolution of integer expressions. + * + *****************************************************************************/ + +static DT_FIELD * +DtLookupLabel ( + char *Name) +{ + DT_FIELD *LabelField; + + + /* Skip a leading $ */ + + if (*Name == '$') + { + Name++; + } + + /* Search global list */ + + LabelField = Gbl_LabelList; + while (LabelField) + { + if (!ACPI_STRCMP (Name, LabelField->Value)) + { + return (LabelField); + } + LabelField = LabelField->NextLabel; + } + + return (NULL); +} diff --git a/source/compiler/dtfield.c b/source/compiler/dtfield.c new file mode 100644 index 000000000000..4f9ab612fbc5 --- /dev/null +++ b/source/compiler/dtfield.c @@ -0,0 +1,561 @@ +/****************************************************************************** + * + * Module Name: dtfield.c - Code generation for individual source fields + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTFIELD_C__ + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtfield") + + +/* Local prototypes */ + +static void +DtCompileString ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength); + +static void +DtCompileUnicode ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength); + +static ACPI_STATUS +DtCompileUuid ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength); + +static char * +DtNormalizeBuffer ( + char *Buffer, + UINT32 *Count); + + +/****************************************************************************** + * + * FUNCTION: DtCompileOneField + * + * PARAMETERS: Buffer - Output buffer + * Field - Field to be compiled + * ByteLength - Byte length of the field + * Type - Field type + * + * RETURN: None + * + * DESCRIPTION: Compile a field value to binary + * + *****************************************************************************/ + +void +DtCompileOneField ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength, + UINT8 Type, + UINT8 Flags) +{ + ACPI_STATUS Status; + + switch (Type) + { + case DT_FIELD_TYPE_INTEGER: + DtCompileInteger (Buffer, Field, ByteLength, Flags); + break; + + case DT_FIELD_TYPE_STRING: + DtCompileString (Buffer, Field, ByteLength); + break; + + case DT_FIELD_TYPE_UUID: + Status = DtCompileUuid (Buffer, Field, ByteLength); + if (ACPI_SUCCESS (Status)) + { + break; + } + + /* Fall through. */ + + case DT_FIELD_TYPE_BUFFER: + DtCompileBuffer (Buffer, Field->Value, Field, ByteLength); + break; + + case DT_FIELD_TYPE_UNICODE: + DtCompileUnicode (Buffer, Field, ByteLength); + break; + + case DT_FIELD_TYPE_DEVICE_PATH: + break; + + default: + DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid field type"); + break; + } +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileString + * + * PARAMETERS: Buffer - Output buffer + * Field - String to be copied to buffer + * ByteLength - Maximum length of string + * + * RETURN: None + * + * DESCRIPTION: Copy string to the buffer + * + *****************************************************************************/ + +static void +DtCompileString ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength) +{ + UINT32 Length; + + + Length = ACPI_STRLEN (Field->Value); + + /* Check if the string is too long for the field */ + + if (Length > ByteLength) + { + sprintf (MsgBuffer, "Maximum %u characters", ByteLength); + DtError (ASL_ERROR, ASL_MSG_STRING_LENGTH, Field, MsgBuffer); + Length = ByteLength; + } + + ACPI_MEMCPY (Buffer, Field->Value, Length); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileUnicode + * + * PARAMETERS: Buffer - Output buffer + * Field - String to be copied to buffer + * ByteLength - Maximum length of string + * + * RETURN: None + * + * DESCRIPTION: Convert ASCII string to Unicode string + * + * Note: The Unicode string is 16 bits per character, no leading signature, + * with a 16-bit terminating NULL. + * + *****************************************************************************/ + +static void +DtCompileUnicode ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength) +{ + UINT32 Count; + UINT32 i; + char *AsciiString; + UINT16 *UnicodeString; + + + AsciiString = Field->Value; + UnicodeString = (UINT16 *) Buffer; + Count = ACPI_STRLEN (AsciiString) + 1; + + /* Convert to Unicode string (including null terminator) */ + + for (i = 0; i < Count; i++) + { + UnicodeString[i] = (UINT16) AsciiString[i]; + } +} + + +/******************************************************************************* + * + * FUNCTION: DtCompileUuid + * + * PARAMETERS: Buffer - Output buffer + * Field - String to be copied to buffer + * ByteLength - Maximum length of string + * + * RETURN: None + * + * DESCRIPTION: Convert UUID string to 16-byte buffer + * + ******************************************************************************/ + +static ACPI_STATUS +DtCompileUuid ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength) +{ + char *InString; + ACPI_STATUS Status; + + + InString = Field->Value; + + Status = AuValidateUuid (InString); + if (ACPI_FAILURE (Status)) + { + sprintf (MsgBuffer, "%s", Field->Value); + DtNameError (ASL_ERROR, ASL_MSG_INVALID_UUID, Field, MsgBuffer); + } + else + { + Status = AuConvertStringToUuid (InString, (char *) Buffer); + } + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileInteger + * + * PARAMETERS: Buffer - Output buffer + * Field - Field obj with Integer to be compiled + * ByteLength - Byte length of the integer + * Flags - Additional compile info + * + * RETURN: None + * + * DESCRIPTION: Compile an integer. Supports integer expressions with C-style + * operators. + * + *****************************************************************************/ + +void +DtCompileInteger ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 ByteLength, + UINT8 Flags) +{ + UINT64 Value; + UINT64 MaxValue; + ACPI_STATUS Status; + + + /* Output buffer byte length must be in range 1-8 */ + + if ((ByteLength > 8) || (ByteLength == 0)) + { + DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, + "Invalid internal Byte length"); + return; + } + + /* Resolve integer expression to a single integer value */ + + Status = DtResolveIntegerExpression (Field, &Value); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Ensure that reserved fields are set to zero */ + /* TBD: should we set to zero, or just make this an ERROR? */ + /* TBD: Probably better to use a flag */ + + if (!ACPI_STRCMP (Field->Name, "Reserved") && + (Value != 0)) + { + DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field, + "Setting to zero"); + Value = 0; + } + + /* Check if the value must be non-zero */ + + if ((Value == 0) && (Flags & DT_NON_ZERO)) + { + DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL); + } + + /* + * Generate the maximum value for the data type (ByteLength) + * Note: construct chosen for maximum portability + */ + MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8)); + + /* Validate that the input value is within range of the target */ + + if (Value > MaxValue) + { + sprintf (MsgBuffer, "%8.8X%8.8X", ACPI_FORMAT_UINT64 (Value)); + DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer); + } + + ACPI_MEMCPY (Buffer, &Value, ByteLength); + return; +} + + +/****************************************************************************** + * + * FUNCTION: DtNormalizeBuffer + * + * PARAMETERS: Buffer - Input buffer + * Count - Output the count of hex number in + * the Buffer + * + * RETURN: The normalized buffer, freed by caller + * + * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized + * to 1A 2B 3C 4D + * + *****************************************************************************/ + +static char * +DtNormalizeBuffer ( + char *Buffer, + UINT32 *Count) +{ + char *NewBuffer; + char *TmpBuffer; + UINT32 BufferCount = 0; + BOOLEAN Separator = TRUE; + char c; + + + NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1); + TmpBuffer = NewBuffer; + + while ((c = *Buffer++)) + { + switch (c) + { + /* Valid separators */ + + case '[': + case ']': + case ' ': + case ',': + Separator = TRUE; + break; + + default: + if (Separator) + { + /* Insert blank as the standard separator */ + + if (NewBuffer[0]) + { + *TmpBuffer++ = ' '; + BufferCount++; + } + + Separator = FALSE; + } + + *TmpBuffer++ = c; + break; + } + } + + *Count = BufferCount + 1; + return (NewBuffer); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileBuffer + * + * PARAMETERS: Buffer - Output buffer + * StringValue - Integer list to be compiled + * Field - Current field object + * ByteLength - Byte length of the integer list + * + * RETURN: Count of remaining data in the input list + * + * DESCRIPTION: Compile and pack an integer list, for example + * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B} + * + *****************************************************************************/ + +UINT32 +DtCompileBuffer ( + UINT8 *Buffer, + char *StringValue, + DT_FIELD *Field, + UINT32 ByteLength) +{ + ACPI_STATUS Status; + char Hex[3]; + UINT64 Value; + UINT32 i; + UINT32 Count; + + + /* Allow several different types of value separators */ + + StringValue = DtNormalizeBuffer (StringValue, &Count); + + Hex[2] = 0; + for (i = 0; i < Count; i++) + { + /* Each element of StringValue is three chars */ + + Hex[0] = StringValue[(3 * i)]; + Hex[1] = StringValue[(3 * i) + 1]; + + /* Convert one hex byte */ + + Value = 0; + Status = DtStrtoul64 (Hex, &Value); + if (ACPI_FAILURE (Status)) + { + DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer); + return (ByteLength - Count); + } + + Buffer[i] = (UINT8) Value; + } + + ACPI_FREE (StringValue); + return (ByteLength - Count); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileFlag + * + * PARAMETERS: Buffer - Output buffer + * Field - Field to be compiled + * Info - Flag info + * + * RETURN: + * + * DESCRIPTION: Compile a flag + * + *****************************************************************************/ + +void +DtCompileFlag ( + UINT8 *Buffer, + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info) +{ + UINT64 Value = 0; + UINT32 BitLength = 1; + UINT8 BitPosition = 0; + ACPI_STATUS Status; + + + Status = DtStrtoul64 (Field->Value, &Value); + if (ACPI_FAILURE (Status)) + { + DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL); + } + + switch (Info->Opcode) + { + case ACPI_DMT_FLAG0: + case ACPI_DMT_FLAG1: + case ACPI_DMT_FLAG2: + case ACPI_DMT_FLAG3: + case ACPI_DMT_FLAG4: + case ACPI_DMT_FLAG5: + case ACPI_DMT_FLAG6: + case ACPI_DMT_FLAG7: + + BitPosition = Info->Opcode; + BitLength = 1; + break; + + case ACPI_DMT_FLAGS0: + + BitPosition = 0; + BitLength = 2; + break; + + + case ACPI_DMT_FLAGS1: + + BitPosition = 1; + BitLength = 2; + break; + + + case ACPI_DMT_FLAGS2: + + BitPosition = 2; + BitLength = 2; + break; + + case ACPI_DMT_FLAGS4: + + BitPosition = 4; + BitLength = 2; + break; + + default: + + DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode"); + break; + } + + /* Check range of the input flag value */ + + if (Value >= ((UINT64) 1 << BitLength)) + { + sprintf (MsgBuffer, "Maximum %u bit", BitLength); + DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer); + Value = 0; + } + + *Buffer |= (UINT8) (Value << BitPosition); +} diff --git a/source/compiler/dtio.c b/source/compiler/dtio.c new file mode 100644 index 000000000000..0fe0f38b93d6 --- /dev/null +++ b/source/compiler/dtio.c @@ -0,0 +1,963 @@ +/****************************************************************************** + * + * Module Name: dtio.c - File I/O support for data table compiler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTIO_C__ + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtio") + + +/* Local prototypes */ + +static char * +DtTrim ( + char *String); + +static void +DtLinkField ( + DT_FIELD *Field); + +static ACPI_STATUS +DtParseLine ( + char *LineBuffer, + UINT32 Line, + UINT32 Offset); + +UINT32 +DtGetNextLine ( + FILE *Handle); + +static void +DtWriteBinary ( + DT_SUBTABLE *Subtable, + void *Context, + void *ReturnValue); + +static void +DtDumpBuffer ( + UINT32 FileId, + UINT8 *Buffer, + UINT32 Offset, + UINT32 Length); + + +/* States for DtGetNextLine */ + +#define DT_NORMAL_TEXT 0 +#define DT_START_QUOTED_STRING 1 +#define DT_START_COMMENT 2 +#define DT_SLASH_ASTERISK_COMMENT 3 +#define DT_SLASH_SLASH_COMMENT 4 +#define DT_END_COMMENT 5 +#define DT_MERGE_LINES 6 + +static UINT32 Gbl_NextLineOffset; + + +/****************************************************************************** + * + * FUNCTION: DtTrim + * + * PARAMETERS: String - Current source code line to trim + * + * RETURN: Trimmed line. Must be freed by caller. + * + * DESCRIPTION: Trim left and right spaces + * + *****************************************************************************/ + +static char * +DtTrim ( + char *String) +{ + char *Start; + char *End; + char *ReturnString; + ACPI_SIZE Length; + + + /* Skip lines that start with a space */ + + if (!ACPI_STRCMP (String, " ")) + { + ReturnString = UtLocalCalloc (1); + return (ReturnString); + } + + /* Setup pointers to start and end of input string */ + + Start = String; + End = String + ACPI_STRLEN (String) - 1; + + /* Find first non-whitespace character */ + + while ((Start <= End) && ((*Start == ' ') || (*Start == '\t'))) + { + Start++; + } + + /* Find last non-space character */ + + while (End >= Start) + { + if (*End == '\r' || *End == '\n') + { + End--; + continue; + } + + if (*End != ' ') + { + break; + } + + End--; + } + + /* Remove any quotes around the string */ + + if (*Start == '\"') + { + Start++; + } + if (*End == '\"') + { + End--; + } + + /* Create the trimmed return string */ + + Length = ACPI_PTR_DIFF (End, Start) + 1; + ReturnString = UtLocalCalloc (Length + 1); + if (ACPI_STRLEN (Start)) + { + ACPI_STRNCPY (ReturnString, Start, Length); + } + + ReturnString[Length] = 0; + return (ReturnString); +} + + +/****************************************************************************** + * + * FUNCTION: DtLinkField + * + * PARAMETERS: Field - New field object to link + * + * RETURN: None + * + * DESCRIPTION: Link one field name and value to the list + * + *****************************************************************************/ + +static void +DtLinkField ( + DT_FIELD *Field) +{ + DT_FIELD *Prev; + DT_FIELD *Next; + + + Prev = Next = Gbl_FieldList; + + while (Next) + { + Prev = Next; + Next = Next->Next; + } + + if (Prev) + { + Prev->Next = Field; + } + else + { + Gbl_FieldList = Field; + } +} + + +/****************************************************************************** + * + * FUNCTION: DtParseLine + * + * PARAMETERS: LineBuffer - Current source code line + * Line - Current line number in the source + * Offset - Current byte offset of the line + * + * RETURN: Status + * + * DESCRIPTION: Parse one source line + * + *****************************************************************************/ + +static ACPI_STATUS +DtParseLine ( + char *LineBuffer, + UINT32 Line, + UINT32 Offset) +{ + char *Start; + char *End; + char *TmpName; + char *TmpValue; + char *Name; + char *Value; + char *Colon; + UINT32 Length; + DT_FIELD *Field; + UINT32 Column; + UINT32 NameColumn; + BOOLEAN IsNullString = FALSE; + + + if (!LineBuffer) + { + return (AE_OK); + } + + /* All lines after "Raw Table Data" are ingored */ + + if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER)) + { + return (AE_NOT_FOUND); + } + + Colon = strchr (LineBuffer, ':'); + if (!Colon) + { + return (AE_OK); + } + + Start = LineBuffer; + End = Colon; + + while (Start < Colon) + { + if (*Start == ' ') + { + Start++; + continue; + } + + /* Found left bracket, go to the right bracket */ + + if (*Start == '[') + { + while (Start < Colon && *Start != ']') + { + Start++; + } + + if (Start == Colon) + { + break; + } + + Start++; + continue; + } + + break; + } + + /* + * There are two column values. One for the field name, + * and one for the field value. + */ + Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3; + NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1; + + Length = ACPI_PTR_DIFF (End, Start); + + TmpName = UtLocalCalloc (Length + 1); + ACPI_STRNCPY (TmpName, Start, Length); + Name = DtTrim (TmpName); + ACPI_FREE (TmpName); + + Start = End = (Colon + 1); + while (*End) + { + /* Found left quotation, go to the right quotation and break */ + + if (*End == '"') + { + End++; + + /* Check for an explicit null string */ + + if (*End == '"') + { + IsNullString = TRUE; + } + while (*End && (*End != '"')) + { + End++; + } + + End++; + break; + } + + /* + * Special "comment" fields at line end, ignore them. + * Note: normal slash-slash and slash-asterisk comments are + * stripped already by the DtGetNextLine parser. + * + * TBD: Perhaps DtGetNextLine should parse the following type + * of comments also. + */ + if (*End == '[') + { + End--; + break; + } + End++; + } + + Length = ACPI_PTR_DIFF (End, Start); + TmpValue = UtLocalCalloc (Length + 1); + + ACPI_STRNCPY (TmpValue, Start, Length); + Value = DtTrim (TmpValue); + ACPI_FREE (TmpValue); + + /* Create a new field object only if we have a valid value field */ + + if ((Value && *Value) || IsNullString) + { + Field = UtLocalCalloc (sizeof (DT_FIELD)); + Field->Name = Name; + Field->Value = Value; + Field->Line = Line; + Field->ByteOffset = Offset; + Field->NameColumn = NameColumn; + Field->Column = Column; + + DtLinkField (Field); + } + else /* Ignore this field, it has no valid data */ + { + ACPI_FREE (Name); + ACPI_FREE (Value); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetNextLine + * + * PARAMETERS: Handle - Open file handle for the source file + * + * RETURN: Filled line buffer and offset of start-of-line (ASL_EOF on EOF) + * + * DESCRIPTION: Get the next valid source line. Removes all comments. + * Ignores empty lines. + * + * Handles both slash-asterisk and slash-slash comments. + * Also, quoted strings, but no escapes within. + * + * Line is returned in Gbl_CurrentLineBuffer. + * Line number in original file is returned in Gbl_CurrentLineNumber. + * + *****************************************************************************/ + +UINT32 +DtGetNextLine ( + FILE *Handle) +{ + BOOLEAN LineNotAllBlanks = FALSE; + UINT32 State = DT_NORMAL_TEXT; + UINT32 CurrentLineOffset; + UINT32 i; + char c; + + + for (i = 0; i < ASL_LINE_BUFFER_SIZE;) + { + c = (char) getc (Handle); + if (c == EOF) + { + switch (State) + { + case DT_START_QUOTED_STRING: + case DT_SLASH_ASTERISK_COMMENT: + case DT_SLASH_SLASH_COMMENT: + + AcpiOsPrintf ("**** EOF within comment/string %u\n", State); + break; + + default: + break; + } + + return (ASL_EOF); + } + + switch (State) + { + case DT_NORMAL_TEXT: + + /* Normal text, insert char into line buffer */ + + Gbl_CurrentLineBuffer[i] = c; + switch (c) + { + case '/': + State = DT_START_COMMENT; + break; + + case '"': + State = DT_START_QUOTED_STRING; + LineNotAllBlanks = TRUE; + i++; + break; + + case '\\': + /* + * The continuation char MUST be last char on this line. + * Otherwise, it will be assumed to be a valid ASL char. + */ + State = DT_MERGE_LINES; + break; + + case '\n': + CurrentLineOffset = Gbl_NextLineOffset; + Gbl_NextLineOffset = (UINT32) ftell (Handle); + Gbl_CurrentLineNumber++; + + /* + * Exit if line is complete. Ignore empty lines (only \n) + * or lines that contain nothing but blanks. + */ + if ((i != 0) && LineNotAllBlanks) + { + Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */ + return (CurrentLineOffset); + } + + /* Toss this line and start a new one */ + + i = 0; + LineNotAllBlanks = FALSE; + break; + + default: + if (c != ' ') + { + LineNotAllBlanks = TRUE; + } + + i++; + break; + } + break; + + case DT_START_QUOTED_STRING: + + /* Insert raw chars until end of quoted string */ + + Gbl_CurrentLineBuffer[i] = c; + i++; + + if (c == '"') + { + State = DT_NORMAL_TEXT; + } + break; + + case DT_START_COMMENT: + + /* Open comment if this character is an asterisk or slash */ + + switch (c) + { + case '*': + State = DT_SLASH_ASTERISK_COMMENT; + break; + + case '/': + State = DT_SLASH_SLASH_COMMENT; + break; + + default: /* Not a comment */ + i++; /* Save the preceeding slash */ + Gbl_CurrentLineBuffer[i] = c; + i++; + State = DT_NORMAL_TEXT; + break; + } + break; + + case DT_SLASH_ASTERISK_COMMENT: + + /* Ignore chars until an asterisk-slash is found */ + + switch (c) + { + case '\n': + Gbl_NextLineOffset = (UINT32) ftell (Handle); + Gbl_CurrentLineNumber++; + break; + + case '*': + State = DT_END_COMMENT; + break; + + default: + break; + } + break; + + case DT_SLASH_SLASH_COMMENT: + + /* Ignore chars until end-of-line */ + + if (c == '\n') + { + /* We will exit via the NORMAL_TEXT path */ + + ungetc (c, Handle); + State = DT_NORMAL_TEXT; + } + break; + + case DT_END_COMMENT: + + /* End comment if this char is a slash */ + + switch (c) + { + case '/': + State = DT_NORMAL_TEXT; + break; + + case '\n': + CurrentLineOffset = Gbl_NextLineOffset; + Gbl_NextLineOffset = (UINT32) ftell (Handle); + Gbl_CurrentLineNumber++; + break; + + case '*': + /* Consume all adjacent asterisks */ + break; + + default: + State = DT_SLASH_ASTERISK_COMMENT; + break; + } + break; + + case DT_MERGE_LINES: + + if (c != '\n') + { + /* + * This is not a continuation backslash, it is a normal + * normal ASL backslash - for example: Scope(\_SB_) + */ + i++; /* Keep the backslash that is already in the buffer */ + + ungetc (c, Handle); + State = DT_NORMAL_TEXT; + } + else + { + /* + * This is a continuation line -- a backlash followed + * immediately by a newline. Insert a space between the + * lines (overwrite the backslash) + */ + Gbl_CurrentLineBuffer[i] = ' '; + i++; + + /* Ignore newline, this will merge the lines */ + + CurrentLineOffset = Gbl_NextLineOffset; + Gbl_NextLineOffset = (UINT32) ftell (Handle); + Gbl_CurrentLineNumber++; + State = DT_NORMAL_TEXT; + } + break; + + default: + DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state"); + return (ASL_EOF); + } + } + + printf ("ERROR - Input line is too long (max %u)\n", ASL_LINE_BUFFER_SIZE); + return (ASL_EOF); +} + + +/****************************************************************************** + * + * FUNCTION: DtScanFile + * + * PARAMETERS: Handle - Open file handle for the source file + * + * RETURN: Pointer to start of the constructed parse tree. + * + * DESCRIPTION: Scan source file, link all field names and values + * to the global parse tree: Gbl_FieldList + * + *****************************************************************************/ + +DT_FIELD * +DtScanFile ( + FILE *Handle) +{ + ACPI_STATUS Status; + UINT32 Offset; + DT_FIELD *Next; + + + ACPI_FUNCTION_NAME (DtScanFile); + + + /* Get the file size */ + + Gbl_InputByteCount = DtGetFileSize (Handle); + + Gbl_CurrentLineNumber = 0; + Gbl_CurrentLineOffset = 0; + Gbl_NextLineOffset = 0; + + /* Scan line-by-line */ + + while ((Offset = DtGetNextLine (Handle)) != ASL_EOF) + { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s", + Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer)); + + Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset); + if (Status == AE_NOT_FOUND) + { + break; + } + } + + /* Dump the parse tree if debug enabled */ + + if (Gbl_DebugFlag) + { + Next = Gbl_FieldList; + DbgPrint (ASL_DEBUG_OUTPUT, "Tree: %32s %32s %8s %8s %8s %8s %8s %8s\n\n", + "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags"); + + while (Next) + { + DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n", + Next->Name, + Next->Value, + Next->Line, + Next->ByteOffset, + Next->NameColumn, + Next->Column, + Next->TableOffset, + Next->Flags); + + Next = Next->Next; + } + } + + return (Gbl_FieldList); +} + + +/* + * Output functions + */ + +/****************************************************************************** + * + * FUNCTION: DtWriteBinary + * + * PARAMETERS: DT_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Write one subtable of a binary ACPI table + * + *****************************************************************************/ + +static void +DtWriteBinary ( + DT_SUBTABLE *Subtable, + void *Context, + void *ReturnValue) +{ + + FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length); +} + + +/****************************************************************************** + * + * FUNCTION: DtOutputBinary + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: Write entire binary ACPI table (result of compilation) + * + *****************************************************************************/ + +void +DtOutputBinary ( + DT_SUBTABLE *RootTable) +{ + + if (!RootTable) + { + return; + } + + /* Walk the entire parse tree, emitting the binary data */ + + DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL); + Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); +} + + +/* + * Listing support + */ + +/****************************************************************************** + * + * FUNCTION: DtDumpBuffer + * + * PARAMETERS: FileID - Where to write buffer data + * Buffer - Buffer to dump + * Offset - Offset in current table + * Length - Buffer Length + * + * RETURN: None + * + * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately). + * + * TBD: merge dump buffer routines + * + *****************************************************************************/ + +static void +DtDumpBuffer ( + UINT32 FileId, + UINT8 *Buffer, + UINT32 Offset, + UINT32 Length) +{ + UINT32 i; + UINT32 j; + UINT8 BufChar; + + + FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ", + Offset, Offset, Length); + + i = 0; + while (i < Length) + { + if (i >= 16) + { + FlPrintFile (FileId, "%24s", ""); + } + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) + { + if (i + j >= Length) + { + /* Dump fill spaces */ + + FlPrintFile (FileId, " "); + j++; + continue; + } + + FlPrintFile (FileId, "%02X ", Buffer[i+j]); + j++; + } + + FlPrintFile (FileId, " "); + for (j = 0; j < 16; j++) + { + if (i + j >= Length) + { + FlPrintFile (FileId, "\n\n"); + return; + } + + BufChar = Buffer[(ACPI_SIZE) i + j]; + if (ACPI_IS_PRINT (BufChar)) + { + FlPrintFile (FileId, "%c", BufChar); + } + else + { + FlPrintFile (FileId, "."); + } + } + + /* Done with that line. */ + + FlPrintFile (FileId, "\n"); + i += 16; + } + + FlPrintFile (FileId, "\n\n"); +} + + +/****************************************************************************** + * + * FUNCTION: DtWriteFieldToListing + * + * PARAMETERS: Buffer - Contains the compiled data + * Field - Field node for the input line + * Length - Length of the output data + * + * RETURN: None + * + * DESCRIPTION: Write one field to the listing file (if listing is enabled). + * + *****************************************************************************/ + +void +DtWriteFieldToListing ( + UINT8 *Buffer, + DT_FIELD *Field, + UINT32 Length) +{ + UINT8 FileByte; + + + if (!Gbl_ListingFlag || !Field) + { + return; + } + + /* Dump the original source line */ + + FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input: "); + FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset); + + while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK) + { + FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1); + if (FileByte == '\n') + { + break; + } + } + + /* Dump the line as parsed and represented internally */ + + FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s", + Field->Column-4, Field->Name, Field->Value); + + if (strlen (Field->Value) > 64) + { + FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n", + strlen (Field->Value)); + } + FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n"); + + /* Dump the hex data that will be output for this field */ + + DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length); +} + + +/****************************************************************************** + * + * FUNCTION: DtWriteTableToListing + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Write the entire compiled table to the listing file + * in hex format + * + *****************************************************************************/ + +void +DtWriteTableToListing ( + void) +{ + UINT8 *Buffer; + + + if (!Gbl_ListingFlag) + { + return; + } + + /* Read the entire table from the output file */ + + Buffer = UtLocalCalloc (Gbl_TableLength); + FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength); + + /* Dump the raw table data */ + + AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle); + + AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n", + ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength); + AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY); + + AcpiOsRedirectOutput (stdout); +} diff --git a/source/compiler/dtparser.l b/source/compiler/dtparser.l new file mode 100644 index 000000000000..12f5efd879c9 --- /dev/null +++ b/source/compiler/dtparser.l @@ -0,0 +1,133 @@ +%{ +/****************************************************************************** + * + * Module Name: dtparser.l - Flex input file for table compiler lexer + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "dtparser.y.h" + +#define YY_NO_INPUT /* No file input, we use strings only */ + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("dtscanner") +%} + +%option noyywrap +%option nounput + +Number [0-9a-fA-F]+ +HexNumber 0[xX][0-9a-fA-F]+ +DecimalNumber 0[dD][0-9]+ +LabelRef $[a-zA-Z][0-9a-zA-Z]* +WhiteSpace [ \t\v\r]+ +NewLine [\n] + +%% + +\( return (EXPOP_PAREN_OPEN); +\) return (EXPOP_PAREN_CLOSE); +\~ return (EXPOP_ONES_COMPLIMENT); +\! return (EXPOP_LOGICAL_NOT); +\* return (EXPOP_MULTIPLY); +\/ return (EXPOP_DIVIDE); +\% return (EXPOP_MODULO); +\+ return (EXPOP_ADD); +\- return (EXPOP_SUBTRACT); +">>" return (EXPOP_SHIFT_RIGHT); +"<<" return (EXPOP_SHIFT_LEFT); +\< return (EXPOP_LESS); +\> return (EXPOP_GREATER); +"<=" return (EXPOP_LESS_EQUAL); +">=" return (EXPOP_GREATER_EQUAL); +"==" return (EXPOP_EQUAL); +"!=" return (EXPOP_NOT_EQUAL); +\& return (EXPOP_AND); +\^ return (EXPOP_XOR); +\| return (EXPOP_OR); +"&&" return (EXPOP_LOGICAL_AND); +"||" return (EXPOP_LOGICAL_OR); +<> return (EXPOP_EOF); /* null end-of-string */ + +{LabelRef} return (EXPOP_LABEL); +{Number} return (EXPOP_NUMBER); +{HexNumber} return (EXPOP_HEX_NUMBER); +{NewLine} return (EXPOP_NEW_LINE); +{WhiteSpace} /* Ignore */ + +. return (EXPOP_EOF); + +%% + +/* + * Local support functions + */ +YY_BUFFER_STATE LexBuffer; + +/****************************************************************************** + * + * FUNCTION: DtInitLexer, DtTerminateLexer + * + * PARAMETERS: String - Input string to be parsed + * + * RETURN: None + * + * DESCRIPTION: Initialization and termination routines for lexer. Lexer needs + * a buffer to handle strings instead of a file. + * + *****************************************************************************/ + +int +DtInitLexer ( + char *String) +{ + + LexBuffer = yy_scan_string (String); + return (LexBuffer == NULL); +} + +void +DtTerminateLexer ( + void) +{ + + yy_delete_buffer (LexBuffer); +} diff --git a/source/compiler/dtparser.y b/source/compiler/dtparser.y new file mode 100644 index 000000000000..b931f0976d5f --- /dev/null +++ b/source/compiler/dtparser.y @@ -0,0 +1,273 @@ +%{ +/****************************************************************************** + * + * Module Name: dtparser.y - Bison input file for table compiler parser + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtparser") + +int DtParserlex (void); +int DtParserparse (void); +void DtParsererror (char const *msg); +extern char *DtParsertext; +extern DT_FIELD *Gbl_CurrentField; + +UINT64 DtParserResult; /* Expression return value */ + +/* Bison/yacc configuration */ + +#define yytname DtParsername +#define YYDEBUG 1 /* Enable debug output */ +#define YYERROR_VERBOSE 1 /* Verbose error messages */ +#define YYFLAG -32768 + +%} + +%union +{ + UINT64 value; + UINT32 op; +} + +/*! [Begin] no source code translation */ + +%type Expression + +%token EXPOP_EOF +%token EXPOP_NEW_LINE +%token EXPOP_NUMBER +%token EXPOP_HEX_NUMBER +%token EXPOP_DECIMAL_NUMBER +%token EXPOP_LABEL +%token EXPOP_PAREN_OPEN +%token EXPOP_PAREN_CLOSE + +%left EXPOP_LOGICAL_OR +%left EXPOP_LOGICAL_AND +%left EXPOP_OR +%left EXPOP_XOR +%left EXPOP_AND +%left EXPOP_EQUAL EXPOP_NOT_EQUAL +%left EXPOP_GREATER EXPOP_LESS EXPOP_GREATER_EQUAL EXPOP_LESS_EQUAL +%left EXPOP_SHIFT_RIGHT EXPOP_SHIFT_LEFT +%left EXPOP_ADD EXPOP_SUBTRACT +%left EXPOP_MULTIPLY EXPOP_DIVIDE EXPOP_MODULO +%right EXPOP_ONES_COMPLIMENT EXPOP_LOGICAL_NOT + +%% + +/* + * Operator precedence rules (from K&R) + * + * 1) ( ) + * 2) ! ~ (unary operators that are supported here) + * 3) * / % + * 4) + - + * 5) >> << + * 6) < > <= >= + * 7) == != + * 8) & + * 9) ^ + * 10) | + * 11) && + * 12) || + */ +Value + : Expression EXPOP_NEW_LINE { DtParserResult=$1; return 0; } /* End of line (newline) */ + | Expression EXPOP_EOF { DtParserResult=$1; return 0; } /* End of string (0) */ + ; + +Expression + + /* Unary operators */ + + : EXPOP_LOGICAL_NOT Expression { $$ = DtDoOperator ($2, EXPOP_LOGICAL_NOT, $2);} + | EXPOP_ONES_COMPLIMENT Expression { $$ = DtDoOperator ($2, EXPOP_ONES_COMPLIMENT, $2);} + + /* Binary operators */ + + | Expression EXPOP_MULTIPLY Expression { $$ = DtDoOperator ($1, EXPOP_MULTIPLY, $3);} + | Expression EXPOP_DIVIDE Expression { $$ = DtDoOperator ($1, EXPOP_DIVIDE, $3);} + | Expression EXPOP_MODULO Expression { $$ = DtDoOperator ($1, EXPOP_MODULO, $3);} + | Expression EXPOP_ADD Expression { $$ = DtDoOperator ($1, EXPOP_ADD, $3);} + | Expression EXPOP_SUBTRACT Expression { $$ = DtDoOperator ($1, EXPOP_SUBTRACT, $3);} + | Expression EXPOP_SHIFT_RIGHT Expression { $$ = DtDoOperator ($1, EXPOP_SHIFT_RIGHT, $3);} + | Expression EXPOP_SHIFT_LEFT Expression { $$ = DtDoOperator ($1, EXPOP_SHIFT_LEFT, $3);} + | Expression EXPOP_GREATER Expression { $$ = DtDoOperator ($1, EXPOP_GREATER, $3);} + | Expression EXPOP_LESS Expression { $$ = DtDoOperator ($1, EXPOP_LESS, $3);} + | Expression EXPOP_GREATER_EQUAL Expression { $$ = DtDoOperator ($1, EXPOP_GREATER_EQUAL, $3);} + | Expression EXPOP_LESS_EQUAL Expression { $$ = DtDoOperator ($1, EXPOP_LESS_EQUAL, $3);} + | Expression EXPOP_EQUAL Expression { $$ = DtDoOperator ($1, EXPOP_EQUAL, $3);} + | Expression EXPOP_NOT_EQUAL Expression { $$ = DtDoOperator ($1, EXPOP_NOT_EQUAL, $3);} + | Expression EXPOP_AND Expression { $$ = DtDoOperator ($1, EXPOP_AND, $3);} + | Expression EXPOP_XOR Expression { $$ = DtDoOperator ($1, EXPOP_XOR, $3);} + | Expression EXPOP_OR Expression { $$ = DtDoOperator ($1, EXPOP_OR, $3);} + | Expression EXPOP_LOGICAL_AND Expression { $$ = DtDoOperator ($1, EXPOP_LOGICAL_AND, $3);} + | Expression EXPOP_LOGICAL_OR Expression { $$ = DtDoOperator ($1, EXPOP_LOGICAL_OR, $3);} + + /* Parentheses: '(' Expression ')' */ + + | EXPOP_PAREN_OPEN Expression + EXPOP_PAREN_CLOSE { $$ = $2;} + + /* Label references (prefixed with $) */ + + | EXPOP_LABEL { $$ = DtResolveLabel (DtParsertext);} + + /* Default base for a non-prefixed integer is 16 */ + + | EXPOP_NUMBER { UtStrtoul64 (DtParsertext, 16, &$$);} + + /* Standard hex number (0x1234) */ + + | EXPOP_HEX_NUMBER { UtStrtoul64 (DtParsertext, 16, &$$);} + + /* TBD: Decimal number with prefix (0d1234) - Not supported by UtStrtoul64 at this time */ + + | EXPOP_DECIMAL_NUMBER { UtStrtoul64 (DtParsertext, 10, &$$);} + ; +%% + +/*! [End] no source code translation !*/ + +/* + * Local support functions, including parser entry point + */ +#define PR_FIRST_PARSE_OPCODE EXPOP_EOF +#define PR_YYTNAME_START 3 + + +/****************************************************************************** + * + * FUNCTION: DtParsererror + * + * PARAMETERS: Message - Parser-generated error message + * + * RETURN: None + * + * DESCRIPTION: Handler for parser errors + * + *****************************************************************************/ + +void +DtParsererror ( + char const *Message) +{ + DtError (ASL_ERROR, ASL_MSG_SYNTAX, + Gbl_CurrentField, (char *) Message); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetOpName + * + * PARAMETERS: ParseOpcode - Parser token (EXPOP_*) + * + * RETURN: Pointer to the opcode name + * + * DESCRIPTION: Get the ascii name of the parse opcode for debug output + * + *****************************************************************************/ + +char * +DtGetOpName ( + UINT32 ParseOpcode) +{ +#ifdef ASL_YYTNAME_START + /* + * First entries (PR_YYTNAME_START) in yytname are special reserved names. + * Ignore first 6 characters of name (EXPOP_) + */ + return ((char *) yytname + [(ParseOpcode - PR_FIRST_PARSE_OPCODE) + PR_YYTNAME_START] + 6); +#else + return ("[Unknown parser generator]"); +#endif +} + + +/****************************************************************************** + * + * FUNCTION: DtEvaluateExpression + * + * PARAMETERS: ExprString - Expression to be evaluated. Must be + * terminated by either a newline or a NUL + * string terminator + * + * RETURN: 64-bit value for the expression + * + * DESCRIPTION: Main entry point for the DT expression parser + * + *****************************************************************************/ + +UINT64 +DtEvaluateExpression ( + char *ExprString) +{ + + DbgPrint (ASL_DEBUG_OUTPUT, + "**** Input expression: %s (Base 16)\n", ExprString); + + /* Point lexer to the input string */ + + if (DtInitLexer (ExprString)) + { + DtError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, + Gbl_CurrentField, "Could not initialize lexer"); + return (0); + } + + /* Parse/Evaluate the input string (value returned in DtParserResult) */ + + DtParserparse (); + DtTerminateLexer (); + + DbgPrint (ASL_DEBUG_OUTPUT, + "**** Parser returned value: %u (%8.8X%8.8X)\n", + (UINT32) DtParserResult, ACPI_FORMAT_UINT64 (DtParserResult)); + + return (DtParserResult); +} diff --git a/source/compiler/dtsubtable.c b/source/compiler/dtsubtable.c new file mode 100644 index 000000000000..27d09cae2ee3 --- /dev/null +++ b/source/compiler/dtsubtable.c @@ -0,0 +1,375 @@ +/****************************************************************************** + * + * Module Name: dtsubtable.c - handling of subtables within ACPI tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTSUBTABLE_C__ + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtsubtable") + + +/****************************************************************************** + * + * FUNCTION: DtCreateSubtable + * + * PARAMETERS: Buffer - Input buffer + * Length - Buffer length + * RetSubtable - Returned newly created subtable + * + * RETURN: None + * + * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO + * For example, FACS has 24 bytes reserved at the end + * and it's not listed at AcpiDmTableInfoFacs + * + *****************************************************************************/ + +void +DtCreateSubtable ( + UINT8 *Buffer, + UINT32 Length, + DT_SUBTABLE **RetSubtable) +{ + DT_SUBTABLE *Subtable; + + + Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); + + /* Create a new buffer for the subtable data */ + + Subtable->Buffer = UtLocalCalloc (Length); + ACPI_MEMCPY (Subtable->Buffer, Buffer, Length); + + Subtable->Length = Length; + Subtable->TotalLength = Length; + + *RetSubtable = Subtable; +} + + +/****************************************************************************** + * + * FUNCTION: DtInsertSubtable + * + * PARAMETERS: ParentTable - The Parent of the new subtable + * Subtable - The new subtable to insert + * + * RETURN: None + * + * DESCRIPTION: Insert the new subtable to the parent table + * + *****************************************************************************/ + +void +DtInsertSubtable ( + DT_SUBTABLE *ParentTable, + DT_SUBTABLE *Subtable) +{ + DT_SUBTABLE *ChildTable; + + + Subtable->Peer = NULL; + Subtable->Parent = ParentTable; + + /* Link the new entry into the child list */ + + if (!ParentTable->Child) + { + ParentTable->Child = Subtable; + } + else + { + /* Walk to the end of the child list */ + + ChildTable = ParentTable->Child; + while (ChildTable->Peer) + { + ChildTable = ChildTable->Peer; + } + + /* Add new subtable at the end of the child list */ + + ChildTable->Peer = Subtable; + } +} + + +/****************************************************************************** + * + * FUNCTION: DtPushSubtable + * + * PARAMETERS: Subtable - Subtable to push + * + * RETURN: None + * + * DESCRIPTION: Push a subtable onto a subtable stack + * + *****************************************************************************/ + +void +DtPushSubtable ( + DT_SUBTABLE *Subtable) +{ + + Subtable->StackTop = Gbl_SubtableStack; + Gbl_SubtableStack = Subtable; +} + + +/****************************************************************************** + * + * FUNCTION: DtPopSubtable + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack + * + *****************************************************************************/ + +void +DtPopSubtable ( + void) +{ + DT_SUBTABLE *Subtable; + + + Subtable = Gbl_SubtableStack; + + if (Subtable) + { + Gbl_SubtableStack = Subtable->StackTop; + } +} + + +/****************************************************************************** + * + * FUNCTION: DtPeekSubtable + * + * PARAMETERS: None + * + * RETURN: The subtable on top of stack + * + * DESCRIPTION: Get the subtable on top of stack + * + *****************************************************************************/ + +DT_SUBTABLE * +DtPeekSubtable ( + void) +{ + + return (Gbl_SubtableStack); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetNextSubtable + * + * PARAMETERS: ParentTable - Parent table whose children we are + * getting + * ChildTable - Previous child that was found. + * The NEXT child will be returned + * + * RETURN: Pointer to the NEXT child or NULL if none is found. + * + * DESCRIPTION: Return the next peer subtable within the tree. + * + *****************************************************************************/ + +DT_SUBTABLE * +DtGetNextSubtable ( + DT_SUBTABLE *ParentTable, + DT_SUBTABLE *ChildTable) +{ + ACPI_FUNCTION_ENTRY (); + + + if (!ChildTable) + { + /* It's really the parent's _scope_ that we want */ + + return (ParentTable->Child); + } + + /* Otherwise just return the next peer (NULL if at end-of-list) */ + + return (ChildTable->Peer); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetParentSubtable + * + * PARAMETERS: Subtable - Current subtable + * + * RETURN: Parent of the given subtable + * + * DESCRIPTION: Get the parent of the given subtable in the tree + * + *****************************************************************************/ + +DT_SUBTABLE * +DtGetParentSubtable ( + DT_SUBTABLE *Subtable) +{ + + if (!Subtable) + { + return (NULL); + } + + return (Subtable->Parent); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetSubtableLength + * + * PARAMETERS: Field - Current field list pointer + * Info - Data table info + * + * RETURN: Subtable length + * + * DESCRIPTION: Get length of bytes needed to compile the subtable + * + *****************************************************************************/ + +UINT32 +DtGetSubtableLength ( + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info) +{ + UINT32 ByteLength = 0; + UINT8 Step; + UINT8 i; + + + /* Walk entire Info table; Null name terminates */ + + for (; Info->Name; Info++) + { + if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) + { + continue; + } + + if (!Field) + { + goto Error; + } + + ByteLength += DtGetFieldLength (Field, Info); + + switch (Info->Opcode) + { + case ACPI_DMT_GAS: + Step = 5; + break; + + case ACPI_DMT_HESTNTFY: + Step = 9; + break; + + default: + Step = 1; + break; + } + + for (i = 0; i < Step; i++) + { + if (!Field) + { + goto Error; + } + + Field = Field->Next; + } + } + + return (ByteLength); + +Error: + if (!Field) + { + sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", + Info->Name); + DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); + } + + return (ASL_EOF); +} + + +/****************************************************************************** + * + * FUNCTION: DtSetSubtableLength + * + * PARAMETERS: Subtable - Subtable + * + * RETURN: None + * + * DESCRIPTION: Set length of the subtable into its length field + * + *****************************************************************************/ + +void +DtSetSubtableLength ( + DT_SUBTABLE *Subtable) +{ + + if (!Subtable->LengthField) + { + return; + } + + ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength, + Subtable->SizeOfLengthField); +} diff --git a/source/compiler/dttable.c b/source/compiler/dttable.c new file mode 100644 index 000000000000..d6baa5350192 --- /dev/null +++ b/source/compiler/dttable.c @@ -0,0 +1,2020 @@ +/****************************************************************************** + * + * Module Name: dttable.c - handling for specific ACPI tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTTABLE_C__ + +/* Compile all complex data tables */ + +#include "aslcompiler.h" +#include "dtcompiler.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dttable") + + +/* TBD: merge these into dmtbinfo.c? */ + +static ACPI_DMTABLE_INFO TableInfoAsfAddress[] = +{ + {ACPI_DMT_BUFFER, 0, "Addresses", 0}, + {ACPI_DMT_EXIT, 0, NULL, 0} +}; + +static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] = +{ + {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0}, + {ACPI_DMT_EXIT, 0, NULL, 0} +}; + + +/* TBD: move to acmacros.h */ + +#define ACPI_SUB_PTR(t, a, b) \ + ACPI_CAST_PTR (t, (ACPI_CAST_PTR (UINT8, (a)) - (ACPI_SIZE)(b))) + + +/* Local prototypes */ + +static ACPI_STATUS +DtCompileTwoSubtables ( + void **List, + ACPI_DMTABLE_INFO *TableInfo1, + ACPI_DMTABLE_INFO *TableInfo2); + + +/****************************************************************************** + * + * FUNCTION: DtCompileTwoSubtables + * + * PARAMETERS: List - Current field list pointer + * TableInfo1 - Info table 1 + * TableInfo1 - Info table 2 + * + * RETURN: Status + * + * DESCRIPTION: Compile tables with a header and one or more same subtables. + * Include CPEP, EINJ, ERST, MCFG, MSCT, WDAT + * + *****************************************************************************/ + +static ACPI_STATUS +DtCompileTwoSubtables ( + void **List, + ACPI_DMTABLE_INFO *TableInfo1, + ACPI_DMTABLE_INFO *TableInfo2) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + + + Status = DtCompileTable (PFieldList, TableInfo1, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + Status = DtCompileTable (PFieldList, TableInfo2, &Subtable, FALSE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileFacs + * + * PARAMETERS: PFieldList - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile FACS. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileFacs ( + DT_FIELD **PFieldList) +{ + DT_SUBTABLE *Subtable; + UINT8 *ReservedBuffer; + ACPI_STATUS Status; + UINT32 ReservedSize; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFacs, + &Gbl_RootTable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Large FACS reserved area at the end of the table */ + + ReservedSize = (UINT32) sizeof (((ACPI_TABLE_FACS *) NULL)->Reserved1); + ReservedBuffer = UtLocalCalloc (ReservedSize); + + DtCreateSubtable (ReservedBuffer, ReservedSize, &Subtable); + + ACPI_FREE (ReservedBuffer); + DtInsertSubtable (Gbl_RootTable, Subtable); + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileRsdp + * + * PARAMETERS: PFieldList - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile RSDP. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileRsdp ( + DT_FIELD **PFieldList) +{ + DT_SUBTABLE *Subtable; + ACPI_TABLE_RSDP *Rsdp; + ACPI_RSDP_EXTENSION *RsdpExtension; + ACPI_STATUS Status; + + + /* Compile the "common" RSDP (ACPI 1.0) */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoRsdp1, + &Gbl_RootTable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Gbl_RootTable->Buffer); + DtSetTableChecksum (&Rsdp->Checksum); + + if (Rsdp->Revision > 0) + { + /* Compile the "extended" part of the RSDP as a subtable */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoRsdp2, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (Gbl_RootTable, Subtable); + + /* Set length and extended checksum for entire RSDP */ + + RsdpExtension = ACPI_CAST_PTR (ACPI_RSDP_EXTENSION, Subtable->Buffer); + RsdpExtension->Length = Gbl_RootTable->Length + Subtable->Length; + DtSetTableChecksum (&RsdpExtension->ExtendedChecksum); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileAsf + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile ASF!. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileAsf ( + void **List) +{ + ACPI_ASF_INFO *AsfTable; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + ACPI_DMTABLE_INFO *InfoTable; + ACPI_DMTABLE_INFO *DataInfoTable = NULL; + UINT32 DataCount = 0; + ACPI_STATUS Status; + UINT32 i; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer); + + switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ + { + case ACPI_ASF_TYPE_INFO: + InfoTable = AcpiDmTableInfoAsf0; + break; + + case ACPI_ASF_TYPE_ALERT: + InfoTable = AcpiDmTableInfoAsf1; + break; + + case ACPI_ASF_TYPE_CONTROL: + InfoTable = AcpiDmTableInfoAsf2; + break; + + case ACPI_ASF_TYPE_BOOT: + InfoTable = AcpiDmTableInfoAsf3; + break; + + case ACPI_ASF_TYPE_ADDRESS: + InfoTable = AcpiDmTableInfoAsf4; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ + { + case ACPI_ASF_TYPE_INFO: + DataInfoTable = NULL; + break; + + case ACPI_ASF_TYPE_ALERT: + DataInfoTable = AcpiDmTableInfoAsf1a; + DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, + ACPI_SUB_PTR (UINT8, Subtable->Buffer, + sizeof (ACPI_ASF_HEADER)))->Alerts; + break; + + case ACPI_ASF_TYPE_CONTROL: + DataInfoTable = AcpiDmTableInfoAsf2a; + DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, + ACPI_SUB_PTR (UINT8, Subtable->Buffer, + sizeof (ACPI_ASF_HEADER)))->Controls; + break; + + case ACPI_ASF_TYPE_BOOT: + DataInfoTable = NULL; + break; + + case ACPI_ASF_TYPE_ADDRESS: + DataInfoTable = TableInfoAsfAddress; + DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, + ACPI_SUB_PTR (UINT8, Subtable->Buffer, + sizeof (ACPI_ASF_HEADER)))->Devices; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); + return (AE_ERROR); + } + + if (DataInfoTable) + { + switch (AsfTable->Header.Type & 0x7F) + { + case ACPI_ASF_TYPE_ADDRESS: + + while (DataCount > 0) + { + Status = DtCompileTable (PFieldList, DataInfoTable, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + DataCount = DataCount - Subtable->Length; + } + break; + + default: + + for (i = 0; i < DataCount; i++) + { + Status = DtCompileTable (PFieldList, DataInfoTable, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + } + break; + } + } + + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileCpep + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile CPEP. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileCpep ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileDmar + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile DMAR. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileDmar ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_DMTABLE_INFO *InfoTable; + ACPI_DMAR_HEADER *DmarHeader; + UINT8 *ReservedBuffer; + UINT32 ReservedSize; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + /* DMAR Reserved area */ + + ReservedSize = (UINT32) sizeof (((ACPI_TABLE_DMAR *) NULL)->Reserved); + ReservedBuffer = UtLocalCalloc (ReservedSize); + + DtCreateSubtable (ReservedBuffer, ReservedSize, &Subtable); + + ACPI_FREE (ReservedBuffer); + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + /* DMAR Header */ + + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer); + + switch (DmarHeader->Type) + { + case ACPI_DMAR_TYPE_HARDWARE_UNIT: + InfoTable = AcpiDmTableInfoDmar0; + break; + case ACPI_DMAR_TYPE_RESERVED_MEMORY: + InfoTable = AcpiDmTableInfoDmar1; + break; + case ACPI_DMAR_TYPE_ATSR: + InfoTable = AcpiDmTableInfoDmar2; + break; + case ACPI_DMAR_HARDWARE_AFFINITY: + InfoTable = AcpiDmTableInfoDmar3; + break; + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); + return (AE_ERROR); + } + + /* DMAR Subtable */ + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + /* Optional Device Scope subtables */ + + while (*PFieldList) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, + &Subtable, FALSE); + if (Status == AE_NOT_FOUND) + { + break; + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + /* Optional PCI Paths */ + + while (*PFieldList) + { + Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, + &Subtable, FALSE); + if (Status == AE_NOT_FOUND) + { + DtPopSubtable (); + break; + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + } + } + + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileEinj + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile EINJ. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileEinj ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileErst + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile ERST. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileErst ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileFadt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile FADT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileFadt ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + ACPI_TABLE_HEADER *Table; + UINT8 Revision; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFadt1, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); + Revision = Table->Revision; + + if (Revision == 2) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFadt2, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + } + else if (Revision >= 2) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFadt3, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + + if (Revision >= 5) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFadt5, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileFpdt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile FPDT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileFpdt ( + void **List) +{ + ACPI_STATUS Status; + ACPI_FPDT_HEADER *FpdtHeader; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + ACPI_DMTABLE_INFO *InfoTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); + + switch (FpdtHeader->Type) + { + case ACPI_FPDT_TYPE_BOOT: + InfoTable = AcpiDmTableInfoFpdt0; + break; + + case ACPI_FPDT_TYPE_S3PERF: + InfoTable = AcpiDmTableInfoFpdt1; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); + return (AE_ERROR); + break; + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileHest + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile HEST. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileHest ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_DMTABLE_INFO *InfoTable; + UINT16 Type; + UINT32 BankCount; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + /* Get subtable type */ + + SubtableStart = *PFieldList; + DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); + + switch (Type) + { + case ACPI_HEST_TYPE_IA32_CHECK: + InfoTable = AcpiDmTableInfoHest0; + break; + + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: + InfoTable = AcpiDmTableInfoHest1; + break; + + case ACPI_HEST_TYPE_IA32_NMI: + InfoTable = AcpiDmTableInfoHest2; + break; + + case ACPI_HEST_TYPE_AER_ROOT_PORT: + InfoTable = AcpiDmTableInfoHest6; + break; + + case ACPI_HEST_TYPE_AER_ENDPOINT: + InfoTable = AcpiDmTableInfoHest7; + break; + + case ACPI_HEST_TYPE_AER_BRIDGE: + InfoTable = AcpiDmTableInfoHest8; + break; + + case ACPI_HEST_TYPE_GENERIC_ERROR: + InfoTable = AcpiDmTableInfoHest9; + break; + + default: + /* Cannot continue on unknown type */ + + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + + /* + * Additional subtable data - IA32 Error Bank(s) + */ + BankCount = 0; + switch (Type) + { + case ACPI_HEST_TYPE_IA32_CHECK: + BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, + Subtable->Buffer))->NumHardwareBanks; + break; + + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: + BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, + Subtable->Buffer))->NumHardwareBanks; + break; + + default: + break; + } + + while (BankCount) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + BankCount--; + } + } + + return AE_OK; +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileIvrs + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile IVRS. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileIvrs ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_DMTABLE_INFO *InfoTable; + ACPI_IVRS_HEADER *IvrsHeader; + UINT8 EntryType; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer); + + switch (IvrsHeader->Type) + { + case ACPI_IVRS_TYPE_HARDWARE: + InfoTable = AcpiDmTableInfoIvrs0; + break; + + case ACPI_IVRS_TYPE_MEMORY1: + case ACPI_IVRS_TYPE_MEMORY2: + case ACPI_IVRS_TYPE_MEMORY3: + InfoTable = AcpiDmTableInfoIvrs1; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE) + { + while (*PFieldList && + !ACPI_STRCMP ((*PFieldList)->Name, "Entry Type")) + { + SubtableStart = *PFieldList; + DtCompileInteger (&EntryType, *PFieldList, 1, 0); + + switch (EntryType) + { + /* 4-byte device entries */ + + case ACPI_IVRS_TYPE_PAD4: + case ACPI_IVRS_TYPE_ALL: + case ACPI_IVRS_TYPE_SELECT: + case ACPI_IVRS_TYPE_START: + case ACPI_IVRS_TYPE_END: + + InfoTable = AcpiDmTableInfoIvrs4; + break; + + /* 8-byte entries, type A */ + + case ACPI_IVRS_TYPE_ALIAS_SELECT: + case ACPI_IVRS_TYPE_ALIAS_START: + + InfoTable = AcpiDmTableInfoIvrs8a; + break; + + /* 8-byte entries, type B */ + + case ACPI_IVRS_TYPE_PAD8: + case ACPI_IVRS_TYPE_EXT_SELECT: + case ACPI_IVRS_TYPE_EXT_START: + + InfoTable = AcpiDmTableInfoIvrs8b; + break; + + /* 8-byte entries, type C */ + + case ACPI_IVRS_TYPE_SPECIAL: + + InfoTable = AcpiDmTableInfoIvrs8c; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, + "IVRS Device Entry"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + } + } + + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileMadt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile MADT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileMadt ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_SUBTABLE_HEADER *MadtHeader; + ACPI_DMTABLE_INFO *InfoTable; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMadt, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMadtHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + MadtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); + + switch (MadtHeader->Type) + { + case ACPI_MADT_TYPE_LOCAL_APIC: + InfoTable = AcpiDmTableInfoMadt0; + break; + case ACPI_MADT_TYPE_IO_APIC: + InfoTable = AcpiDmTableInfoMadt1; + break; + case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: + InfoTable = AcpiDmTableInfoMadt2; + break; + case ACPI_MADT_TYPE_NMI_SOURCE: + InfoTable = AcpiDmTableInfoMadt3; + break; + case ACPI_MADT_TYPE_LOCAL_APIC_NMI: + InfoTable = AcpiDmTableInfoMadt4; + break; + case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: + InfoTable = AcpiDmTableInfoMadt5; + break; + case ACPI_MADT_TYPE_IO_SAPIC: + InfoTable = AcpiDmTableInfoMadt6; + break; + case ACPI_MADT_TYPE_LOCAL_SAPIC: + InfoTable = AcpiDmTableInfoMadt7; + break; + case ACPI_MADT_TYPE_INTERRUPT_SOURCE: + InfoTable = AcpiDmTableInfoMadt8; + break; + case ACPI_MADT_TYPE_LOCAL_X2APIC: + InfoTable = AcpiDmTableInfoMadt9; + break; + case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: + InfoTable = AcpiDmTableInfoMadt10; + break; + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + InfoTable = AcpiDmTableInfoMadt11; + break; + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + InfoTable = AcpiDmTableInfoMadt12; + break; + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "MADT"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileMcfg + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile MCFG. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileMcfg ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoMcfg, AcpiDmTableInfoMcfg0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileMpst + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile MPST. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileMpst ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + ACPI_MPST_CHANNEL *MpstChannelInfo; + ACPI_MPST_POWER_NODE *MpstPowerNode; + ACPI_MPST_DATA_HDR *MpstDataHeader; + UINT16 SubtableCount; + UINT8 PowerStateCount; + UINT8 ComponentCount; + + + /* Main table */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + MpstChannelInfo = ACPI_CAST_PTR (ACPI_MPST_CHANNEL, Subtable->Buffer); + SubtableCount = MpstChannelInfo->PowerNodeCount; + + while (*PFieldList && SubtableCount) + { + /* Subtable: Memory Power Node(s) */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + MpstPowerNode = ACPI_CAST_PTR (ACPI_MPST_POWER_NODE, Subtable->Buffer); + PowerStateCount = MpstPowerNode->NumPowerStates; + ComponentCount = MpstPowerNode->NumPhysicalComponents; + + ParentTable = DtPeekSubtable (); + + /* Sub-subtables - Memory Power State Structure(s) */ + + while (*PFieldList && PowerStateCount) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0A, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + PowerStateCount--; + } + + /* Sub-subtables - Physical Component ID Structure(s) */ + + while (*PFieldList && ComponentCount) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0B, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + ComponentCount--; + } + + SubtableCount--; + DtPopSubtable (); + } + + /* Subtable: Count of Memory Power State Characteristic structures */ + + DtPopSubtable (); + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst1, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + MpstDataHeader = ACPI_CAST_PTR (ACPI_MPST_DATA_HDR, Subtable->Buffer); + SubtableCount = MpstDataHeader->CharacteristicsCount; + + ParentTable = DtPeekSubtable (); + + /* Subtable: Memory Power State Characteristics structure(s) */ + + while (*PFieldList && SubtableCount) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst2, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + SubtableCount--; + } + + DtPopSubtable (); + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileMsct + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile MSCT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileMsct ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoMsct, AcpiDmTableInfoMsct0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompilePmtt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile PMTT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompilePmtt ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_PMTT_HEADER *PmttHeader; + ACPI_PMTT_CONTROLLER *PmttController; + UINT16 DomainCount; + UINT8 PrevType = ACPI_PMTT_TYPE_SOCKET; + + + /* Main table */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmttHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + PmttHeader = ACPI_CAST_PTR (ACPI_PMTT_HEADER, Subtable->Buffer); + while (PrevType >= PmttHeader->Type) + { + DtPopSubtable (); + + if (PrevType == ACPI_PMTT_TYPE_SOCKET) + { + break; + } + PrevType--; + } + PrevType = PmttHeader->Type; + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + switch (PmttHeader->Type) + { + case ACPI_PMTT_TYPE_SOCKET: + + /* Subtable: Socket Structure */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt0, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + break; + + case ACPI_PMTT_TYPE_CONTROLLER: + + /* Subtable: Memory Controller Structure */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt1, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + PmttController = ACPI_CAST_PTR (ACPI_PMTT_CONTROLLER, + (Subtable->Buffer - sizeof (ACPI_PMTT_HEADER))); + DomainCount = PmttController->DomainCount; + + while (DomainCount) + { + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt1a, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtInsertSubtable (ParentTable, Subtable); + DomainCount--; + } + break; + + case ACPI_PMTT_TYPE_DIMM: + + /* Subtable: Physical Component Structure */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt2, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + break; + + default: + + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "PMTT"); + return (AE_ERROR); + } + } + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileRsdt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile RSDT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileRsdt ( + void **List) +{ + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD *FieldList = *(DT_FIELD **) List; + UINT32 Address; + + + ParentTable = DtPeekSubtable (); + + while (FieldList) + { + DtCompileInteger ((UINT8 *) &Address, FieldList, 4, DT_NON_ZERO); + + DtCreateSubtable ((UINT8 *) &Address, 4, &Subtable); + DtInsertSubtable (ParentTable, Subtable); + FieldList = FieldList->Next; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileS3pt + * + * PARAMETERS: PFieldList - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile S3PT (Pointed to by FPDT) + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileS3pt ( + DT_FIELD **PFieldList) +{ + ACPI_STATUS Status; + ACPI_S3PT_HEADER *S3ptHeader; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + ACPI_DMTABLE_INFO *InfoTable; + DT_FIELD *SubtableStart; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoS3pt, + &Gbl_RootTable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DtPushSubtable (Gbl_RootTable); + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoS3ptHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + S3ptHeader = ACPI_CAST_PTR (ACPI_S3PT_HEADER, Subtable->Buffer); + + switch (S3ptHeader->Type) + { + case ACPI_S3PT_TYPE_RESUME: + InfoTable = AcpiDmTableInfoS3pt0; + break; + + case ACPI_S3PT_TYPE_SUSPEND: + InfoTable = AcpiDmTableInfoS3pt1; + break; + + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "S3PT"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileSlic + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile SLIC. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileSlic ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_SLIC_HEADER *SlicHeader; + ACPI_DMTABLE_INFO *InfoTable; + + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoSlicHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + SlicHeader = ACPI_CAST_PTR (ACPI_SLIC_HEADER, Subtable->Buffer); + + switch (SlicHeader->Type) + { + case ACPI_SLIC_TYPE_PUBLIC_KEY: + InfoTable = AcpiDmTableInfoSlic0; + break; + case ACPI_SLIC_TYPE_WINDOWS_MARKER: + InfoTable = AcpiDmTableInfoSlic1; + break; + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "SLIC"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileSlit + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile SLIT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileSlit ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *FieldList; + UINT32 Localities; + UINT8 *LocalityBuffer; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoSlit, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + Localities = *ACPI_CAST_PTR (UINT32, Subtable->Buffer); + LocalityBuffer = UtLocalCalloc (Localities); + + /* Compile each locality buffer */ + + FieldList = *PFieldList; + while (FieldList) + { + DtCompileBuffer (LocalityBuffer, + FieldList->Value, FieldList, Localities); + + DtCreateSubtable (LocalityBuffer, Localities, &Subtable); + DtInsertSubtable (ParentTable, Subtable); + FieldList = FieldList->Next; + } + + ACPI_FREE (LocalityBuffer); + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileSrat + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile SRAT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileSrat ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_FIELD *SubtableStart; + ACPI_SUBTABLE_HEADER *SratHeader; + ACPI_DMTABLE_INFO *InfoTable; + + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoSrat, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + while (*PFieldList) + { + SubtableStart = *PFieldList; + Status = DtCompileTable (PFieldList, AcpiDmTableInfoSratHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPushSubtable (Subtable); + + SratHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); + + switch (SratHeader->Type) + { + case ACPI_SRAT_TYPE_CPU_AFFINITY: + InfoTable = AcpiDmTableInfoSrat0; + break; + case ACPI_SRAT_TYPE_MEMORY_AFFINITY: + InfoTable = AcpiDmTableInfoSrat1; + break; + case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: + InfoTable = AcpiDmTableInfoSrat2; + break; + default: + DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "SRAT"); + return (AE_ERROR); + } + + Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + DtPopSubtable (); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetGenericTableInfo + * + * PARAMETERS: Name - Generic type name + * + * RETURN: Info entry + * + * DESCRIPTION: Obtain table info for a generic name entry + * + *****************************************************************************/ + +ACPI_DMTABLE_INFO * +DtGetGenericTableInfo ( + char *Name) +{ + ACPI_DMTABLE_INFO *Info; + UINT32 i; + + + if (!Name) + { + return (NULL); + } + + /* Search info table for name match */ + + for (i = 0; ; i++) + { + Info = AcpiDmTableInfoGeneric[i]; + if (Info->Opcode == ACPI_DMT_EXIT) + { + Info = NULL; + break; + } + + /* Use caseless compare for generic keywords */ + + if (!AcpiUtStricmp (Name, Info->Name)) + { + break; + } + } + + return (Info); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileUefi + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile UEFI. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileUefi ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + UINT16 *DataOffset; + + + /* Compile the predefined portion of the UEFI table */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoUefi, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + DataOffset = (UINT16 *) (Subtable->Buffer + 16); + *DataOffset = sizeof (ACPI_TABLE_UEFI); + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + /* + * Compile the "generic" portion of the UEFI table. This + * part of the table is not predefined and any of the generic + * operators may be used. + */ + + DtCompileGeneric ((void **) PFieldList); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileWdat + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile WDAT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileWdat ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoWdat, AcpiDmTableInfoWdat0); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileXsdt + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile XSDT. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileXsdt ( + void **List) +{ + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD *FieldList = *(DT_FIELD **) List; + UINT64 Address; + + ParentTable = DtPeekSubtable (); + + while (FieldList) + { + DtCompileInteger ((UINT8 *) &Address, FieldList, 8, DT_NON_ZERO); + + DtCreateSubtable ((UINT8 *) &Address, 8, &Subtable); + DtInsertSubtable (ParentTable, Subtable); + FieldList = FieldList->Next; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtCompileGeneric + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile generic unknown table. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileGeneric ( + void **List) +{ + ACPI_STATUS Status; + DT_SUBTABLE *Subtable; + DT_SUBTABLE *ParentTable; + DT_FIELD **PFieldList = (DT_FIELD **) List; + ACPI_DMTABLE_INFO *Info; + + + ParentTable = DtPeekSubtable (); + + /* + * Compile the "generic" portion of the table. This + * part of the table is not predefined and any of the generic + * operators may be used. + */ + + /* Find any and all labels in the entire generic portion */ + + DtDetectAllLabels (*PFieldList); + + /* Now we can actually compile the parse tree */ + + while (*PFieldList) + { + Info = DtGetGenericTableInfo ((*PFieldList)->Name); + if (!Info) + { + sprintf (MsgBuffer, "Generic data type \"%s\" not found", + (*PFieldList)->Name); + DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME, + (*PFieldList), MsgBuffer); + + *PFieldList = (*PFieldList)->Next; + continue; + } + + Status = DtCompileTable (PFieldList, Info, + &Subtable, TRUE); + if (ACPI_SUCCESS (Status)) + { + DtInsertSubtable (ParentTable, Subtable); + } + else + { + *PFieldList = (*PFieldList)->Next; + + if (Status == AE_NOT_FOUND) + { + sprintf (MsgBuffer, "Generic data type \"%s\" not found", + (*PFieldList)->Name); + DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME, + (*PFieldList), MsgBuffer); + } + } + } + + return (AE_OK); +} diff --git a/source/compiler/dttemplate.c b/source/compiler/dttemplate.c new file mode 100644 index 000000000000..27b032fa7b48 --- /dev/null +++ b/source/compiler/dttemplate.c @@ -0,0 +1,374 @@ +/****************************************************************************** + * + * Module Name: dttemplate - ACPI table template generation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "acapps.h" +#include "dtcompiler.h" +#include "dttemplate.h" /* Contains the hex ACPI table templates */ + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dttemplate") + + +/* Local prototypes */ + +static BOOLEAN +AcpiUtIsSpecialTable ( + char *Signature); + +static ACPI_STATUS +DtCreateOneTemplate ( + char *Signature, + ACPI_DMTABLE_DATA *TableData); + +static ACPI_STATUS +DtCreateAllTemplates ( + void); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtIsSpecialTable + * + * PARAMETERS: Signature - ACPI table signature + * + * RETURN: TRUE if signature is a special ACPI table + * + * DESCRIPTION: Check for valid ACPI tables that are not in the main ACPI + * table data structure (AcpiDmTableData). + * + ******************************************************************************/ + +static BOOLEAN +AcpiUtIsSpecialTable ( + char *Signature) +{ + + if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) || + ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS) || + ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME)) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: DtCreateTemplates + * + * PARAMETERS: Signature - ACPI table signature + * + * RETURN: Status + * + * DESCRIPTION: Create one or more template files. + * + ******************************************************************************/ + +ACPI_STATUS +DtCreateTemplates ( + char *Signature) +{ + ACPI_DMTABLE_DATA *TableData; + ACPI_STATUS Status; + + + AslInitializeGlobals (); + AcpiUtStrupr (Signature); + + /* Create all known templates if requested */ + + if (!ACPI_STRNCMP (Signature, "ALL", 3) || + !ACPI_STRCMP (Signature, "*")) + { + Status = DtCreateAllTemplates (); + return (Status); + } + + /* + * Validate signature and get the template data: + * 1) Signature must be 4 characters + * 2) Signature must be a recognized ACPI table + * 3) There must be a template associated with the signature + */ + if (strlen (Signature) != ACPI_NAME_SIZE) + { + fprintf (stderr, "%s, Invalid ACPI table signature\n", Signature); + return (AE_ERROR); + } + + /* + * Some slack for the two strange tables whose name is different than + * their signatures: MADT->APIC and FADT->FACP. + */ + if (!strcmp (Signature, "MADT")) + { + Signature = "APIC"; + } + else if (!strcmp (Signature, "FADT")) + { + Signature = "FACP"; + } + + TableData = AcpiDmGetTableData (Signature); + if (TableData) + { + if (!TableData->Template) + { + fprintf (stderr, "%4.4s, No template available\n", Signature); + return (AE_ERROR); + } + } + else if (!AcpiUtIsSpecialTable (Signature)) + { + fprintf (stderr, + "%4.4s, Unrecognized ACPI table signature\n", Signature); + return (AE_ERROR); + } + + Status = AdInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = DtCreateOneTemplate (Signature, TableData); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: DtCreateAllTemplates + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create all currently defined template files + * + ******************************************************************************/ + +static ACPI_STATUS +DtCreateAllTemplates ( + void) +{ + ACPI_DMTABLE_DATA *TableData; + ACPI_STATUS Status; + + + Status = AdInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + fprintf (stderr, "Creating all supported Template files\n"); + + /* Walk entire ACPI table data structure */ + + for (TableData = AcpiDmTableData; TableData->Signature; TableData++) + { + /* If table has a template, create the template file */ + + if (TableData->Template) + { + Status = DtCreateOneTemplate (TableData->Signature, + TableData); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + /* + * Create the "special ACPI tables: + * 1) DSDT/SSDT are AML tables, not data tables + * 2) FACS and RSDP have non-standard headers + */ + Status = DtCreateOneTemplate (ACPI_SIG_DSDT, NULL); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = DtCreateOneTemplate (ACPI_SIG_SSDT, NULL); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = DtCreateOneTemplate (ACPI_SIG_FACS, NULL); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = DtCreateOneTemplate (ACPI_RSDP_NAME, NULL); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: DtCreateOneTemplate + * + * PARAMETERS: Signature - ACPI signature, NULL terminated. + * TableData - Entry in ACPI table data structure. + * NULL if a special ACPI table. + * + * RETURN: Status + * + * DESCRIPTION: Create one template source file for the requested ACPI table. + * + ******************************************************************************/ + +static ACPI_STATUS +DtCreateOneTemplate ( + char *Signature, + ACPI_DMTABLE_DATA *TableData) +{ + char *DisasmFilename; + FILE *File; + ACPI_STATUS Status = AE_OK; + + + /* New file will have a .asl suffix */ + + DisasmFilename = FlGenerateFilename ( + Signature, FILE_SUFFIX_ASL_CODE); + if (!DisasmFilename) + { + fprintf (stderr, "Could not generate output filename\n"); + return (AE_ERROR); + } + + /* Probably should prompt to overwrite the file */ + + AcpiUtStrlwr (DisasmFilename); + File = fopen (DisasmFilename, "w+"); + if (!File) + { + fprintf (stderr, "Could not open output file %s\n", DisasmFilename); + return (AE_ERROR); + } + + /* Emit the common file header */ + + AcpiOsRedirectOutput (File); + + AcpiOsPrintf ("/*\n"); + AcpiOsPrintf (ACPI_COMMON_HEADER ("iASL Compiler/Disassembler", " * ")); + + AcpiOsPrintf (" * Template for [%4.4s] ACPI Table\n", + Signature); + + /* Dump the actual ACPI table */ + + if (TableData) + { + /* Normal case, tables that appear in AcpiDmTableData */ + + if (Gbl_VerboseTemplates) + { + AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]" + " FieldName : HexFieldValue\n */\n\n"); + } + else + { + AcpiOsPrintf (" * Format: [ByteLength]" + " FieldName : HexFieldValue\n */\n\n"); + } + + AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER, + TableData->Template)); + } + else + { + /* Special ACPI tables - DSDT, SSDT, FACS, RSDP */ + + AcpiOsPrintf (" */\n\n"); + if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) + { + fwrite (TemplateDsdt, sizeof (TemplateDsdt) -1, 1, File); + } + else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT)) + { + fwrite (TemplateSsdt, sizeof (TemplateSsdt) -1, 1, File); + } + else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) + { + AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER, + TemplateFacs)); + } + else if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME)) + { + AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER, + TemplateRsdp)); + } + else + { + fprintf (stderr, + "%4.4s, Unrecognized ACPI table signature\n", Signature); + return (AE_ERROR); + } + } + + fprintf (stderr, + "Created ACPI table template for [%4.4s], written to \"%s\"\n", + Signature, DisasmFilename); + + fclose (File); + AcpiOsRedirectOutput (stdout); + ACPI_FREE (DisasmFilename); + return (Status); +} diff --git a/source/compiler/dttemplate.h b/source/compiler/dttemplate.h new file mode 100644 index 000000000000..4d4370452f59 --- /dev/null +++ b/source/compiler/dttemplate.h @@ -0,0 +1,897 @@ +/****************************************************************************** + * + * Module Name: dttemplate.h - ACPI table template definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __DTTEMPLATE_H +#define __DTTEMPLATE_H + + +/* Special templates for DSDT and SSDT (AML byte-code tables) */ + +const char TemplateDsdt[] = + "DefinitionBlock (\"dsdt.aml\", \"DSDT\", 2, \"Intel\", \"Template\", 0x00000001)\n" + "{\n" + " Method (MAIN, 0, NotSerialized)\n" + " {\n" + " Return (Zero)\n" + " }\n" + "}\n\n"; + +const char TemplateSsdt[] = + "DefinitionBlock (\"ssdt.aml\", \"SSDT\", 2, \"Intel\", \"Template\", 0x00000001)\n" + "{\n" + " Method (MAIN, 0, NotSerialized)\n" + " {\n" + " Return (Zero)\n" + " }\n" + "}\n\n"; + + +/* Templates for ACPI data tables */ + +const unsigned char TemplateAsf[] = +{ + 0x41,0x53,0x46,0x21,0x72,0x00,0x00,0x00, /* 00000000 "ASF!r..." */ + 0x10,0x0B,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x10,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x14,0x00, /* 00000030 "........" */ + 0x00,0x00,0x01,0x0C,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x02,0x00,0x0C,0x00,0x01,0x04,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x03,0x00,0x17,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x84,0x00,0x07,0x00,0x00, /* 00000068 "........" */ + 0x01,0x00 /* 00000070 ".." */ +}; + +const unsigned char TemplateBgrt[] = +{ + 0x42,0x47,0x52,0x54,0x38,0x00,0x00,0x00, /* 00000000 "BGRT8..." */ + 0x01,0x0D,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x23,0x06,0x11,0x20,0x01,0x00,0x00,0x00, /* 00000020 "#.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000030 "........" */ +}; + +const unsigned char TemplateBert[] = +{ + 0x42,0x45,0x52,0x54,0x30,0x00,0x00,0x00, /* 00000000 "BERT0..." */ + 0x01,0x15,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000028 "........" */ +}; + +const unsigned char TemplateBoot[] = +{ + 0x42,0x4F,0x4F,0x54,0x28,0x00,0x00,0x00, /* 00000000 "BOOT(..." */ + 0x01,0x0D,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x04,0x06,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00 /* 00000020 "(.. ...." */ +}; + +const unsigned char TemplateCpep[] = +{ + 0x43,0x50,0x45,0x50,0x34,0x00,0x00,0x00, /* 00000000 "CPEP4..." */ + 0x01,0x0F,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00 /* 00000030 "...." */ +}; + +const unsigned char TemplateDbgp[] = +{ + 0x44,0x42,0x47,0x50,0x34,0x00,0x00,0x00, /* 00000000 "DBGP4..." */ + 0x01,0x1A,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00 /* 00000030 "...." */ +}; + +const unsigned char TemplateDmar[] = +{ + 0x44,0x4D,0x41,0x52,0x8C,0x00,0x00,0x00, /* 00000000 "DMAR...." */ + 0x01,0x15,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x2F,0x01,0x00,0x00, /* 00000020 "(.. /..." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x18,0x00,0x01,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x02,0xFD,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x03,0x08,0x00,0x00,0x08,0xF0,0x1F,0x07, /* 00000040 "........" */ + 0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00, /* 00000048 ".. ....." */ + 0x00,0x10,0xC2,0x78,0x00,0x00,0x00,0x00, /* 00000050 "...x...." */ + 0xFF,0x3F,0xC2,0x78,0x00,0x00,0x00,0x00, /* 00000058 ".?.x...." */ + 0x01,0x08,0x00,0x00,0x00,0x00,0x1D,0x00, /* 00000060 "........" */ + 0x02,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x02,0x08,0x00,0x00,0x00,0x00,0x01,0x00, /* 00000070 "........" */ + 0x03,0x00,0x14,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x02,0xFD,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x00,0x00,0x00,0x00 /* 00000088 "...." */ +}; + +const unsigned char TemplateEcdt[] = +{ + 0x45,0x43,0x44,0x54,0x42,0x00,0x00,0x00, /* 00000000 "ECDTB..." */ + 0x01,0x2D,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".-INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x01,0x08,0x00,0x00, /* 00000020 "(.. ...." */ + 0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "f......." */ + 0x01,0x08,0x00,0x00,0x62,0x00,0x00,0x00, /* 00000030 "....b..." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x09,0x00 /* 00000040 ".." */ +}; + +const unsigned char TemplateEinj[] = +{ + 0x45,0x49,0x4E,0x4A,0x30,0x01,0x00,0x00, /* 00000000 "EINJ0..." */ + 0x01,0x09,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x30,0x00,0x00,0x00, /* 00000020 "(.. 0..." */ + 0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000030 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000048 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000050 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000068 "........" */ + 0x02,0x02,0x01,0x00,0x00,0x40,0x00,0x04, /* 00000070 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000088 "........" */ + 0x03,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000090 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000A8 "........" */ + 0x04,0x03,0x01,0x00,0x00,0x40,0x00,0x04, /* 000000B0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000C8 "........" */ + 0x05,0x03,0x01,0x00,0x01,0x10,0x00,0x02, /* 000000D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000E8 "........" */ + 0x06,0x01,0x00,0x00,0x00,0x40,0x00,0x04, /* 000000F0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000100 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000108 "........" */ + 0x07,0x00,0x01,0x00,0x00,0x40,0x00,0x04, /* 00000110 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000118 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000120 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF /* 00000128 "........" */ +}; + +const unsigned char TemplateErst[] = +{ + 0x45,0x52,0x53,0x54,0x30,0x02,0x00,0x00, /* 00000000 "ERST0..." */ + 0x01,0xAB,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x30,0x00,0x00,0x00, /* 00000020 "(.. 0..." */ + 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x03,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000030 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000048 "........" */ + 0x01,0x03,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000050 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000068 "........" */ + 0x02,0x03,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000070 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000088 "........" */ + 0x03,0x04,0x01,0x00,0x00,0x40,0x00,0x04, /* 00000090 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000A8 "........" */ + 0x04,0x02,0x00,0x00,0x00,0x40,0x00,0x04, /* 000000B0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000C8 "........" */ + 0x05,0x03,0x00,0x00,0x01,0x08,0x00,0x01, /* 000000D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000000E8 "........" */ + 0x06,0x01,0x00,0x00,0x00,0x40,0x00,0x04, /* 000000F0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000100 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000108 "........" */ + 0x07,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000110 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000118 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000120 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000128 "........" */ + 0x08,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000130 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000138 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000140 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000148 "........" */ + 0x09,0x02,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000150 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000158 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000160 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000168 "........" */ + 0x0A,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000170 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000178 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000180 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000188 "........" */ + 0x0B,0x03,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000190 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000198 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001A0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000001A8 "........" */ + 0x0C,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 000001B0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001B8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001C0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000001C8 "........" */ + 0x0D,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 000001D0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001E0 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 000001E8 "........" */ + 0x0E,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 000001F0 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000200 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 00000208 "........" */ + 0x0F,0x00,0x00,0x00,0x00,0x40,0x00,0x04, /* 00000210 ".....@.." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000218 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000220 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF /* 00000228 "........" */ +}; + +const unsigned char TemplateFacs[] = +{ + 0x46,0x41,0x43,0x53,0x40,0x00,0x00,0x00, /* 00000000 "FACS@..." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000008 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000010 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000018 "........" */ + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000020 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000038 "........" */ +}; + +/* Version 5 FADT */ + +const unsigned char TemplateFadt[] = +{ + 0x46,0x41,0x43,0x50,0x0C,0x01,0x00,0x00, /* 00000000 "FACP...." */ + 0x05,0x18,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x23,0x11,0x11,0x20,0x01,0x00,0x00,0x00, /* 00000020 "#.. ...." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000048 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x04,0x02,0x01,0x04,0x08,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x01, /* 00000070 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000080 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000088 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x02, /* 00000090 "..... .." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x10,0x00,0x02, /* 000000A8 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00, /* 000000C0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */ + 0x01,0x20,0x00,0x03,0x01,0x00,0x00,0x00, /* 000000D0 ". ......" */ + 0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x01, /* 000000D8 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x01, /* 000000F0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x01,0x08,0x00,0x01,0x00,0x00,0x00,0x00, /* 00000100 "........" */ + 0x00,0x00,0x00,0x00 /* 00000108 "...." */ +}; + +const unsigned char TemplateFpdt[] = +{ + 0x46,0x50,0x44,0x54,0x64,0x00,0x00,0x00, /* 00000000 "FPDTd..." */ + 0x01,0xBD,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x04,0x08,0x11,0x20,0x00,0x00,0x30,0x01, /* 00000020 "... ..0." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x01, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00 /* 00000060 "...." */ +}; + +const unsigned char TemplateGtdt[] = +{ + 0x47,0x54,0x44,0x54,0x50,0x00,0x00,0x00, /* 00000000 "GTDTP..." */ + 0x01,0xF1,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x23,0x06,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "#.. ...." */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000048 "........" */ +}; + +const unsigned char TemplateHest[] = +{ + 0x48,0x45,0x53,0x54,0xD4,0x01,0x00,0x00, /* 00000000 "HEST...." */ + 0x01,0x20,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ". INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x04,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, /* 00000028 "........" */ + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01, /* 00000088 "........" */ + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000090 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 000000D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01, /* 000000F0 "........" */ + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000100 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000108 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000110 "........" */ + 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00, /* 00000118 "........" */ + 0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00, /* 00000120 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000128 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000130 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000138 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000140 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000148 "........" */ + 0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x00, /* 00000150 "........" */ + 0xFF,0xFF,0x00,0x01,0x01,0x00,0x00,0x00, /* 00000158 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x00, /* 00000160 "........" */ + 0x00,0x40,0x00,0x04,0x00,0x00,0x00,0x00, /* 00000168 ".@......" */ + 0x00,0x00,0x00,0x00,0x03,0x1C,0x00,0x00, /* 00000170 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000178 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000180 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000188 "........" */ + 0x00,0x10,0x00,0x00,0x09,0x00,0x03,0x00, /* 00000190 "........" */ + 0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00, /* 00000198 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x00, /* 000001A0 "........" */ + 0x00,0x40,0x00,0x04,0x00,0x00,0x00,0x00, /* 000001A8 ".@......" */ + 0x00,0x00,0x00,0x00,0x04,0x1C,0x00,0x00, /* 000001B0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001B8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001C0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001C8 "........" */ + 0x00,0x10,0x00,0x00 /* 000001D0 "...." */ +}; + +const unsigned char TemplateHpet[] = +{ + 0x48,0x50,0x45,0x54,0x38,0x00,0x00,0x00, /* 00000000 "HPET8..." */ + 0x01,0x09,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000030 "........" */ +}; + +const unsigned char TemplateIvrs[] = +{ + 0x49,0x56,0x52,0x53,0xBC,0x00,0x00,0x00, /* 00000000 "IVRS...." */ + 0x01,0x87,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x10,0x14,0x34,0x00,0x00,0x00,0x00,0x00, /* 00000030 "..4....." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00, /* 00000048 "....@..." */ + 0x00,0x00,0x00,0x00,0x42,0x00,0x00,0x00, /* 00000050 "....B..." */ + 0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00, /* 00000058 "....H..." */ + 0x00,0x00,0x00,0x00,0x20,0x08,0x20,0x00, /* 00000060 ".... . ." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x21,0x04,0x20,0x00, /* 00000080 "....!. ." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000088 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000090 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x10,0x14,0x18,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x00,0x00,0x00,0x00 /* 000000B8 "...." */ +}; + +/* MADT with ACPI 5.0 subtables */ + +const unsigned char TemplateMadt[] = +{ + 0x41,0x50,0x49,0x43,0xF6,0x00,0x00,0x00, /* 00000000 "APIC...." */ + 0x01,0xB0,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x23,0x06,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "#.. ...." */ + 0x01,0x00,0x00,0x00,0x00,0x08,0x00,0x00, /* 00000028 "........" */ + 0x01,0x00,0x00,0x00,0x01,0x0C,0x01,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x02,0x0A,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x03,0x08,0x0D,0x00,0x01,0x00, /* 00000048 "........" */ + 0x00,0x00,0x04,0x06,0x00,0x05,0x00,0x01, /* 00000050 "........" */ + 0x05,0x0C,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x06,0x10,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x07,0x16,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x5C,0x43,0x50,0x55, /* 00000080 "....\CPU" */ + 0x30,0x00,0x08,0x10,0x05,0x00,0x00,0x00, /* 00000088 "0......." */ + 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00, /* 00000090 "........" */ + 0x00,0x00,0x09,0x10,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x0A,0x0C,0x05,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x28, /* 000000B0 ".......(" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, /* 000000C0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00 /* 000000F0 "......" */ +}; + +const unsigned char TemplateMcfg[] = +{ + 0x4D,0x43,0x46,0x47,0x3C,0x00,0x00,0x00, /* 00000000 "MCFG<..." */ + 0x01,0x19,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00 /* 00000038 "...." */ +}; + +const unsigned char TemplateMchi[] = +{ + 0x4D,0x43,0x48,0x49,0x45,0x00,0x00,0x00, /* 00000000 "MCHIE..." */ + 0x01,0xE4,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x15,0x07,0x00,0x02,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x01,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00 /* 00000040 "....." */ +}; + +const unsigned char TemplateMpst[] = +{ + 0x4D,0x50,0x53,0x54,0x6E,0x00,0x00,0x00, /* 00000000 "MPSTn..." */ + 0x01,0x98,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x04,0x08,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "... ...." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x02,0x03,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x01,0x00,0x41,0x00,0x00,0x00,0x00,0x00, /* 00000050 "..A....." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00 /* 00000068 "......" */ +}; + +const unsigned char TemplateMsct[] = +{ + 0x4D,0x53,0x43,0x54,0x90,0x00,0x00,0x00, /* 00000000 "MSCT...." */ + 0x01,0xB7,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x38,0x00,0x00,0x00, /* 00000020 "(.. 8..." */ + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0x00, /* 00000030 "........" */ + 0x01,0x16,0x00,0x00,0x00,0x00,0x03,0x00, /* 00000038 "........" */ + 0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x16, /* 00000048 "..@....." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x16,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x01,0x16,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000088 "........" */ +}; + +const unsigned char TemplatePmtt[] = +{ + 0x50,0x4D,0x54,0x54,0xB4,0x00,0x00,0x00, /* 00000000 "PMTT...." */ + 0x01,0x3A,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".:INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x26,0x08,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "&.. ...." */ + 0x00,0x00,0x80,0x00,0x01,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x54,0x00, /* 00000030 "......T." */ + 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x02,0x00,0x14,0x00,0x02,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x02,0x00,0x14,0x00, /* 00000070 "........" */ + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x01,0x00,0x20,0x00,0x01,0x00,0x00,0x00, /* 00000088 ".. ....." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000090 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x0C,0x00,0x01,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00 /* 000000B0 "...." */ +}; + +const unsigned char TemplateRsdp[] = +{ + 0x52,0x53,0x44,0x20,0x50,0x54,0x52,0x20, /* 00000000 "RSD PTR " */ + 0x43,0x49,0x4E,0x54,0x45,0x4C,0x20,0x02, /* 00000008 "CINTEL ." */ + 0x00,0x00,0x00,0x00,0x24,0x00,0x00,0x00, /* 00000010 "....$..." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000018 "........" */ + 0xDC,0x00,0x00,0x00 /* 00000020 "...." */ +}; + +const unsigned char TemplateRsdt[] = +{ + 0x52,0x53,0x44,0x54,0x44,0x00,0x00,0x00, /* 00000000 "RSDTD..." */ + 0x01,0xB1,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x10,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x20,0x00,0x00,0x00,0x30,0x00,0x00,0x00, /* 00000028 " ...0..." */ + 0x40,0x00,0x00,0x00,0x50,0x00,0x00,0x00, /* 00000030 "@...P..." */ + 0x60,0x00,0x00,0x00,0x70,0x00,0x00,0x00, /* 00000038 "`...p..." */ + 0x80,0x00,0x00,0x00 /* 00000040 "...." */ +}; + +const unsigned char TemplateS3pt[] = +{ + 0x53,0x33,0x50,0x54,0x34,0x00,0x00,0x00, /* 00000000 "S3PT4..." */ + 0x00,0x00,0x18,0x01,0x00,0x00,0x00,0x00, /* 00000008 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000010 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000018 "........" */ + 0x01,0x00,0x14,0x01,0x00,0x00,0x00,0x00, /* 00000020 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00 /* 00000030 "...." */ +}; + +const unsigned char TemplateSbst[] = +{ + 0x53,0x42,0x53,0x54,0x30,0x00,0x00,0x00, /* 00000000 "SBST0..." */ + 0x01,0x06,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000028 "........" */ +}; + +const unsigned char TemplateSlic[] = +{ + 0x53,0x4C,0x49,0x43,0x76,0x01,0x00,0x00, /* 00000000 "SLICv..." */ + 0x01,0x07,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x11,0x02,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "... ...." */ + 0x9C,0x00,0x00,0x00,0x06,0x02,0x00,0x00, /* 00000028 "........" */ + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31, /* 00000030 ".$..RSA1" */ + 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000088 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000090 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x01,0x00,0x00,0x00,0xB6,0x00,0x00,0x00, /* 000000C0 "........" */ + 0x00,0x00,0x02,0x00,0x49,0x4E,0x54,0x45, /* 000000C8 "....INTE" */ + 0x4C,0x20,0x54,0x45,0x4D,0x50,0x4C,0x41, /* 000000D0 "L TEMPLA" */ + 0x54,0x45,0x57,0x49,0x4E,0x44,0x4F,0x57, /* 000000D8 "TEWINDOW" */ + 0x53,0x20,0x01,0x00,0x02,0x00,0x00,0x00, /* 000000E0 "S ......" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000100 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000108 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000110 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000118 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000120 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000128 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000130 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000138 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000140 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000148 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000150 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000158 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000160 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000168 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00 /* 00000170 "......" */ +}; + +const unsigned char TemplateSlit[] = +{ + 0x53,0x4C,0x49,0x54,0xBC,0x01,0x00,0x00, /* 00000000 "SLIT...." */ + 0x01,0x00,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x16,0x03,0x11,0x20,0x14,0x00,0x00,0x00, /* 00000020 "... ...." */ + 0x00,0x00,0x00,0x00,0x0A,0x10,0x16,0x17, /* 00000028 "........" */ + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, /* 00000030 "........" */ + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, /* 00000038 " !"#$%&'" */ + 0x10,0x0A,0x15,0x16,0x17,0x18,0x19,0x1A, /* 00000040 "........" */ + 0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, /* 00000048 "..... !"" */ + 0x23,0x24,0x25,0x26,0x16,0x15,0x0A,0x10, /* 00000050 "#$%&...." */ + 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D, /* 00000058 "........" */ + 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25, /* 00000060 ".. !"#$%" */ + 0x17,0x16,0x10,0x0A,0x15,0x16,0x17,0x18, /* 00000068 "........" */ + 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, /* 00000070 "....... " */ + 0x21,0x22,0x23,0x24,0x18,0x17,0x16,0x15, /* 00000078 "!"#$...." */ + 0x0A,0x10,0x16,0x17,0x18,0x19,0x1A,0x1B, /* 00000080 "........" */ + 0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23, /* 00000088 ".... !"#" */ + 0x19,0x18,0x17,0x16,0x10,0x0A,0x15,0x16, /* 00000090 "........" */ + 0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E, /* 00000098 "........" */ + 0x1F,0x20,0x21,0x22,0x1A,0x19,0x18,0x17, /* 000000A0 ". !"...." */ + 0x16,0x15,0x0A,0x10,0x16,0x17,0x18,0x19, /* 000000A8 "........" */ + 0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21, /* 000000B0 "...... !" */ + 0x1B,0x1A,0x19,0x18,0x17,0x16,0x10,0x0A, /* 000000B8 "........" */ + 0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C, /* 000000C0 "........" */ + 0x1D,0x1E,0x1F,0x20,0x1C,0x1B,0x1A,0x19, /* 000000C8 "... ...." */ + 0x18,0x17,0x16,0x15,0x0A,0x10,0x16,0x17, /* 000000D0 "........" */ + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, /* 000000D8 "........" */ + 0x1D,0x1C,0x1B,0x1A,0x19,0x18,0x17,0x16, /* 000000E0 "........" */ + 0x10,0x0A,0x15,0x16,0x17,0x18,0x19,0x1A, /* 000000E8 "........" */ + 0x1B,0x1C,0x1D,0x1E,0x1E,0x1D,0x1C,0x1B, /* 000000F0 "........" */ + 0x1A,0x19,0x18,0x17,0x16,0x15,0x0A,0x10, /* 000000F8 "........" */ + 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D, /* 00000100 "........" */ + 0x1F,0x1E,0x1D,0x1C,0x1B,0x1A,0x19,0x18, /* 00000108 "........" */ + 0x17,0x16,0x10,0x0A,0x15,0x16,0x17,0x18, /* 00000110 "........" */ + 0x19,0x1A,0x1B,0x1C,0x20,0x1F,0x1E,0x1D, /* 00000118 ".... ..." */ + 0x1C,0x1B,0x1A,0x19,0x18,0x17,0x16,0x15, /* 00000120 "........" */ + 0x0A,0x10,0x16,0x17,0x18,0x19,0x1A,0x1B, /* 00000128 "........" */ + 0x21,0x20,0x1F,0x1E,0x1D,0x1C,0x1B,0x1A, /* 00000130 "! ......" */ + 0x19,0x18,0x17,0x16,0x10,0x0A,0x15,0x16, /* 00000138 "........" */ + 0x17,0x18,0x19,0x1A,0x22,0x21,0x20,0x1F, /* 00000140 "...."! ." */ + 0x1E,0x1D,0x1C,0x1B,0x1A,0x19,0x18,0x17, /* 00000148 "........" */ + 0x16,0x15,0x0A,0x10,0x16,0x17,0x18,0x19, /* 00000150 "........" */ + 0x23,0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C, /* 00000158 "#"! ...." */ + 0x1B,0x1A,0x19,0x18,0x17,0x16,0x10,0x0A, /* 00000160 "........" */ + 0x15,0x16,0x17,0x18,0x24,0x23,0x22,0x21, /* 00000168 "....$#"!" */ + 0x20,0x1F,0x1E,0x1D,0x1C,0x1B,0x1A,0x19, /* 00000170 " ......." */ + 0x18,0x17,0x16,0x15,0x0A,0x10,0x16,0x17, /* 00000178 "........" */ + 0x25,0x24,0x23,0x22,0x21,0x20,0x1F,0x1E, /* 00000180 "%$#"! .." */ + 0x1D,0x1C,0x1B,0x1A,0x19,0x18,0x17,0x16, /* 00000188 "........" */ + 0x10,0x0A,0x15,0x16,0x26,0x25,0x24,0x23, /* 00000190 "....&%$#" */ + 0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C,0x1B, /* 00000198 ""! ....." */ + 0x1A,0x19,0x18,0x17,0x16,0x15,0x0A,0x10, /* 000001A0 "........" */ + 0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20, /* 000001A8 "'&%$#"! " */ + 0x1F,0x1E,0x1D,0x1C,0x1B,0x1A,0x19,0x18, /* 000001B0 "........" */ + 0x17,0x16,0x10,0x0A /* 000001B8 "...." */ +}; + +const unsigned char TemplateSpcr[] = +{ + 0x53,0x50,0x43,0x52,0x50,0x00,0x00,0x00, /* 00000000 "SPCRP..." */ + 0x01,0xE3,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000048 "........" */ +}; + +const unsigned char TemplateSpmi[] = +{ + 0x53,0x50,0x4D,0x49,0x41,0x00,0x00,0x00, /* 00000000 "SPMIA..." */ + 0x04,0xED,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00 /* 00000040 "." */ +}; + +const unsigned char TemplateSrat[] = +{ + 0x53,0x52,0x41,0x54,0x80,0x00,0x00,0x00, /* 00000000 "SRAT...." */ + 0x03,0x5A,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".ZINTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x01,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x01,0x28,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 ".(......" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0xFC,0x09,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x02,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000070 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000078 "........" */ +}; + +const unsigned char TemplateTcpa[] = +{ + 0x54,0x43,0x50,0x41,0x32,0x00,0x00,0x00, /* 00000000 "TCPA2..." */ + 0x01,0x67,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".gINTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x80,0x31,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 ".1..INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00 /* 00000030 ".." */ +}; + +const unsigned char TemplateUefi[] = +{ + 0x55,0x45,0x46,0x49,0x36,0x00,0x00,0x00, /* 00000000 "UEFI6..." */ + 0x01,0x9B,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x01,0x02,0x03, /* 00000020 "(.. ...." */ + 0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, /* 00000028 "........" */ + 0x0C,0x0D,0x0E,0x0F,0x00,0x00 /* 00000030 "......" */ +}; + +const unsigned char TemplateWaet[] = +{ + 0x57,0x41,0x45,0x54,0x28,0x00,0x00,0x00, /* 00000000 "WAET(..." */ + 0x01,0x19,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00 /* 00000020 "(.. ...." */ +}; + +const unsigned char TemplateWdat[] = +{ + 0x57,0x44,0x41,0x54,0x5C,0x00,0x00,0x00, /* 00000000 "WDAT\..." */ + 0x01,0xE3,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x20,0x00,0x00,0x00, /* 00000020 "(.. ..." */ + 0xFF,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00, /* 00000028 "........" */ + 0x58,0x02,0x00,0x00,0xFF,0x03,0x00,0x00, /* 00000030 "X......." */ + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x0E,0x00,0x00,0x00,0x01,0x02,0x00,0x00, /* 00000040 "........" */ + 0x01,0x10,0x00,0x02,0x60,0x04,0x00,0x00, /* 00000048 "....`..." */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000050 "........" */ + 0x01,0x00,0x00,0x00 /* 00000058 "...." */ +}; + +const unsigned char TemplateWddt[] = +{ + 0x57,0x44,0x44,0x54,0x40,0x00,0x00,0x00, /* 00000000 "WDDT@..." */ + 0x01,0x00,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000038 "........" */ +}; + +const unsigned char TemplateWdrt[] = +{ + 0x57,0x44,0x52,0x54,0x47,0x00,0x00,0x00, /* 00000000 "WDRTG..." */ + 0x01,0xB0,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x00,0x20,0x00,0x00, /* 00000020 "(.. . .." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 ". ......" */ + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0xFF,0xFF,0x00 /* 00000040 "......." */ +}; + +const unsigned char TemplateXsdt[] = +{ + 0x58,0x53,0x44,0x54,0x64,0x00,0x00,0x00, /* 00000000 "XSDTd..." */ + 0x01,0x8B,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x28,0x05,0x10,0x20,0x10,0x00,0x00,0x00, /* 00000020 "(.. ...." */ + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, /* 00000028 ".... ..." */ + 0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00, /* 00000030 "....0..." */ + 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00, /* 00000038 "....@..." */ + 0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00, /* 00000040 "....P..." */ + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00, /* 00000048 "....`..." */ + 0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00, /* 00000050 "....p..." */ + 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00 /* 00000060 "...." */ +}; + +#endif diff --git a/source/compiler/dtutils.c b/source/compiler/dtutils.c new file mode 100644 index 000000000000..45bc4ff0c6cf --- /dev/null +++ b/source/compiler/dtutils.c @@ -0,0 +1,882 @@ +/****************************************************************************** + * + * Module Name: dtutils.c - Utility routines for the data table compiler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DTUTILS_C__ + +#include "aslcompiler.h" +#include "dtcompiler.h" +#include "actables.h" + +#define _COMPONENT DT_COMPILER + ACPI_MODULE_NAME ("dtutils") + +/* Local prototypes */ + +static void +DtSum ( + DT_SUBTABLE *Subtable, + void *Context, + void *ReturnValue); + + +/****************************************************************************** + * + * FUNCTION: DtError + * + * PARAMETERS: Level - Seriousness (Warning/error, etc.) + * MessageId - Index into global message buffer + * Op - Parse node where error happened + * ExtraMessage - additional error message + * + * RETURN: None + * + * DESCRIPTION: Common error interface for data table compiler + * + *****************************************************************************/ + +void +DtError ( + UINT8 Level, + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage) +{ + + switch (Level) + { + case ASL_WARNING2: + case ASL_WARNING3: + if (Gbl_WarningLevel < Level) + { + return; + } + break; + + default: + break; + } + + if (FieldObject) + { + AslCommonError (Level, MessageId, + FieldObject->Line, + FieldObject->Line, + FieldObject->ByteOffset, + FieldObject->Column, + Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage); + } + else + { + AslCommonError (Level, MessageId, 0, + 0, 0, 0, 0, ExtraMessage); + } +} + + +/****************************************************************************** + * + * FUNCTION: DtNameError + * + * PARAMETERS: Level - Seriousness (Warning/error, etc.) + * MessageId - Index into global message buffer + * Op - Parse node where error happened + * ExtraMessage - additional error message + * + * RETURN: None + * + * DESCRIPTION: Error interface for named objects + * + *****************************************************************************/ + +void +DtNameError ( + UINT8 Level, + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage) +{ + + switch (Level) + { + case ASL_WARNING2: + case ASL_WARNING3: + if (Gbl_WarningLevel < Level) + { + return; + } + break; + + default: + break; + } + + if (FieldObject) + { + AslCommonError (Level, MessageId, + FieldObject->Line, + FieldObject->Line, + FieldObject->ByteOffset, + FieldObject->NameColumn, + Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage); + } + else + { + AslCommonError (Level, MessageId, 0, + 0, 0, 0, 0, ExtraMessage); + } +} + + +/******************************************************************************* + * + * FUNCTION: DtFatal + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump the error log and abort the compiler. Used for serious + * compile or I/O errors + * + ******************************************************************************/ + +void +DtFatal ( + UINT8 MessageId, + DT_FIELD *FieldObject, + char *ExtraMessage) +{ + + DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage); + +/* + * TBD: remove this entire function, DtFatal + * + * We cannot abort the compiler on error, because we may be compiling a + * list of files. We must move on to the next file. + */ +#ifdef __OBSOLETE + CmCleanupAndExit (); + exit (1); +#endif +} + + +/****************************************************************************** + * + * FUNCTION: DtStrtoul64 + * + * PARAMETERS: String - Null terminated string + * ReturnInteger - Where the converted integer is returned + * + * RETURN: Status + * + * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned + * value. Assumes no leading "0x" for the constant. + * + * Portability note: The reason this function exists is because a 64-bit + * sscanf is not available in all environments. + * + *****************************************************************************/ + +ACPI_STATUS +DtStrtoul64 ( + char *String, + UINT64 *ReturnInteger) +{ + char *ThisChar = String; + UINT32 ThisDigit; + UINT64 ReturnValue = 0; + int DigitCount = 0; + + + /* Skip over any white space in the buffer */ + + while ((*ThisChar == ' ') || (*ThisChar == '\t')) + { + ThisChar++; + } + + /* Skip leading zeros */ + + while ((*ThisChar) == '0') + { + ThisChar++; + } + + /* Convert character-by-character */ + + while (*ThisChar) + { + if (ACPI_IS_DIGIT (*ThisChar)) + { + /* Convert ASCII 0-9 to Decimal value */ + + ThisDigit = ((UINT8) *ThisChar) - '0'; + } + else /* Letter */ + { + ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar); + if (!ACPI_IS_XDIGIT ((char) ThisDigit)) + { + /* Not A-F */ + + return (AE_BAD_CHARACTER); + } + + /* Convert ASCII Hex char (A-F) to value */ + + ThisDigit = (ThisDigit - 'A') + 10; + } + + /* Insert the 4-bit hex digit */ + + ReturnValue <<= 4; + ReturnValue += ThisDigit; + + ThisChar++; + DigitCount++; + if (DigitCount > 16) + { + /* Value is too large (> 64 bits/8 bytes/16 hex digits) */ + + return (AE_LIMIT); + } + } + + *ReturnInteger = ReturnValue; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetFileSize + * + * PARAMETERS: Handle - Open file handler + * + * RETURN: Current file size + * + * DESCRIPTION: Get the current size of a file. Seek to the EOF and get the + * offset. Seek back to the original location. + * + *****************************************************************************/ + +UINT32 +DtGetFileSize ( + FILE *Handle) +{ + int CurrentOffset; + int LastOffset; + + + CurrentOffset = ftell (Handle); + fseek (Handle, 0, SEEK_END); + LastOffset = ftell (Handle); + fseek (Handle, CurrentOffset, SEEK_SET); + + return ((UINT32) LastOffset); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetFieldValue + * + * PARAMETERS: Field - Current field list pointer + * + * RETURN: Field value + * + * DESCRIPTION: Get field value + * + *****************************************************************************/ + +char * +DtGetFieldValue ( + DT_FIELD *Field) +{ + if (!Field) + { + return (NULL); + } + + return (Field->Value); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetFieldType + * + * PARAMETERS: Info - Data table info + * + * RETURN: Field type + * + * DESCRIPTION: Get field type + * + *****************************************************************************/ + +UINT8 +DtGetFieldType ( + ACPI_DMTABLE_INFO *Info) +{ + UINT8 Type; + + + /* DT_FLAG means that this is the start of a block of flag bits */ + /* TBD - we can make these a separate opcode later */ + + if (Info->Flags & DT_FLAG) + { + return (DT_FIELD_TYPE_FLAGS_INTEGER); + } + + /* Type is based upon the opcode for this field in the info table */ + + switch (Info->Opcode) + { + case ACPI_DMT_FLAG0: + case ACPI_DMT_FLAG1: + case ACPI_DMT_FLAG2: + case ACPI_DMT_FLAG3: + case ACPI_DMT_FLAG4: + case ACPI_DMT_FLAG5: + case ACPI_DMT_FLAG6: + case ACPI_DMT_FLAG7: + case ACPI_DMT_FLAGS0: + case ACPI_DMT_FLAGS1: + case ACPI_DMT_FLAGS2: + case ACPI_DMT_FLAGS4: + Type = DT_FIELD_TYPE_FLAG; + break; + + case ACPI_DMT_NAME4: + case ACPI_DMT_SIG: + case ACPI_DMT_NAME6: + case ACPI_DMT_NAME8: + case ACPI_DMT_STRING: + Type = DT_FIELD_TYPE_STRING; + break; + + case ACPI_DMT_BUFFER: + case ACPI_DMT_BUF7: + case ACPI_DMT_BUF16: + case ACPI_DMT_BUF128: + case ACPI_DMT_PCI_PATH: + Type = DT_FIELD_TYPE_BUFFER; + break; + + case ACPI_DMT_GAS: + case ACPI_DMT_HESTNTFY: + Type = DT_FIELD_TYPE_INLINE_SUBTABLE; + break; + + case ACPI_DMT_UNICODE: + Type = DT_FIELD_TYPE_UNICODE; + break; + + case ACPI_DMT_UUID: + Type = DT_FIELD_TYPE_UUID; + break; + + case ACPI_DMT_DEVICE_PATH: + Type = DT_FIELD_TYPE_DEVICE_PATH; + break; + + case ACPI_DMT_LABEL: + Type = DT_FIELD_TYPE_LABEL; + break; + + default: + Type = DT_FIELD_TYPE_INTEGER; + break; + } + + return (Type); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetBufferLength + * + * PARAMETERS: Buffer - List of integers, + * for example "10 3A 4F 2E" + * + * RETURN: Count of integer + * + * DESCRIPTION: Get length of bytes needed to store the integers + * + *****************************************************************************/ + +UINT32 +DtGetBufferLength ( + char *Buffer) +{ + UINT32 ByteLength = 0; + + + while (*Buffer) + { + if (*Buffer == ' ') + { + ByteLength++; + + while (*Buffer == ' ') + { + Buffer++; + } + } + + Buffer++; + } + + return (++ByteLength); +} + + +/****************************************************************************** + * + * FUNCTION: DtGetFieldLength + * + * PARAMETERS: Field - Current field + * Info - Data table info + * + * RETURN: Field length + * + * DESCRIPTION: Get length of bytes needed to compile the field + * + * Note: This function must remain in sync with AcpiDmDumpTable. + * + *****************************************************************************/ + +UINT32 +DtGetFieldLength ( + DT_FIELD *Field, + ACPI_DMTABLE_INFO *Info) +{ + UINT32 ByteLength = 0; + char *Value; + + + /* Length is based upon the opcode for this field in the info table */ + + switch (Info->Opcode) + { + case ACPI_DMT_FLAG0: + case ACPI_DMT_FLAG1: + case ACPI_DMT_FLAG2: + case ACPI_DMT_FLAG3: + case ACPI_DMT_FLAG4: + case ACPI_DMT_FLAG5: + case ACPI_DMT_FLAG6: + case ACPI_DMT_FLAG7: + case ACPI_DMT_FLAGS0: + case ACPI_DMT_FLAGS1: + case ACPI_DMT_FLAGS2: + case ACPI_DMT_FLAGS4: + case ACPI_DMT_LABEL: + case ACPI_DMT_EXTRA_TEXT: + ByteLength = 0; + break; + + case ACPI_DMT_UINT8: + case ACPI_DMT_CHKSUM: + case ACPI_DMT_SPACEID: + case ACPI_DMT_ACCWIDTH: + case ACPI_DMT_IVRS: + case ACPI_DMT_MADT: + case ACPI_DMT_PMTT: + case ACPI_DMT_SRAT: + case ACPI_DMT_ASF: + case ACPI_DMT_HESTNTYP: + case ACPI_DMT_FADTPM: + case ACPI_DMT_EINJACT: + case ACPI_DMT_EINJINST: + case ACPI_DMT_ERSTACT: + case ACPI_DMT_ERSTINST: + ByteLength = 1; + break; + + case ACPI_DMT_UINT16: + case ACPI_DMT_DMAR: + case ACPI_DMT_HEST: + case ACPI_DMT_PCI_PATH: + ByteLength = 2; + break; + + case ACPI_DMT_UINT24: + ByteLength = 3; + break; + + case ACPI_DMT_UINT32: + case ACPI_DMT_NAME4: + case ACPI_DMT_SLIC: + case ACPI_DMT_SIG: + ByteLength = 4; + break; + + case ACPI_DMT_UINT40: + ByteLength = 5; + break; + + case ACPI_DMT_UINT48: + case ACPI_DMT_NAME6: + ByteLength = 6; + break; + + case ACPI_DMT_UINT56: + case ACPI_DMT_BUF7: + ByteLength = 7; + break; + + case ACPI_DMT_UINT64: + case ACPI_DMT_NAME8: + ByteLength = 8; + break; + + case ACPI_DMT_STRING: + Value = DtGetFieldValue (Field); + if (Value) + { + ByteLength = ACPI_STRLEN (Value) + 1; + } + else + { /* At this point, this is a fatal error */ + + sprintf (MsgBuffer, "Expected \"%s\"", Info->Name); + DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); + return (0); + } + break; + + case ACPI_DMT_GAS: + ByteLength = sizeof (ACPI_GENERIC_ADDRESS); + break; + + case ACPI_DMT_HESTNTFY: + ByteLength = sizeof (ACPI_HEST_NOTIFY); + break; + + case ACPI_DMT_BUFFER: + Value = DtGetFieldValue (Field); + if (Value) + { + ByteLength = DtGetBufferLength (Value); + } + else + { /* At this point, this is a fatal error */ + + sprintf (MsgBuffer, "Expected \"%s\"", Info->Name); + DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); + return (0); + } + break; + + case ACPI_DMT_BUF16: + case ACPI_DMT_UUID: + ByteLength = 16; + break; + + case ACPI_DMT_BUF128: + ByteLength = 128; + break; + + case ACPI_DMT_UNICODE: + Value = DtGetFieldValue (Field); + + /* TBD: error if Value is NULL? (as below?) */ + + ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16); + break; + + default: + DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode"); + return (0); + } + + return (ByteLength); +} + + +/****************************************************************************** + * + * FUNCTION: DtSum + * + * PARAMETERS: DT_WALK_CALLBACK: + * Subtable - Subtable + * Context - Unused + * ReturnValue - Store the checksum of subtable + * + * RETURN: Status + * + * DESCRIPTION: Get the checksum of subtable + * + *****************************************************************************/ + +static void +DtSum ( + DT_SUBTABLE *Subtable, + void *Context, + void *ReturnValue) +{ + UINT8 Checksum; + UINT8 *Sum = ReturnValue; + + + Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length); + *Sum = (UINT8) (*Sum + Checksum); +} + + +/****************************************************************************** + * + * FUNCTION: DtSetTableChecksum + * + * PARAMETERS: ChecksumPointer - Where to return the checksum + * + * RETURN: None + * + * DESCRIPTION: Set checksum of the whole data table into the checksum field + * + *****************************************************************************/ + +void +DtSetTableChecksum ( + UINT8 *ChecksumPointer) +{ + UINT8 Checksum = 0; + UINT8 OldSum; + + + DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum); + + OldSum = *ChecksumPointer; + Checksum = (UINT8) (Checksum - OldSum); + + /* Compute the final checksum */ + + Checksum = (UINT8) (0 - Checksum); + *ChecksumPointer = Checksum; +} + + +/****************************************************************************** + * + * FUNCTION: DtSetTableLength + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Walk the subtables and set all the length fields + * + *****************************************************************************/ + +void +DtSetTableLength ( + void) +{ + DT_SUBTABLE *ParentTable; + DT_SUBTABLE *ChildTable; + + + ParentTable = Gbl_RootTable; + ChildTable = NULL; + + if (!ParentTable) + { + return; + } + + DtSetSubtableLength (ParentTable); + + while (1) + { + ChildTable = DtGetNextSubtable (ParentTable, ChildTable); + if (ChildTable) + { + if (ChildTable->LengthField) + { + DtSetSubtableLength (ChildTable); + } + + if (ChildTable->Child) + { + ParentTable = ChildTable; + ChildTable = NULL; + } + else + { + ParentTable->TotalLength += ChildTable->TotalLength; + if (ParentTable->LengthField) + { + DtSetSubtableLength (ParentTable); + } + } + } + else + { + ChildTable = ParentTable; + + if (ChildTable == Gbl_RootTable) + { + break; + } + + ParentTable = DtGetParentSubtable (ParentTable); + + ParentTable->TotalLength += ChildTable->TotalLength; + if (ParentTable->LengthField) + { + DtSetSubtableLength (ParentTable); + } + } + } +} + + +/****************************************************************************** + * + * FUNCTION: DtWalkTableTree + * + * PARAMETERS: StartTable - Subtable in the tree where walking begins + * UserFunction - Called during the walk + * Context - Passed to user function + * ReturnValue - The return value of UserFunction + * + * RETURN: None + * + * DESCRIPTION: Performs a depth-first walk of the subtable tree + * + *****************************************************************************/ + +void +DtWalkTableTree ( + DT_SUBTABLE *StartTable, + DT_WALK_CALLBACK UserFunction, + void *Context, + void *ReturnValue) +{ + DT_SUBTABLE *ParentTable; + DT_SUBTABLE *ChildTable; + + + ParentTable = StartTable; + ChildTable = NULL; + + if (!ParentTable) + { + return; + } + + UserFunction (ParentTable, Context, ReturnValue); + + while (1) + { + ChildTable = DtGetNextSubtable (ParentTable, ChildTable); + if (ChildTable) + { + UserFunction (ChildTable, Context, ReturnValue); + + if (ChildTable->Child) + { + ParentTable = ChildTable; + ChildTable = NULL; + } + } + else + { + ChildTable = ParentTable; + if (ChildTable == Gbl_RootTable) + { + break; + } + + ParentTable = DtGetParentSubtable (ParentTable); + + if (ChildTable->Peer == StartTable) + { + break; + } + } + } +} + + +/****************************************************************************** + * + * FUNCTION: DtFreeFieldList + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Free the field list + * + *****************************************************************************/ + +void +DtFreeFieldList ( + void) +{ + DT_FIELD *Field = Gbl_FieldList; + DT_FIELD *NextField; + + + /* Walk and free entire field list */ + + while (Field) + { + NextField = Field->Next; /* Save link */ + + if (!(Field->Flags & DT_FIELD_NOT_ALLOCATED)) + { + ACPI_FREE (Field->Name); + ACPI_FREE (Field->Value); + } + + ACPI_FREE (Field); + Field = NextField; + } +} diff --git a/source/compiler/readme.txt b/source/compiler/readme.txt new file mode 100644 index 000000000000..fceea472e57d --- /dev/null +++ b/source/compiler/readme.txt @@ -0,0 +1,85 @@ + +Instructions for integrating iASL compiler into MS VC++ 6.0 environment. + +Part 1. Integration as a custom tool + +This procedure adds the iASL compiler as a custom tool that can be used +to compile ASL source files. The output is sent to the VC output +window. + +a) Select Tools->Customize. + +b) Select the "Tools" tab. + +c) Scroll down to the bottom of the "Menu Contents" window. There you + will see an empty rectangle. Click in the rectangle to enter a + name for this tool. + +d) Type "iASL Compiler" in the box and hit enter. You can now edit + the other fields for this new custom tool. + +e) Enter the following into the fields: + + Command: C:\Acpi\iasl.exe + Arguments: -e "$(FilePath)" + Initial Directory "$(FileDir)" + Use Output Window + + "Command" must be the path to wherever you copied the compiler. + "-e" instructs the compiler to produce messages appropriate for VC. + Quotes around FilePath and FileDir enable spaces in filenames. + +f) Select "Close". + +These steps will add the compiler to the tools menu as a custom tool. +By enabling "Use Output Window", you can click on error messages in +the output window and the source file and source line will be +automatically displayed by VC. Also, you can use F4 to step through +the messages and the corresponding source line(s). + + +Part 2. Integration into a project build + +This procedure creates a project that compiles ASL files to AML. + +a) Create a new, empty project and add your .ASL files to the project + +b) For all ASL files in the project, specify a custom build (under +Project/Settings/CustomBuild with the following settings (or similar): + +Commands: +c:\acpi\libraries\iasl.exe -vs -vi "$(InputPath)" + +Output: +$(InputDir)\$(InputPath).aml + + + +Compiler Generation From Source + +Generation of the ASL compiler from source code requires these items: + + +Required Tools +1) The Flex (or Lex) lexical analyzer generator. +2) The Bison (or Yacc) parser generator. +3) An ANSI C compiler. + + +Required Source Code. + +There are three major source code components that are required to +generate the compiler: + +1) The ASL compiler source. +2) The ACPI CA Core Subsystem source. In particular, the Namespace Manager + component is used to create an internal ACPI namespace and symbol table, + and the AML Interpreter is used to evaluate constant expressions. +3) The Common source for all ACPI components. + + + + + + + diff --git a/source/components/debugger/dbcmds.c b/source/components/debugger/dbcmds.c new file mode 100644 index 000000000000..cf214a161c07 --- /dev/null +++ b/source/components/debugger/dbcmds.c @@ -0,0 +1,1084 @@ +/******************************************************************************* + * + * Module Name: dbcmds - Miscellaneous debug commands and output routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acdebug.h" +#include "acnamesp.h" +#include "acresrc.h" +#include "actables.h" + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbcmds") + + +/* Local prototypes */ + +static void +AcpiDmCompareAmlResources ( + UINT8 *Aml1Buffer, + ACPI_RSDESC_SIZE Aml1BufferLength, + UINT8 *Aml2Buffer, + ACPI_RSDESC_SIZE Aml2BufferLength); + +static ACPI_STATUS +AcpiDmTestResourceConversion ( + ACPI_NAMESPACE_NODE *Node, + char *Name); + +static ACPI_STATUS +AcpiDbResourceCallback ( + ACPI_RESOURCE *Resource, + void *Context); + +static ACPI_STATUS +AcpiDbDeviceResources ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * FUNCTION: AcpiDbConvertToNode + * + * PARAMETERS: InString - String to convert + * + * RETURN: Pointer to a NS node + * + * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or + * alpha strings. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiDbConvertToNode ( + char *InString) +{ + ACPI_NAMESPACE_NODE *Node; + + + if ((*InString >= 0x30) && (*InString <= 0x39)) + { + /* Numeric argument, convert */ + + Node = ACPI_TO_POINTER (ACPI_STRTOUL (InString, NULL, 16)); + if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) + { + AcpiOsPrintf ("Address %p is invalid in this address space\n", + Node); + return (NULL); + } + + /* Make sure pointer is valid NS node */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + AcpiOsPrintf ("Address %p is not a valid NS node [%s]\n", + Node, AcpiUtGetDescriptorName (Node)); + return (NULL); + } + } + else + { + /* Alpha argument */ + /* The parameter is a name string that must be resolved to a + * Named obj + */ + Node = AcpiDbLocalNsLookup (InString); + if (!Node) + { + Node = AcpiGbl_RootNode; + } + } + + return (Node); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSleep + * + * PARAMETERS: ObjectArg - Desired sleep state (0-5) + * + * RETURN: Status + * + * DESCRIPTION: Simulate a sleep/wake sequence + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbSleep ( + char *ObjectArg) +{ + ACPI_STATUS Status; + UINT8 SleepState; + + + ACPI_FUNCTION_TRACE (AcpiDbSleep); + + + SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0); + + AcpiOsPrintf ("**** Prepare to sleep ****\n"); + Status = AcpiEnterSleepStatePrep (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + AcpiOsPrintf ("**** Going to sleep ****\n"); + Status = AcpiEnterSleepState (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + AcpiOsPrintf ("**** Prepare to return from sleep ****\n"); + Status = AcpiLeaveSleepStatePrep (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + AcpiOsPrintf ("**** Returning from sleep ****\n"); + Status = AcpiLeaveSleepState (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + return (Status); + + +ErrorExit: + + ACPI_EXCEPTION ((AE_INFO, Status, "During sleep test")); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayLocks + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display information about internal mutexes. + * + ******************************************************************************/ + +void +AcpiDbDisplayLocks ( + void) +{ + UINT32 i; + + + for (i = 0; i < ACPI_MAX_MUTEX; i++) + { + AcpiOsPrintf ("%26s : %s\n", AcpiUtGetMutexName (i), + AcpiGbl_MutexInfo[i].ThreadId == ACPI_MUTEX_NOT_ACQUIRED + ? "Locked" : "Unlocked"); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayTableInfo + * + * PARAMETERS: TableArg - String with name of table to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display information about loaded tables. Current + * implementation displays all loaded tables. + * + ******************************************************************************/ + +void +AcpiDbDisplayTableInfo ( + char *TableArg) +{ + UINT32 i; + ACPI_TABLE_DESC *TableDesc; + ACPI_STATUS Status; + + + /* Walk the entire root table list */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + TableDesc = &AcpiGbl_RootTableList.Tables[i]; + AcpiOsPrintf ("%u ", i); + + /* Make sure that the table is mapped */ + + Status = AcpiTbVerifyTable (TableDesc); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Dump the table header */ + + if (TableDesc->Pointer) + { + AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); + } + else + { + /* If the pointer is null, the table has been unloaded */ + + ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded", + TableDesc->Signature.Ascii)); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbUnloadAcpiTable + * + * PARAMETERS: TableArg - Name of the table to be unloaded + * InstanceArg - Which instance of the table to unload (if + * there are multiple tables of the same type) + * + * RETURN: Nonde + * + * DESCRIPTION: Unload an ACPI table. + * Instance is not implemented + * + ******************************************************************************/ + +void +AcpiDbUnloadAcpiTable ( + char *TableArg, + char *InstanceArg) +{ +/* TBD: Need to reimplement for new data structures */ + +#if 0 + UINT32 i; + ACPI_STATUS Status; + + + /* Search all tables for the target type */ + + for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++) + { + if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature, + AcpiGbl_TableData[i].SigLength)) + { + /* Found the table, unload it */ + + Status = AcpiUnloadTable (i); + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg); + } + else + { + AcpiOsPrintf ("%s, while unloading [%s]\n", + AcpiFormatException (Status), TableArg); + } + + return; + } + } + + AcpiOsPrintf ("Unknown table type [%s]\n", TableArg); +#endif +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSendNotify + * + * PARAMETERS: Name - Name of ACPI object to send the notify to + * Value - Value of the notify to send. + * + * RETURN: None + * + * DESCRIPTION: Send an ACPI notification. The value specified is sent to the + * named object as an ACPI notify. + * + ******************************************************************************/ + +void +AcpiDbSendNotify ( + char *Name, + UINT32 Value) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Translate name to an Named object */ + + Node = AcpiDbConvertToNode (Name); + if (!Node) + { + return; + } + + /* Decode Named object type */ + + switch (Node->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* Send the notify */ + + Status = AcpiEvQueueNotifyRequest (Node, Value); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not queue notify\n"); + } + break; + + default: + AcpiOsPrintf ("Named object is not a device or a thermal object\n"); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayInterfaces + * + * PARAMETERS: ActionArg - Null, "install", or "remove" + * InterfaceNameArg - Name for install/remove options + * + * RETURN: None + * + * DESCRIPTION: Display or modify the global _OSI interface list + * + ******************************************************************************/ + +void +AcpiDbDisplayInterfaces ( + char *ActionArg, + char *InterfaceNameArg) +{ + ACPI_INTERFACE_INFO *NextInterface; + char *SubString; + ACPI_STATUS Status; + + + /* If no arguments, just display current interface list */ + + if (!ActionArg) + { + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, + ACPI_WAIT_FOREVER); + + NextInterface = AcpiGbl_SupportedInterfaces; + + while (NextInterface) + { + if (!(NextInterface->Flags & ACPI_OSI_INVALID)) + { + AcpiOsPrintf ("%s\n", NextInterface->Name); + } + NextInterface = NextInterface->Next; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return; + } + + /* If ActionArg exists, so must InterfaceNameArg */ + + if (!InterfaceNameArg) + { + AcpiOsPrintf ("Missing Interface Name argument\n"); + return; + } + + /* Uppercase the action for match below */ + + AcpiUtStrupr (ActionArg); + + /* Install - install an interface */ + + SubString = ACPI_STRSTR ("INSTALL", ActionArg); + if (SubString) + { + Status = AcpiInstallInterface (InterfaceNameArg); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("%s, while installing \"%s\"\n", + AcpiFormatException (Status), InterfaceNameArg); + } + return; + } + + /* Remove - remove an interface */ + + SubString = ACPI_STRSTR ("REMOVE", ActionArg); + if (SubString) + { + Status = AcpiRemoveInterface (InterfaceNameArg); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("%s, while removing \"%s\"\n", + AcpiFormatException (Status), InterfaceNameArg); + } + return; + } + + /* Invalid ActionArg */ + + AcpiOsPrintf ("Invalid action argument: %s\n", ActionArg); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayTemplate + * + * PARAMETERS: BufferArg - Buffer name or addrss + * + * RETURN: None + * + * DESCRIPTION: Dump a buffer that contains a resource template + * + ******************************************************************************/ + +void +AcpiDbDisplayTemplate ( + char *BufferArg) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_BUFFER ReturnObj; + + + /* Translate BufferArg to an Named object */ + + Node = AcpiDbConvertToNode (BufferArg); + if (!Node || (Node == AcpiGbl_RootNode)) + { + AcpiOsPrintf ("Invalid argument: %s\n", BufferArg); + return; + } + + /* We must have a buffer object */ + + if (Node->Type != ACPI_TYPE_BUFFER) + { + AcpiOsPrintf ("Not a Buffer object, cannot be a template: %s\n", + BufferArg); + return; + } + + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + ReturnObj.Pointer = AcpiGbl_DbBuffer; + + /* Attempt to convert the raw buffer to a resource list */ + + Status = AcpiRsCreateResourceList (Node->Object, &ReturnObj); + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + AcpiDbgLevel |= ACPI_LV_RESOURCES; + + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not convert Buffer to a resource list: %s, %s\n", + BufferArg, AcpiFormatException (Status)); + goto DumpBuffer; + } + + /* Now we can dump the resource list */ + + AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, + ReturnObj.Pointer)); + +DumpBuffer: + AcpiOsPrintf ("\nRaw data buffer:\n"); + AcpiUtDumpBuffer ((UINT8 *) Node->Object->Buffer.Pointer, + Node->Object->Buffer.Length, + DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCompareAmlResources + * + * PARAMETERS: Aml1Buffer - Contains first resource list + * Aml1BufferLength - Length of first resource list + * Aml2Buffer - Contains second resource list + * Aml2BufferLength - Length of second resource list + * + * RETURN: None + * + * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in + * order to isolate a miscompare to an individual resource) + * + ******************************************************************************/ + +static void +AcpiDmCompareAmlResources ( + UINT8 *Aml1Buffer, + ACPI_RSDESC_SIZE Aml1BufferLength, + UINT8 *Aml2Buffer, + ACPI_RSDESC_SIZE Aml2BufferLength) +{ + UINT8 *Aml1; + UINT8 *Aml2; + UINT8 *Aml1End; + UINT8 *Aml2End; + ACPI_RSDESC_SIZE Aml1Length; + ACPI_RSDESC_SIZE Aml2Length; + ACPI_RSDESC_SIZE Offset = 0; + UINT8 ResourceType; + UINT32 Count = 0; + UINT32 i; + + + /* Compare overall buffer sizes (may be different due to size rounding) */ + + if (Aml1BufferLength != Aml2BufferLength) + { + AcpiOsPrintf ( + "**** Buffer length mismatch in converted AML: Original %X, New %X ****\n", + Aml1BufferLength, Aml2BufferLength); + } + + Aml1 = Aml1Buffer; + Aml2 = Aml2Buffer; + Aml1End = Aml1Buffer + Aml1BufferLength; + Aml2End = Aml2Buffer + Aml2BufferLength; + + /* Walk the descriptor lists, comparing each descriptor */ + + while ((Aml1 < Aml1End) && (Aml2 < Aml2End)) + { + /* Get the lengths of each descriptor */ + + Aml1Length = AcpiUtGetDescriptorLength (Aml1); + Aml2Length = AcpiUtGetDescriptorLength (Aml2); + ResourceType = AcpiUtGetResourceType (Aml1); + + /* Check for descriptor length match */ + + if (Aml1Length != Aml2Length) + { + AcpiOsPrintf ( + "**** Length mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X Len1 %X, Len2 %X ****\n", + Count, ResourceType, Offset, Aml1Length, Aml2Length); + } + + /* Check for descriptor byte match */ + + else if (ACPI_MEMCMP (Aml1, Aml2, Aml1Length)) + { + AcpiOsPrintf ( + "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n", + Count, ResourceType, Offset); + + for (i = 0; i < Aml1Length; i++) + { + if (Aml1[i] != Aml2[i]) + { + AcpiOsPrintf ("Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n", + i, Aml2[i], Aml1[i]); + } + } + } + + /* Exit on EndTag descriptor */ + + if (ResourceType == ACPI_RESOURCE_NAME_END_TAG) + { + return; + } + + /* Point to next descriptor in each buffer */ + + Count++; + Offset += Aml1Length; + Aml1 += Aml1Length; + Aml2 += Aml2Length; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmTestResourceConversion + * + * PARAMETERS: Node - Parent device node + * Name - resource method name (_CRS) + * + * RETURN: Status + * + * DESCRIPTION: Compare the original AML with a conversion of the AML to + * internal resource list, then back to AML. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmTestResourceConversion ( + ACPI_NAMESPACE_NODE *Node, + char *Name) +{ + ACPI_STATUS Status; + ACPI_BUFFER ReturnObj; + ACPI_BUFFER ResourceObj; + ACPI_BUFFER NewAml; + ACPI_OBJECT *OriginalAml; + + + AcpiOsPrintf ("Resource Conversion Comparison:\n"); + + NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + ReturnObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + ResourceObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + /* Get the original _CRS AML resource template */ + + Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not obtain %s: %s\n", + Name, AcpiFormatException (Status)); + return (Status); + } + + /* Get the AML resource template, converted to internal resource structs */ + + Status = AcpiGetCurrentResources (Node, &ResourceObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", + AcpiFormatException (Status)); + goto Exit1; + } + + /* Convert internal resource list to external AML resource template */ + + Status = AcpiRsCreateAmlResources (ResourceObj.Pointer, &NewAml); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n", + AcpiFormatException (Status)); + goto Exit2; + } + + /* Compare original AML to the newly created AML resource list */ + + OriginalAml = ReturnObj.Pointer; + + AcpiDmCompareAmlResources ( + OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length, + NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length); + + /* Cleanup and exit */ + + ACPI_FREE (NewAml.Pointer); +Exit2: + ACPI_FREE (ResourceObj.Pointer); +Exit1: + ACPI_FREE (ReturnObj.Pointer); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbResourceCallback + * + * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Simple callback to exercise AcpiWalkResources + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbResourceCallback ( + ACPI_RESOURCE *Resource, + void *Context) +{ + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDeviceResources + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbDeviceResources ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_NAMESPACE_NODE *PrtNode = NULL; + ACPI_NAMESPACE_NODE *CrsNode = NULL; + ACPI_NAMESPACE_NODE *PrsNode = NULL; + ACPI_NAMESPACE_NODE *AeiNode = NULL; + char *ParentPath; + ACPI_BUFFER ReturnObj; + ACPI_STATUS Status; + + + Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + ParentPath = AcpiNsGetExternalPathname (Node); + if (!ParentPath) + { + return (AE_NO_MEMORY); + } + + /* Get handles to the resource methods for this device */ + + (void) AcpiGetHandle (Node, METHOD_NAME__PRT, ACPI_CAST_PTR (ACPI_HANDLE, &PrtNode)); + (void) AcpiGetHandle (Node, METHOD_NAME__CRS, ACPI_CAST_PTR (ACPI_HANDLE, &CrsNode)); + (void) AcpiGetHandle (Node, METHOD_NAME__PRS, ACPI_CAST_PTR (ACPI_HANDLE, &PrsNode)); + (void) AcpiGetHandle (Node, METHOD_NAME__AEI, ACPI_CAST_PTR (ACPI_HANDLE, &AeiNode)); + if (!PrtNode && !CrsNode && !PrsNode && !AeiNode) + { + goto Cleanup; /* Nothing to do */ + } + + AcpiOsPrintf ("\nDevice: %s\n", ParentPath); + + /* Prepare for a return object of arbitrary size */ + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + + /* _PRT */ + + if (PrtNode) + { + AcpiOsPrintf ("Evaluating _PRT\n"); + + Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not evaluate _PRT: %s\n", + AcpiFormatException (Status)); + goto GetCrs; + } + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiGetIrqRoutingTable (Node, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n", + AcpiFormatException (Status)); + goto GetCrs; + } + + AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer)); + } + + + /* _CRS */ + +GetCrs: + if (CrsNode) + { + AcpiOsPrintf ("Evaluating _CRS\n"); + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not evaluate _CRS: %s\n", + AcpiFormatException (Status)); + goto GetPrs; + } + + /* This code is here to exercise the AcpiWalkResources interface */ + + Status = AcpiWalkResources (Node, METHOD_NAME__CRS, + AcpiDbResourceCallback, NULL); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiWalkResources failed: %s\n", + AcpiFormatException (Status)); + goto GetPrs; + } + + /* Get the _CRS resource list */ + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiGetCurrentResources (Node, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", + AcpiFormatException (Status)); + goto GetPrs; + } + + /* Dump the _CRS resource list */ + + AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, + ReturnObj.Pointer)); + + /* + * Perform comparison of original AML to newly created AML. This tests both + * the AML->Resource conversion and the Resource->Aml conversion. + */ + Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS); + + /* Execute _SRS with the resource list */ + + Status = AcpiSetCurrentResources (Node, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n", + AcpiFormatException (Status)); + goto GetPrs; + } + } + + + /* _PRS */ + +GetPrs: + if (PrsNode) + { + AcpiOsPrintf ("Evaluating _PRS\n"); + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not evaluate _PRS: %s\n", + AcpiFormatException (Status)); + goto GetAei; + } + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiGetPossibleResources (Node, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n", + AcpiFormatException (Status)); + goto GetAei; + } + + AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); + } + + + /* _AEI */ + +GetAei: + if (AeiNode) + { + AcpiOsPrintf ("Evaluating _AEI\n"); + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not evaluate _AEI: %s\n", + AcpiFormatException (Status)); + goto Cleanup; + } + + ReturnObj.Pointer = AcpiGbl_DbBuffer; + ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; + + Status = AcpiGetEventResources (Node, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("AcpiGetEventResources failed: %s\n", + AcpiFormatException (Status)); + goto Cleanup; + } + + AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); + } + + +Cleanup: + ACPI_FREE (ParentPath); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayResources + * + * PARAMETERS: ObjectArg - String object name or object pointer. + * "*" means "display resources for all devices" + * + * RETURN: None + * + * DESCRIPTION: Display the resource objects associated with a device. + * + ******************************************************************************/ + +void +AcpiDbDisplayResources ( + char *ObjectArg) +{ + ACPI_NAMESPACE_NODE *Node; + + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + AcpiDbgLevel |= ACPI_LV_RESOURCES; + + /* Asterisk means "display resources for all devices" */ + + if (!ACPI_STRCMP (ObjectArg, "*")) + { + (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL); + } + else + { + /* Convert string to object pointer */ + + Node = AcpiDbConvertToNode (ObjectArg); + if (Node) + { + if (Node->Type != ACPI_TYPE_DEVICE) + { + AcpiOsPrintf ("%4.4s: Name is not a device object (%s)\n", + Node->Name.Ascii, AcpiUtGetTypeName (Node->Type)); + } + else + { + (void) AcpiDbDeviceResources (Node, 0, NULL, NULL); + } + } + } + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiDbGenerateGpe + * + * PARAMETERS: GpeArg - Raw GPE number, ascii string + * BlockArg - GPE block number, ascii string + * 0 or 1 for FADT GPE blocks + * + * RETURN: None + * + * DESCRIPTION: Generate a GPE + * + ******************************************************************************/ + +void +AcpiDbGenerateGpe ( + char *GpeArg, + char *BlockArg) +{ + UINT32 BlockNumber; + UINT32 GpeNumber; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + + + GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0); + BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0); + + + GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber), + GpeNumber); + if (!GpeEventInfo) + { + AcpiOsPrintf ("Invalid GPE\n"); + return; + } + + (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); +} +#endif /* !ACPI_REDUCED_HARDWARE */ + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/debugger/dbdisply.c b/source/components/debugger/dbdisply.c new file mode 100644 index 000000000000..fa943e7fa996 --- /dev/null +++ b/source/components/debugger/dbdisply.c @@ -0,0 +1,1057 @@ +/******************************************************************************* + * + * Module Name: dbdisply - debug display commands + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acinterp.h" +#include "acdebug.h" +#include "acdisasm.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbdisply") + +/* Local prototypes */ + +static void +AcpiDbDumpParserDescriptor ( + ACPI_PARSE_OBJECT *Op); + +static void * +AcpiDbGetPointer ( + void *Target); + + +/* + * System handler information. + * Used for Handlers command, in AcpiDbDisplayHandlers. + */ +#define ACPI_PREDEFINED_PREFIX "%25s (%.2X) : " +#define ACPI_HANDLER_NAME_STRING "%30s : " +#define ACPI_HANDLER_PRESENT_STRING "%-9s (%p)\n" +#define ACPI_HANDLER_NOT_PRESENT_STRING "%-9s\n" + +/* All predefined Address Space IDs */ + +static ACPI_ADR_SPACE_TYPE AcpiGbl_SpaceIdList[] = +{ + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_EC, + ACPI_ADR_SPACE_SMBUS, + ACPI_ADR_SPACE_CMOS, + ACPI_ADR_SPACE_PCI_BAR_TARGET, + ACPI_ADR_SPACE_IPMI, + ACPI_ADR_SPACE_GPIO, + ACPI_ADR_SPACE_GSBUS, + ACPI_ADR_SPACE_DATA_TABLE, + ACPI_ADR_SPACE_FIXED_HARDWARE +}; + +/* Global handler information */ + +typedef struct acpi_handler_info +{ + void *Handler; + char *Name; + +} ACPI_HANDLER_INFO; + +static ACPI_HANDLER_INFO AcpiGbl_HandlerList[] = +{ + {&AcpiGbl_SystemNotify.Handler, "System Notifications"}, + {&AcpiGbl_DeviceNotify.Handler, "Device Notifications"}, + {&AcpiGbl_TableHandler, "ACPI Table Events"}, + {&AcpiGbl_ExceptionHandler, "Control Method Exceptions"}, + {&AcpiGbl_InterfaceHandler, "OSI Invocations"} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetPointer + * + * PARAMETERS: Target - Pointer to string to be converted + * + * RETURN: Converted pointer + * + * DESCRIPTION: Convert an ascii pointer value to a real value + * + ******************************************************************************/ + +static void * +AcpiDbGetPointer ( + void *Target) +{ + void *ObjPtr; + + + ObjPtr = ACPI_TO_POINTER (ACPI_STRTOUL (Target, NULL, 16)); + return (ObjPtr); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDumpParserDescriptor + * + * PARAMETERS: Op - A parser Op descriptor + * + * RETURN: None + * + * DESCRIPTION: Display a formatted parser object + * + ******************************************************************************/ + +static void +AcpiDbDumpParserDescriptor ( + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *Info; + + + Info = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + AcpiOsPrintf ("Parser Op Descriptor:\n"); + AcpiOsPrintf ("%20.20s : %4.4X\n", "Opcode", Op->Common.AmlOpcode); + + ACPI_DEBUG_ONLY_MEMBERS (AcpiOsPrintf ("%20.20s : %s\n", "Opcode Name", + Info->Name)); + + AcpiOsPrintf ("%20.20s : %p\n", "Value/ArgList", Op->Common.Value.Arg); + AcpiOsPrintf ("%20.20s : %p\n", "Parent", Op->Common.Parent); + AcpiOsPrintf ("%20.20s : %p\n", "NextOp", Op->Common.Next); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDecodeAndDisplayObject + * + * PARAMETERS: Target - String with object to be displayed. Names + * and hex pointers are supported. + * OutputType - Byte, Word, Dword, or Qword (B|W|D|Q) + * + * RETURN: None + * + * DESCRIPTION: Display a formatted ACPI object + * + ******************************************************************************/ + +void +AcpiDbDecodeAndDisplayObject ( + char *Target, + char *OutputType) +{ + void *ObjPtr; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 Display = DB_BYTE_DISPLAY; + char Buffer[80]; + ACPI_BUFFER RetBuf; + ACPI_STATUS Status; + UINT32 Size; + + + if (!Target) + { + return; + } + + /* Decode the output type */ + + if (OutputType) + { + AcpiUtStrupr (OutputType); + if (OutputType[0] == 'W') + { + Display = DB_WORD_DISPLAY; + } + else if (OutputType[0] == 'D') + { + Display = DB_DWORD_DISPLAY; + } + else if (OutputType[0] == 'Q') + { + Display = DB_QWORD_DISPLAY; + } + } + + RetBuf.Length = sizeof (Buffer); + RetBuf.Pointer = Buffer; + + /* Differentiate between a number and a name */ + + if ((Target[0] >= 0x30) && (Target[0] <= 0x39)) + { + ObjPtr = AcpiDbGetPointer (Target); + if (!AcpiOsReadable (ObjPtr, 16)) + { + AcpiOsPrintf ("Address %p is invalid in this address space\n", + ObjPtr); + return; + } + + /* Decode the object type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjPtr)) + { + case ACPI_DESC_TYPE_NAMED: + + /* This is a namespace Node */ + + if (!AcpiOsReadable (ObjPtr, sizeof (ACPI_NAMESPACE_NODE))) + { + AcpiOsPrintf ( + "Cannot read entire Named object at address %p\n", ObjPtr); + return; + } + + Node = ObjPtr; + goto DumpNode; + + + case ACPI_DESC_TYPE_OPERAND: + + /* This is a ACPI OPERAND OBJECT */ + + if (!AcpiOsReadable (ObjPtr, sizeof (ACPI_OPERAND_OBJECT))) + { + AcpiOsPrintf ("Cannot read entire ACPI object at address %p\n", + ObjPtr); + return; + } + + AcpiUtDumpBuffer (ObjPtr, sizeof (ACPI_OPERAND_OBJECT), Display, + ACPI_UINT32_MAX); + AcpiExDumpObjectDescriptor (ObjPtr, 1); + break; + + + case ACPI_DESC_TYPE_PARSER: + + /* This is a Parser Op object */ + + if (!AcpiOsReadable (ObjPtr, sizeof (ACPI_PARSE_OBJECT))) + { + AcpiOsPrintf ( + "Cannot read entire Parser object at address %p\n", ObjPtr); + return; + } + + AcpiUtDumpBuffer (ObjPtr, sizeof (ACPI_PARSE_OBJECT), Display, + ACPI_UINT32_MAX); + AcpiDbDumpParserDescriptor ((ACPI_PARSE_OBJECT *) ObjPtr); + break; + + + default: + + /* Is not a recognizeable object */ + + Size = 16; + if (AcpiOsReadable (ObjPtr, 64)) + { + Size = 64; + } + + /* Just dump some memory */ + + AcpiUtDumpBuffer (ObjPtr, Size, Display, ACPI_UINT32_MAX); + break; + } + + return; + } + + /* The parameter is a name string that must be resolved to a Named obj */ + + Node = AcpiDbLocalNsLookup (Target); + if (!Node) + { + return; + } + + +DumpNode: + /* Now dump the NS node */ + + Status = AcpiGetName (Node, ACPI_FULL_PATHNAME, &RetBuf); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not convert name to pathname\n"); + } + + else + { + AcpiOsPrintf ("Object (%p) Pathname: %s\n", + Node, (char *) RetBuf.Pointer); + } + + if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) + { + AcpiOsPrintf ("Invalid Named object at address %p\n", Node); + return; + } + + AcpiUtDumpBuffer ((void *) Node, sizeof (ACPI_NAMESPACE_NODE), + Display, ACPI_UINT32_MAX); + AcpiExDumpNamespaceNode (Node, 1); + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + AcpiOsPrintf ("\nAttached Object (%p):\n", ObjDesc); + if (!AcpiOsReadable (ObjDesc, sizeof (ACPI_OPERAND_OBJECT))) + { + AcpiOsPrintf ("Invalid internal ACPI Object at address %p\n", + ObjDesc); + return; + } + + AcpiUtDumpBuffer ((void *) ObjDesc, sizeof (ACPI_OPERAND_OBJECT), + Display, ACPI_UINT32_MAX); + AcpiExDumpObjectDescriptor (ObjDesc, 1); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayMethodInfo + * + * PARAMETERS: StartOp - Root of the control method parse tree + * + * RETURN: None + * + * DESCRIPTION: Display information about the current method + * + ******************************************************************************/ + +void +AcpiDbDisplayMethodInfo ( + ACPI_PARSE_OBJECT *StartOp) +{ + ACPI_WALK_STATE *WalkState; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *RootOp; + ACPI_PARSE_OBJECT *Op; + const ACPI_OPCODE_INFO *OpInfo; + UINT32 NumOps = 0; + UINT32 NumOperands = 0; + UINT32 NumOperators = 0; + UINT32 NumRemainingOps = 0; + UINT32 NumRemainingOperands = 0; + UINT32 NumRemainingOperators = 0; + BOOLEAN CountRemaining = FALSE; + + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + ObjDesc = WalkState->MethodDesc; + Node = WalkState->MethodNode; + + AcpiOsPrintf ("Currently executing control method is [%4.4s]\n", + AcpiUtGetNodeName (Node)); + AcpiOsPrintf ("%X Arguments, SyncLevel = %X\n", + (UINT32) ObjDesc->Method.ParamCount, + (UINT32) ObjDesc->Method.SyncLevel); + + + RootOp = StartOp; + while (RootOp->Common.Parent) + { + RootOp = RootOp->Common.Parent; + } + + Op = RootOp; + + while (Op) + { + if (Op == StartOp) + { + CountRemaining = TRUE; + } + + NumOps++; + if (CountRemaining) + { + NumRemainingOps++; + } + + /* Decode the opcode */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + switch (OpInfo->Class) + { + case AML_CLASS_ARGUMENT: + if (CountRemaining) + { + NumRemainingOperands++; + } + + NumOperands++; + break; + + case AML_CLASS_UNKNOWN: + /* Bad opcode or ASCII character */ + + continue; + + default: + if (CountRemaining) + { + NumRemainingOperators++; + } + + NumOperators++; + break; + } + + Op = AcpiPsGetDepthNext (StartOp, Op); + } + + AcpiOsPrintf ( + "Method contains: %X AML Opcodes - %X Operators, %X Operands\n", + NumOps, NumOperators, NumOperands); + + AcpiOsPrintf ( + "Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", + NumRemainingOps, NumRemainingOperators, NumRemainingOperands); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayLocals + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all locals for the currently running control method + * + ******************************************************************************/ + +void +AcpiDbDisplayLocals ( + void) +{ + ACPI_WALK_STATE *WalkState; + + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + AcpiDmDisplayLocals (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayArguments + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all arguments for the currently running control method + * + ******************************************************************************/ + +void +AcpiDbDisplayArguments ( + void) +{ + ACPI_WALK_STATE *WalkState; + + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + AcpiDmDisplayArguments (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayResults + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current contents of a method result stack + * + ******************************************************************************/ + +void +AcpiDbDisplayResults ( + void) +{ + UINT32 i; + ACPI_WALK_STATE *WalkState; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 ResultCount = 0; + ACPI_NAMESPACE_NODE *Node; + ACPI_GENERIC_STATE *Frame; + UINT32 Index; /* Index onto current frame */ + + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + ObjDesc = WalkState->MethodDesc; + Node = WalkState->MethodNode; + + if (WalkState->Results) + { + ResultCount = WalkState->ResultCount; + } + + AcpiOsPrintf ("Method [%4.4s] has %X stacked result objects\n", + AcpiUtGetNodeName (Node), ResultCount); + + /* From the top element of result stack */ + + Frame = WalkState->Results; + Index = (ResultCount - 1) % ACPI_RESULTS_FRAME_OBJ_NUM; + + for (i = 0; i < ResultCount; i++) + { + ObjDesc = Frame->Results.ObjDesc[Index]; + AcpiOsPrintf ("Result%u: ", i); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + if (Index == 0) + { + Frame = Frame->Results.Next; + Index = ACPI_RESULTS_FRAME_OBJ_NUM; + } + Index--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayCallingTree + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current calling tree of nested control methods + * + ******************************************************************************/ + +void +AcpiDbDisplayCallingTree ( + void) +{ + ACPI_WALK_STATE *WalkState; + ACPI_NAMESPACE_NODE *Node; + + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + Node = WalkState->MethodNode; + AcpiOsPrintf ("Current Control Method Call Tree\n"); + + while (WalkState) + { + Node = WalkState->MethodNode; + + AcpiOsPrintf (" [%4.4s]\n", AcpiUtGetNodeName (Node)); + + WalkState = WalkState->Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayObjectType + * + * PARAMETERS: ObjectArg - User entered NS node handle + * + * RETURN: None + * + * DESCRIPTION: Display type of an arbitrary NS node + * + ******************************************************************************/ + +void +AcpiDbDisplayObjectType ( + char *ObjectArg) +{ + ACPI_HANDLE Handle; + ACPI_DEVICE_INFO *Info; + ACPI_STATUS Status; + UINT32 i; + + + Handle = ACPI_TO_POINTER (ACPI_STRTOUL (ObjectArg, NULL, 16)); + + Status = AcpiGetObjectInfo (Handle, &Info); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get object info, %s\n", + AcpiFormatException (Status)); + return; + } + + AcpiOsPrintf ("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n", + ACPI_FORMAT_UINT64 (Info->Address), + Info->CurrentStatus, Info->Flags); + + AcpiOsPrintf ("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n", + Info->HighestDstates[0], Info->HighestDstates[1], + Info->HighestDstates[2], Info->HighestDstates[3]); + + AcpiOsPrintf ("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n", + Info->LowestDstates[0], Info->LowestDstates[1], + Info->LowestDstates[2], Info->LowestDstates[3], + Info->LowestDstates[4]); + + if (Info->Valid & ACPI_VALID_HID) + { + AcpiOsPrintf ("HID: %s\n", Info->HardwareId.String); + } + if (Info->Valid & ACPI_VALID_UID) + { + AcpiOsPrintf ("UID: %s\n", Info->UniqueId.String); + } + if (Info->Valid & ACPI_VALID_CID) + { + for (i = 0; i < Info->CompatibleIdList.Count; i++) + { + AcpiOsPrintf ("CID %u: %s\n", i, + Info->CompatibleIdList.Ids[i].String); + } + } + + ACPI_FREE (Info); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayResultObject + * + * PARAMETERS: ObjDesc - Object to be displayed + * WalkState - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + * Note: Curently only displays the result object if we are single stepping. + * However, this output may be useful in other contexts and could be enabled + * to do so if needed. + * + ******************************************************************************/ + +void +AcpiDbDisplayResultObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + + /* Only display if single stepping */ + + if (!AcpiGbl_CmSingleStep) + { + return; + } + + AcpiOsPrintf ("ResultObj: "); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiOsPrintf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayArgumentObject + * + * PARAMETERS: ObjDesc - Object to be displayed + * WalkState - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + ******************************************************************************/ + +void +AcpiDbDisplayArgumentObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + + if (!AcpiGbl_CmSingleStep) + { + return; + } + + AcpiOsPrintf ("ArgObj: "); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayGpes + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the current GPE structures + * + ******************************************************************************/ + +void +AcpiDbDisplayGpes ( + void) +{ + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + char *GpeType; + UINT32 GpeIndex; + UINT32 Block = 0; + UINT32 i; + UINT32 j; + char Buffer[80]; + ACPI_BUFFER RetBuf; + ACPI_STATUS Status; + + + RetBuf.Length = sizeof (Buffer); + RetBuf.Pointer = Buffer; + + Block = 0; + + /* Walk the GPE lists */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + Status = AcpiGetName (GpeBlock->Node, ACPI_FULL_PATHNAME, &RetBuf); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not convert name to pathname\n"); + } + + if (GpeBlock->Node == AcpiGbl_FadtGpeDevice) + { + GpeType = "FADT-defined GPE block"; + } + else + { + GpeType = "GPE Block Device"; + } + + AcpiOsPrintf ("\nBlock %u - Info %p DeviceNode %p [%s] - %s\n", + Block, GpeBlock, GpeBlock->Node, Buffer, GpeType); + + AcpiOsPrintf (" Registers: %u (%u GPEs)\n", + GpeBlock->RegisterCount, GpeBlock->GpeCount); + + AcpiOsPrintf (" GPE range: 0x%X to 0x%X on interrupt %u\n", + GpeBlock->BlockBaseNumber, + GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1), + GpeXruptInfo->InterruptNumber); + + AcpiOsPrintf ( + " RegisterInfo: %p Status %8.8X%8.8X Enable %8.8X%8.8X\n", + GpeBlock->RegisterInfo, + ACPI_FORMAT_UINT64 (GpeBlock->RegisterInfo->StatusAddress.Address), + ACPI_FORMAT_UINT64 (GpeBlock->RegisterInfo->EnableAddress.Address)); + + AcpiOsPrintf (" EventInfo: %p\n", GpeBlock->EventInfo); + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; + + AcpiOsPrintf ( + " Reg %u: (GPE %.2X-%.2X) RunEnable %2.2X WakeEnable %2.2X" + " Status %8.8X%8.8X Enable %8.8X%8.8X\n", + i, GpeRegisterInfo->BaseGpeNumber, + GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), + GpeRegisterInfo->EnableForRun, + GpeRegisterInfo->EnableForWake, + ACPI_FORMAT_UINT64 (GpeRegisterInfo->StatusAddress.Address), + ACPI_FORMAT_UINT64 (GpeRegisterInfo->EnableAddress.Address)); + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; + GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) + { + /* This GPE is not used (no method or handler), ignore it */ + + continue; + } + + AcpiOsPrintf ( + " GPE %.2X: %p RunRefs %2.2X Flags %2.2X (", + GpeBlock->BlockBaseNumber + GpeIndex, GpeEventInfo, + GpeEventInfo->RuntimeCount, GpeEventInfo->Flags); + + /* Decode the flags byte */ + + if (GpeEventInfo->Flags & ACPI_GPE_LEVEL_TRIGGERED) + { + AcpiOsPrintf ("Level, "); + } + else + { + AcpiOsPrintf ("Edge, "); + } + + if (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) + { + AcpiOsPrintf ("CanWake, "); + } + else + { + AcpiOsPrintf ("RunOnly, "); + } + + switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) + { + case ACPI_GPE_DISPATCH_NONE: + AcpiOsPrintf ("NotUsed"); + break; + case ACPI_GPE_DISPATCH_METHOD: + AcpiOsPrintf ("Method"); + break; + case ACPI_GPE_DISPATCH_HANDLER: + AcpiOsPrintf ("Handler"); + break; + case ACPI_GPE_DISPATCH_NOTIFY: + AcpiOsPrintf ("Notify"); + break; + default: + AcpiOsPrintf ("UNKNOWN: %X", + GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK); + break; + } + + AcpiOsPrintf (")\n"); + } + } + Block++; + GpeBlock = GpeBlock->Next; + } + GpeXruptInfo = GpeXruptInfo->Next; + } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayHandlers + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the currently installed global handlers + * + ******************************************************************************/ + +void +AcpiDbDisplayHandlers ( + void) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_ADR_SPACE_TYPE SpaceId; + UINT32 i; + + + /* Operation region handlers */ + + AcpiOsPrintf ("\nOperation Region Handlers:\n"); + + ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); + if (ObjDesc) + { + for (i = 0; i < ACPI_ARRAY_LENGTH (AcpiGbl_SpaceIdList); i++) + { + SpaceId = AcpiGbl_SpaceIdList[i]; + HandlerObj = ObjDesc->Device.Handler; + + AcpiOsPrintf (ACPI_PREDEFINED_PREFIX, + AcpiUtGetRegionName ((UINT8) SpaceId), SpaceId); + + while (HandlerObj) + { + if (AcpiGbl_SpaceIdList[i] == HandlerObj->AddressSpace.SpaceId) + { + AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, + (HandlerObj->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default" : "User", + HandlerObj->AddressSpace.Handler); + goto FoundHandler; + } + + HandlerObj = HandlerObj->AddressSpace.Next; + } + + /* There is no handler for this SpaceId */ + + AcpiOsPrintf ("None\n"); + + FoundHandler:; + } + + /* Find all handlers for user-defined SpaceIDs */ + + HandlerObj = ObjDesc->Device.Handler; + while (HandlerObj) + { + if (HandlerObj->AddressSpace.SpaceId >= ACPI_USER_REGION_BEGIN) + { + AcpiOsPrintf (ACPI_PREDEFINED_PREFIX, + "User-defined ID", HandlerObj->AddressSpace.SpaceId); + AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, + (HandlerObj->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default" : "User", + HandlerObj->AddressSpace.Handler); + } + + HandlerObj = HandlerObj->AddressSpace.Next; + } + } + +#if (!ACPI_REDUCED_HARDWARE) + + /* Fixed event handlers */ + + AcpiOsPrintf ("\nFixed Event Handlers:\n"); + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + AcpiOsPrintf (ACPI_PREDEFINED_PREFIX, AcpiUtGetEventName (i), i); + if (AcpiGbl_FixedEventHandlers[i].Handler) + { + AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, "User", + AcpiGbl_FixedEventHandlers[i].Handler); + } + else + { + AcpiOsPrintf (ACPI_HANDLER_NOT_PRESENT_STRING, "None"); + } + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Miscellaneous global handlers */ + + AcpiOsPrintf ("\nMiscellaneous Global Handlers:\n"); + + for (i = 0; i < ACPI_ARRAY_LENGTH (AcpiGbl_HandlerList); i++) + { + AcpiOsPrintf (ACPI_HANDLER_NAME_STRING, AcpiGbl_HandlerList[i].Name); + if (AcpiGbl_HandlerList[i].Handler) + { + AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, "User", + AcpiGbl_HandlerList[i].Handler); + } + else + { + AcpiOsPrintf (ACPI_HANDLER_NOT_PRESENT_STRING, "None"); + } + } +} + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/debugger/dbexec.c b/source/components/debugger/dbexec.c new file mode 100644 index 000000000000..7818c9ddbef8 --- /dev/null +++ b/source/components/debugger/dbexec.c @@ -0,0 +1,1105 @@ +/******************************************************************************* + * + * Module Name: dbexec - debugger control method execution + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" +#include "acnamesp.h" + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbexec") + + +static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; +#define DB_DEFAULT_PKG_ELEMENTS 33 + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDbExecuteMethod ( + ACPI_DB_METHOD_INFO *Info, + ACPI_BUFFER *ReturnObj); + +static void +AcpiDbExecuteSetup ( + ACPI_DB_METHOD_INFO *Info); + +static UINT32 +AcpiDbGetOutstandingAllocations ( + void); + +static void ACPI_SYSTEM_XFACE +AcpiDbMethodThread ( + void *Context); + +static ACPI_STATUS +AcpiDbExecutionWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbHexCharToValue ( + int HexChar, + UINT8 *ReturnValue); + +static ACPI_STATUS +AcpiDbConvertToPackage ( + char *String, + ACPI_OBJECT *Object); + +static ACPI_STATUS +AcpiDbConvertToObject ( + ACPI_OBJECT_TYPE Type, + char *String, + ACPI_OBJECT *Object); + +static void +AcpiDbDeleteObjects ( + UINT32 Count, + ACPI_OBJECT *Objects); + + +/******************************************************************************* + * + * FUNCTION: AcpiDbHexCharToValue + * + * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F + * ReturnValue - Where the converted value is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16). + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbHexCharToValue ( + int HexChar, + UINT8 *ReturnValue) +{ + UINT8 Value; + + + /* Digit must be ascii [0-9a-fA-F] */ + + if (!ACPI_IS_XDIGIT (HexChar)) + { + return (AE_BAD_HEX_CONSTANT); + } + + if (HexChar <= 0x39) + { + Value = (UINT8) (HexChar - 0x30); + } + else + { + Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37); + } + + *ReturnValue = Value; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbHexByteToBinary + * + * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format: + * HiByte then LoByte. + * ReturnValue - Where the converted value is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255). + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbHexByteToBinary ( + char *HexByte, + UINT8 *ReturnValue) +{ + UINT8 Local0; + UINT8 Local1; + ACPI_STATUS Status; + + + /* High byte */ + + Status = AcpiDbHexCharToValue (HexByte[0], &Local0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Low byte */ + + Status = AcpiDbHexCharToValue (HexByte[1], &Local1); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *ReturnValue = (UINT8) ((Local0 << 4) | Local1); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbConvertToBuffer + * + * PARAMETERS: String - Input string to be converted + * Object - Where the buffer object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a string to a buffer object. String is treated a list + * of buffer elements, each separated by a space or comma. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbConvertToBuffer ( + char *String, + ACPI_OBJECT *Object) +{ + UINT32 i; + UINT32 j; + UINT32 Length; + UINT8 *Buffer; + ACPI_STATUS Status; + + + /* Generate the final buffer length */ + + for (i = 0, Length = 0; String[i];) + { + i+=2; + Length++; + + while (String[i] && + ((String[i] == ',') || (String[i] == ' '))) + { + i++; + } + } + + Buffer = ACPI_ALLOCATE (Length); + if (!Buffer) + { + return (AE_NO_MEMORY); + } + + /* Convert the command line bytes to the buffer */ + + for (i = 0, j = 0; String[i];) + { + Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (Buffer); + return (Status); + } + + j++; + i+=2; + while (String[i] && + ((String[i] == ',') || (String[i] == ' '))) + { + i++; + } + } + + Object->Type = ACPI_TYPE_BUFFER; + Object->Buffer.Pointer = Buffer; + Object->Buffer.Length = Length; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbConvertToPackage + * + * PARAMETERS: String - Input string to be converted + * Object - Where the package object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a string to a package object. Handles nested packages + * via recursion with AcpiDbConvertToObject. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbConvertToPackage ( + char *String, + ACPI_OBJECT *Object) +{ + char *This; + char *Next; + UINT32 i; + ACPI_OBJECT_TYPE Type; + ACPI_OBJECT *Elements; + ACPI_STATUS Status; + + + Elements = ACPI_ALLOCATE_ZEROED ( + DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT)); + + This = String; + for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) + { + This = AcpiDbGetNextToken (This, &Next, &Type); + if (!This) + { + break; + } + + /* Recursive call to convert each package element */ + + Status = AcpiDbConvertToObject (Type, This, &Elements[i]); + if (ACPI_FAILURE (Status)) + { + AcpiDbDeleteObjects (i + 1, Elements); + ACPI_FREE (Elements); + return (Status); + } + + This = Next; + } + + Object->Type = ACPI_TYPE_PACKAGE; + Object->Package.Count = i; + Object->Package.Elements = Elements; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbConvertToObject + * + * PARAMETERS: Type - Object type as determined by parser + * String - Input string to be converted + * Object - Where the new object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing: + * 1) String objects were surrounded by quotes. + * 2) Buffer objects were surrounded by parentheses. + * 3) Package objects were surrounded by brackets "[]". + * 4) All standalone tokens are treated as integers. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbConvertToObject ( + ACPI_OBJECT_TYPE Type, + char *String, + ACPI_OBJECT *Object) +{ + ACPI_STATUS Status = AE_OK; + + + switch (Type) + { + case ACPI_TYPE_STRING: + Object->Type = ACPI_TYPE_STRING; + Object->String.Pointer = String; + Object->String.Length = (UINT32) ACPI_STRLEN (String); + break; + + case ACPI_TYPE_BUFFER: + Status = AcpiDbConvertToBuffer (String, Object); + break; + + case ACPI_TYPE_PACKAGE: + Status = AcpiDbConvertToPackage (String, Object); + break; + + default: + Object->Type = ACPI_TYPE_INTEGER; + Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value); + break; + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDeleteObjects + * + * PARAMETERS: Count - Count of objects in the list + * Objects - Array of ACPI_OBJECTs to be deleted + * + * RETURN: None + * + * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested + * packages via recursion. + * + ******************************************************************************/ + +static void +AcpiDbDeleteObjects ( + UINT32 Count, + ACPI_OBJECT *Objects) +{ + UINT32 i; + + + for (i = 0; i < Count; i++) + { + switch (Objects[i].Type) + { + case ACPI_TYPE_BUFFER: + ACPI_FREE (Objects[i].Buffer.Pointer); + break; + + case ACPI_TYPE_PACKAGE: + + /* Recursive call to delete package elements */ + + AcpiDbDeleteObjects (Objects[i].Package.Count, + Objects[i].Package.Elements); + + /* Free the elements array */ + + ACPI_FREE (Objects[i].Package.Elements); + break; + + default: + break; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbExecuteMethod + * + * PARAMETERS: Info - Valid info segment + * ReturnObj - Where to put return object + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbExecuteMethod ( + ACPI_DB_METHOD_INFO *Info, + ACPI_BUFFER *ReturnObj) +{ + ACPI_STATUS Status; + ACPI_OBJECT_LIST ParamObjects; + ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; + ACPI_HANDLE Handle; + ACPI_DEVICE_INFO *ObjInfo; + UINT32 i; + + + ACPI_FUNCTION_TRACE (DbExecuteMethod); + + + if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) + { + AcpiOsPrintf ("Warning: debug output is not enabled!\n"); + } + + /* Get the NS node, determines existence also */ + + Status = AcpiGetHandle (NULL, Info->Pathname, &Handle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the object info for number of method parameters */ + + Status = AcpiGetObjectInfo (Handle, &ObjInfo); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ParamObjects.Pointer = NULL; + ParamObjects.Count = 0; + + if (ObjInfo->Type == ACPI_TYPE_METHOD) + { + /* Are there arguments to the method? */ + + i = 0; + if (Info->Args && Info->Args[0]) + { + /* Get arguments passed on the command line */ + + for (; Info->Args[i] && + (i < ACPI_METHOD_NUM_ARGS) && + (i < ObjInfo->ParamCount); + i++) + { + /* Convert input string (token) to an actual ACPI_OBJECT */ + + Status = AcpiDbConvertToObject (Info->Types[i], + Info->Args[i], &Params[i]); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While parsing method arguments")); + goto Cleanup; + } + } + } + + /* Create additional "default" parameters as needed */ + + if (i < ObjInfo->ParamCount) + { + AcpiOsPrintf ("Adding %u arguments containing default values\n", + ObjInfo->ParamCount - i); + + for (; i < ObjInfo->ParamCount; i++) + { + switch (i) + { + case 0: + + Params[0].Type = ACPI_TYPE_INTEGER; + Params[0].Integer.Value = 0x01020304; + break; + + case 1: + + Params[1].Type = ACPI_TYPE_STRING; + Params[1].String.Length = 12; + Params[1].String.Pointer = "AML Debugger"; + break; + + default: + + Params[i].Type = ACPI_TYPE_INTEGER; + Params[i].Integer.Value = i * (UINT64) 0x1000; + break; + } + } + } + + ParamObjects.Count = ObjInfo->ParamCount; + ParamObjects.Pointer = Params; + } + + /* Prepare for a return object of arbitrary size */ + + ReturnObj->Pointer = AcpiGbl_DbBuffer; + ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; + + /* Do the actual method execution */ + + AcpiGbl_MethodExecuting = TRUE; + Status = AcpiEvaluateObject (NULL, + Info->Pathname, &ParamObjects, ReturnObj); + + AcpiGbl_CmSingleStep = FALSE; + AcpiGbl_MethodExecuting = FALSE; + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "while executing %s from debugger", Info->Pathname)); + + if (Status == AE_BUFFER_OVERFLOW) + { + ACPI_ERROR ((AE_INFO, + "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)", + ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); + } + } + +Cleanup: + AcpiDbDeleteObjects (ObjInfo->ParamCount, Params); + ACPI_FREE (ObjInfo); + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbExecuteSetup + * + * PARAMETERS: Info - Valid method info + * + * RETURN: None + * + * DESCRIPTION: Setup info segment prior to method execution + * + ******************************************************************************/ + +static void +AcpiDbExecuteSetup ( + ACPI_DB_METHOD_INFO *Info) +{ + + /* Catenate the current scope to the supplied name */ + + Info->Pathname[0] = 0; + if ((Info->Name[0] != '\\') && + (Info->Name[0] != '/')) + { + ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); + } + + ACPI_STRCAT (Info->Pathname, Info->Name); + AcpiDbPrepNamestring (Info->Pathname); + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + AcpiOsPrintf ("Executing %s\n", Info->Pathname); + + if (Info->Flags & EX_SINGLE_STEP) + { + AcpiGbl_CmSingleStep = TRUE; + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + } + + else + { + /* No single step, allow redirection to a file */ + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + } +} + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +UINT32 +AcpiDbGetCacheInfo ( + ACPI_MEMORY_LIST *Cache) +{ + + return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); +} +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetOutstandingAllocations + * + * PARAMETERS: None + * + * RETURN: Current global allocation count minus cache entries + * + * DESCRIPTION: Determine the current number of "outstanding" allocations -- + * those allocations that have not been freed and also are not + * in one of the various object caches. + * + ******************************************************************************/ + +static UINT32 +AcpiDbGetOutstandingAllocations ( + void) +{ + UINT32 Outstanding = 0; + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); + Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); + Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); + Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); +#endif + + return (Outstanding); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbExecutionWalk + * + * PARAMETERS: WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. Name is relative to the current + * scope. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbExecutionWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_BUFFER ReturnObj; + ACPI_STATUS Status; + + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc->Method.ParamCount) + { + return (AE_OK); + } + + ReturnObj.Pointer = NULL; + ReturnObj.Length = ACPI_ALLOCATE_BUFFER; + + AcpiNsPrintNodePathname (Node, "Execute"); + + /* Do the actual method execution */ + + AcpiOsPrintf ("\n"); + AcpiGbl_MethodExecuting = TRUE; + + Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); + + AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node), + AcpiFormatException (Status)); + AcpiGbl_MethodExecuting = FALSE; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbExecute + * + * PARAMETERS: Name - Name of method to execute + * Args - Parameters to the method + * Flags - single step/no single step + * + * RETURN: None + * + * DESCRIPTION: Execute a control method. Name is relative to the current + * scope. + * + ******************************************************************************/ + +void +AcpiDbExecute ( + char *Name, + char **Args, + ACPI_OBJECT_TYPE *Types, + UINT32 Flags) +{ + ACPI_STATUS Status; + ACPI_BUFFER ReturnObj; + char *NameString; + + +#ifdef ACPI_DEBUG_OUTPUT + UINT32 PreviousAllocations; + UINT32 Allocations; + + + /* Memory allocation tracking */ + + PreviousAllocations = AcpiDbGetOutstandingAllocations (); +#endif + + if (*Name == '*') + { + (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); + return; + } + else + { + NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); + if (!NameString) + { + return; + } + + ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); + + ACPI_STRCPY (NameString, Name); + AcpiUtStrupr (NameString); + AcpiGbl_DbMethodInfo.Name = NameString; + AcpiGbl_DbMethodInfo.Args = Args; + AcpiGbl_DbMethodInfo.Types = Types; + AcpiGbl_DbMethodInfo.Flags = Flags; + + ReturnObj.Pointer = NULL; + ReturnObj.Length = ACPI_ALLOCATE_BUFFER; + + AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); + Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); + ACPI_FREE (NameString); + } + + /* + * Allow any handlers in separate threads to complete. + * (Such as Notify handlers invoked from AML executed above). + */ + AcpiOsSleep ((UINT64) 10); + + +#ifdef ACPI_DEBUG_OUTPUT + + /* Memory allocation tracking */ + + Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + + if (Allocations > 0) + { + AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n", + Allocations); + } +#endif + + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Execution of %s failed with status %s\n", + AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); + } + else + { + /* Display a return object, if any */ + + if (ReturnObj.Length) + { + AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", + AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, + (UINT32) ReturnObj.Length); + AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); + } + else + { + AcpiOsPrintf ("No return object from execution of %s\n", + AcpiGbl_DbMethodInfo.Pathname); + } + } + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbMethodThread + * + * PARAMETERS: Context - Execution info segment + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE +AcpiDbMethodThread ( + void *Context) +{ + ACPI_STATUS Status; + ACPI_DB_METHOD_INFO *Info = Context; + ACPI_DB_METHOD_INFO LocalInfo; + UINT32 i; + UINT8 Allow; + ACPI_BUFFER ReturnObj; + + + /* + * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. + * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads + * concurrently. + * + * Note: The arguments we are passing are used by the ASL test suite + * (aslts). Do not change them without updating the tests. + */ + (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); + + if (Info->InitArgs) + { + AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); + AcpiDbUInt32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr); + } + + if (Info->Threads && (Info->NumCreated < Info->NumThreads)) + { + Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); + } + + LocalInfo = *Info; + LocalInfo.Args = LocalInfo.Arguments; + LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; + LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; + LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; + LocalInfo.Arguments[3] = NULL; + + LocalInfo.Types = LocalInfo.ArgTypes; + + (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); + + for (i = 0; i < Info->NumLoops; i++) + { + Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("%s During execution of %s at iteration %X\n", + AcpiFormatException (Status), Info->Pathname, i); + if (Status == AE_ABORT_METHOD) + { + break; + } + } + +#if 0 + if ((i % 100) == 0) + { + AcpiOsPrintf ("%u executions, Thread 0x%x\n", i, AcpiOsGetThreadId ()); + } + + if (ReturnObj.Length) + { + AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", + Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); + AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); + } +#endif + } + + /* Signal our completion */ + + Allow = 0; + (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); + Info->NumCompleted++; + + if (Info->NumCompleted == Info->NumThreads) + { + /* Do signal for main thread once only */ + Allow = 1; + } + + (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); + + if (Allow) + { + Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", + AcpiFormatException (Status)); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbCreateExecutionThreads + * + * PARAMETERS: NumThreadsArg - Number of threads to create + * NumLoopsArg - Loop count for the thread(s) + * MethodNameArg - Control method to execute + * + * RETURN: None + * + * DESCRIPTION: Create threads to execute method(s) + * + ******************************************************************************/ + +void +AcpiDbCreateExecutionThreads ( + char *NumThreadsArg, + char *NumLoopsArg, + char *MethodNameArg) +{ + ACPI_STATUS Status; + UINT32 NumThreads; + UINT32 NumLoops; + UINT32 i; + UINT32 Size; + ACPI_MUTEX MainThreadGate; + ACPI_MUTEX ThreadCompleteGate; + ACPI_MUTEX InfoGate; + + + /* Get the arguments */ + + NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); + NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); + + if (!NumThreads || !NumLoops) + { + AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", + NumThreads, NumLoops); + return; + } + + /* + * Create the semaphore for synchronization of + * the created threads with the main thread. + */ + Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", + AcpiFormatException (Status)); + return; + } + + /* + * Create the semaphore for synchronization + * between the created threads. + */ + Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", + AcpiFormatException (Status)); + (void) AcpiOsDeleteSemaphore (MainThreadGate); + return; + } + + Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", + AcpiFormatException (Status)); + (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); + (void) AcpiOsDeleteSemaphore (MainThreadGate); + return; + } + + ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); + + /* Array to store IDs of threads */ + + AcpiGbl_DbMethodInfo.NumThreads = NumThreads; + Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; + AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); + if (AcpiGbl_DbMethodInfo.Threads == NULL) + { + AcpiOsPrintf ("No memory for thread IDs array\n"); + (void) AcpiOsDeleteSemaphore (MainThreadGate); + (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); + (void) AcpiOsDeleteSemaphore (InfoGate); + return; + } + ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); + + /* Setup the context to be passed to each thread */ + + AcpiGbl_DbMethodInfo.Name = MethodNameArg; + AcpiGbl_DbMethodInfo.Flags = 0; + AcpiGbl_DbMethodInfo.NumLoops = NumLoops; + AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; + AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; + AcpiGbl_DbMethodInfo.InfoGate = InfoGate; + + /* Init arguments to be passed to method */ + + AcpiGbl_DbMethodInfo.InitArgs = 1; + AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; + AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; + AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; + AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; + AcpiGbl_DbMethodInfo.Arguments[3] = NULL; + + AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; + AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; + AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; + AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; + + AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); + + AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); + + /* Create the threads */ + + AcpiOsPrintf ("Creating %X threads to execute %X times each\n", + NumThreads, NumLoops); + + for (i = 0; i < (NumThreads); i++) + { + Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, + &AcpiGbl_DbMethodInfo); + if (ACPI_FAILURE (Status)) + { + break; + } + } + + /* Wait for all threads to complete */ + + (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + + /* Cleanup and exit */ + + (void) AcpiOsDeleteSemaphore (MainThreadGate); + (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); + (void) AcpiOsDeleteSemaphore (InfoGate); + + AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); + AcpiGbl_DbMethodInfo.Threads = NULL; +} + +#endif /* ACPI_DEBUGGER */ + + diff --git a/source/components/debugger/dbfileio.c b/source/components/debugger/dbfileio.c new file mode 100644 index 000000000000..ef9b7fef5379 --- /dev/null +++ b/source/components/debugger/dbfileio.c @@ -0,0 +1,578 @@ +/******************************************************************************* + * + * Module Name: dbfileio - Debugger file I/O commands. These can't usually + * be used when running the debugger in Ring 0 (Kernel mode) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#ifdef ACPI_APPLICATION +#include "actables.h" +#endif + +#if (defined ACPI_DEBUGGER || defined ACPI_DISASSEMBLER) + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbfileio") + +/* + * NOTE: this is here for lack of a better place. It is used in all + * flavors of the debugger, need LCD file + */ +#ifdef ACPI_APPLICATION +#include +FILE *AcpiGbl_DebugFile = NULL; +#endif + + +#ifdef ACPI_DEBUGGER + +/* Local prototypes */ + +#ifdef ACPI_APPLICATION + +static ACPI_STATUS +AcpiDbCheckTextModeCorruption ( + UINT8 *Table, + UINT32 TableLength, + UINT32 FileLength); + +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiDbCloseDebugFile + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: If open, close the current debug output file + * + ******************************************************************************/ + +void +AcpiDbCloseDebugFile ( + void) +{ + +#ifdef ACPI_APPLICATION + + if (AcpiGbl_DebugFile) + { + fclose (AcpiGbl_DebugFile); + AcpiGbl_DebugFile = NULL; + AcpiGbl_DbOutputToFile = FALSE; + AcpiOsPrintf ("Debug output file %s closed\n", AcpiGbl_DbDebugFilename); + } +#endif +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbOpenDebugFile + * + * PARAMETERS: Name - Filename to open + * + * RETURN: None + * + * DESCRIPTION: Open a file where debug output will be directed. + * + ******************************************************************************/ + +void +AcpiDbOpenDebugFile ( + char *Name) +{ + +#ifdef ACPI_APPLICATION + + AcpiDbCloseDebugFile (); + AcpiGbl_DebugFile = fopen (Name, "w+"); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("Debug output file %s opened\n", Name); + ACPI_STRCPY (AcpiGbl_DbDebugFilename, Name); + AcpiGbl_DbOutputToFile = TRUE; + } + else + { + AcpiOsPrintf ("Could not open debug file %s\n", Name); + } + +#endif +} +#endif + + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: AcpiDbCheckTextModeCorruption + * + * PARAMETERS: Table - Table buffer + * TableLength - Length of table from the table header + * FileLength - Length of the file that contains the table + * + * RETURN: Status + * + * DESCRIPTION: Check table for text mode file corruption where all linefeed + * characters (LF) have been replaced by carriage return linefeed + * pairs (CR/LF). + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbCheckTextModeCorruption ( + UINT8 *Table, + UINT32 TableLength, + UINT32 FileLength) +{ + UINT32 i; + UINT32 Pairs = 0; + + + if (TableLength != FileLength) + { + ACPI_WARNING ((AE_INFO, + "File length (0x%X) is not the same as the table length (0x%X)", + FileLength, TableLength)); + } + + /* Scan entire table to determine if each LF has been prefixed with a CR */ + + for (i = 1; i < FileLength; i++) + { + if (Table[i] == 0x0A) + { + if (Table[i - 1] != 0x0D) + { + /* The LF does not have a preceding CR, table not corrupted */ + + return (AE_OK); + } + else + { + /* Found a CR/LF pair */ + + Pairs++; + } + i++; + } + } + + if (!Pairs) + { + return (AE_OK); + } + + /* + * Entire table scanned, each CR is part of a CR/LF pair -- + * meaning that the table was treated as a text file somewhere. + * + * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the + * original table are left untouched by the text conversion process -- + * meaning that we cannot simply replace CR/LF pairs with LFs. + */ + AcpiOsPrintf ("Table has been corrupted by text mode conversion\n"); + AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs); + AcpiOsPrintf ("Table cannot be repaired!\n"); + return (AE_BAD_VALUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbReadTable + * + * PARAMETERS: fp - File that contains table + * Table - Return value, buffer with table + * TableLength - Return value, length of table + * + * RETURN: Status + * + * DESCRIPTION: Load the DSDT from the file pointer + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbReadTable ( + FILE *fp, + ACPI_TABLE_HEADER **Table, + UINT32 *TableLength) +{ + ACPI_TABLE_HEADER TableHeader; + UINT32 Actual; + ACPI_STATUS Status; + UINT32 FileSize; + BOOLEAN StandardHeader = TRUE; + + + /* Get the file size */ + + fseek (fp, 0, SEEK_END); + FileSize = (UINT32) ftell (fp); + fseek (fp, 0, SEEK_SET); + + if (FileSize < 4) + { + return (AE_BAD_HEADER); + } + + /* Read the signature */ + + if (fread (&TableHeader, 1, 4, fp) != 4) + { + AcpiOsPrintf ("Could not read the table signature\n"); + return (AE_BAD_HEADER); + } + + fseek (fp, 0, SEEK_SET); + + /* The RSDT, FACS and S3PT tables do not have standard ACPI headers */ + + if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD ") || + ACPI_COMPARE_NAME (TableHeader.Signature, "FACS") || + ACPI_COMPARE_NAME (TableHeader.Signature, "S3PT")) + { + *TableLength = FileSize; + StandardHeader = FALSE; + } + else + { + /* Read the table header */ + + if (fread (&TableHeader, 1, sizeof (TableHeader), fp) != + sizeof (ACPI_TABLE_HEADER)) + { + AcpiOsPrintf ("Could not read the table header\n"); + return (AE_BAD_HEADER); + } + +#if 0 + /* Validate the table header/length */ + + Status = AcpiTbValidateTableHeader (&TableHeader); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Table header is invalid!\n"); + return (Status); + } +#endif + + /* File size must be at least as long as the Header-specified length */ + + if (TableHeader.Length > FileSize) + { + AcpiOsPrintf ( + "TableHeader length [0x%X] greater than the input file size [0x%X]\n", + TableHeader.Length, FileSize); + return (AE_BAD_HEADER); + } + +#ifdef ACPI_OBSOLETE_CODE + /* We only support a limited number of table types */ + + if (ACPI_STRNCMP ((char *) TableHeader.Signature, DSDT_SIG, 4) && + ACPI_STRNCMP ((char *) TableHeader.Signature, PSDT_SIG, 4) && + ACPI_STRNCMP ((char *) TableHeader.Signature, SSDT_SIG, 4)) + { + AcpiOsPrintf ("Table signature [%4.4s] is invalid or not supported\n", + (char *) TableHeader.Signature); + ACPI_DUMP_BUFFER (&TableHeader, sizeof (ACPI_TABLE_HEADER)); + return (AE_ERROR); + } +#endif + + *TableLength = TableHeader.Length; + } + + /* Allocate a buffer for the table */ + + *Table = AcpiOsAllocate ((size_t) FileSize); + if (!*Table) + { + AcpiOsPrintf ( + "Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", + TableHeader.Signature, *TableLength); + return (AE_NO_MEMORY); + } + + /* Get the rest of the table */ + + fseek (fp, 0, SEEK_SET); + Actual = fread (*Table, 1, (size_t) FileSize, fp); + if (Actual == FileSize) + { + if (StandardHeader) + { + /* Now validate the checksum */ + + Status = AcpiTbVerifyChecksum ((void *) *Table, + ACPI_CAST_PTR (ACPI_TABLE_HEADER, *Table)->Length); + + if (Status == AE_BAD_CHECKSUM) + { + Status = AcpiDbCheckTextModeCorruption ((UINT8 *) *Table, + FileSize, (*Table)->Length); + return (Status); + } + } + return (AE_OK); + } + + if (Actual > 0) + { + AcpiOsPrintf ("Warning - reading table, asked for %X got %X\n", + FileSize, Actual); + return (AE_OK); + } + + AcpiOsPrintf ("Error - could not read the table file\n"); + AcpiOsFree (*Table); + *Table = NULL; + *TableLength = 0; + + return (AE_ERROR); +} + + +/******************************************************************************* + * + * FUNCTION: AeLocalLoadTable + * + * PARAMETERS: Table - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + ******************************************************************************/ + +static ACPI_STATUS +AeLocalLoadTable ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status = AE_OK; +/* ACPI_TABLE_DESC TableInfo; */ + + + ACPI_FUNCTION_TRACE (AeLocalLoadTable); +#if 0 + + + if (!Table) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + TableInfo.Pointer = Table; + Status = AcpiTbRecognizeTable (&TableInfo, ACPI_TABLE_ALL); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Install the new table into the local data structures */ + + Status = AcpiTbInstallTable (&TableInfo); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_ALREADY_EXISTS) + { + /* Table already exists, no error */ + + Status = AE_OK; + } + + /* Free table allocated by AcpiTbGetTable */ + + AcpiTbDeleteSingleTable (&TableInfo); + return_ACPI_STATUS (Status); + } + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + Status = AcpiNsLoadTable (TableInfo.InstalledDesc, AcpiGbl_RootNode); + if (ACPI_FAILURE (Status)) + { + /* Uninstall table and free the buffer */ + + AcpiTbDeleteTablesByType (ACPI_TABLE_ID_DSDT); + return_ACPI_STATUS (Status); + } +#endif +#endif + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbReadTableFromFile + * + * PARAMETERS: Filename - File where table is located + * Table - Where a pointer to the table is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table from a file + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbReadTableFromFile ( + char *Filename, + ACPI_TABLE_HEADER **Table) +{ + FILE *fp; + UINT32 TableLength; + ACPI_STATUS Status; + + + /* Open the file */ + + fp = fopen (Filename, "rb"); + if (!fp) + { + AcpiOsPrintf ("Could not open input file %s\n", Filename); + return (AE_ERROR); + } + + /* Get the entire file */ + + fprintf (stderr, "Loading Acpi table from file %s\n", Filename); + Status = AcpiDbReadTable (fp, Table, &TableLength); + fclose(fp); + + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get table from the file\n"); + return (Status); + } + + return (AE_OK); + } +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetTableFromFile + * + * PARAMETERS: Filename - File where table is located + * ReturnTable - Where a pointer to the table is returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a file + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbGetTableFromFile ( + char *Filename, + ACPI_TABLE_HEADER **ReturnTable) +{ +#ifdef ACPI_APPLICATION + ACPI_STATUS Status; + ACPI_TABLE_HEADER *Table; + BOOLEAN IsAmlTable = TRUE; + + + Status = AcpiDbReadTableFromFile (Filename, &Table); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + +#ifdef ACPI_DATA_TABLE_DISASSEMBLY + IsAmlTable = AcpiUtIsAmlTable (Table); +#endif + + if (IsAmlTable) + { + /* Attempt to recognize and install the table */ + + Status = AeLocalLoadTable (Table); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_ALREADY_EXISTS) + { + AcpiOsPrintf ("Table %4.4s is already installed\n", + Table->Signature); + } + else + { + AcpiOsPrintf ("Could not install table, %s\n", + AcpiFormatException (Status)); + } + + return (Status); + } + + fprintf (stderr, + "Acpi table [%4.4s] successfully installed and loaded\n", + Table->Signature); + } + + AcpiGbl_AcpiHardwarePresent = FALSE; + if (ReturnTable) + { + *ReturnTable = Table; + } + + +#endif /* ACPI_APPLICATION */ + return (AE_OK); +} + +#endif /* ACPI_DEBUGGER */ + diff --git a/source/components/debugger/dbhistry.c b/source/components/debugger/dbhistry.c new file mode 100644 index 000000000000..536b69cdfaab --- /dev/null +++ b/source/components/debugger/dbhistry.c @@ -0,0 +1,220 @@ +/****************************************************************************** + * + * Module Name: dbhistry - debugger HISTORY command + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbhistry") + + +#define HI_NO_HISTORY 0 +#define HI_RECORD_HISTORY 1 +#define HISTORY_SIZE 20 + + +typedef struct HistoryInfo +{ + char Command[80]; + UINT32 CmdNum; + +} HISTORY_INFO; + + +static HISTORY_INFO AcpiGbl_HistoryBuffer[HISTORY_SIZE]; +static UINT16 AcpiGbl_LoHistory = 0; +static UINT16 AcpiGbl_NumHistory = 0; +static UINT16 AcpiGbl_NextHistoryIndex = 0; +static UINT32 AcpiGbl_NextCmdNum = 1; + + +/******************************************************************************* + * + * FUNCTION: AcpiDbAddToHistory + * + * PARAMETERS: CommandLine - Command to add + * + * RETURN: None + * + * DESCRIPTION: Add a command line to the history buffer. + * + ******************************************************************************/ + +void +AcpiDbAddToHistory ( + char *CommandLine) +{ + + /* Put command into the next available slot */ + + ACPI_STRCPY (AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].Command, + CommandLine); + + AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].CmdNum = AcpiGbl_NextCmdNum; + + /* Adjust indexes */ + + if ((AcpiGbl_NumHistory == HISTORY_SIZE) && + (AcpiGbl_NextHistoryIndex == AcpiGbl_LoHistory)) + { + AcpiGbl_LoHistory++; + if (AcpiGbl_LoHistory >= HISTORY_SIZE) + { + AcpiGbl_LoHistory = 0; + } + } + + AcpiGbl_NextHistoryIndex++; + if (AcpiGbl_NextHistoryIndex >= HISTORY_SIZE) + { + AcpiGbl_NextHistoryIndex = 0; + } + + AcpiGbl_NextCmdNum++; + if (AcpiGbl_NumHistory < HISTORY_SIZE) + { + AcpiGbl_NumHistory++; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayHistory + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the contents of the history buffer + * + ******************************************************************************/ + +void +AcpiDbDisplayHistory ( + void) +{ + UINT32 i; + UINT16 HistoryIndex; + + + HistoryIndex = AcpiGbl_LoHistory; + + /* Dump entire history buffer */ + + for (i = 0; i < AcpiGbl_NumHistory; i++) + { + AcpiOsPrintf ("%ld %s\n", AcpiGbl_HistoryBuffer[HistoryIndex].CmdNum, + AcpiGbl_HistoryBuffer[HistoryIndex].Command); + + HistoryIndex++; + if (HistoryIndex >= HISTORY_SIZE) + { + HistoryIndex = 0; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetFromHistory + * + * PARAMETERS: CommandNumArg - String containing the number of the + * command to be retrieved + * + * RETURN: Pointer to the retrieved command. Null on error. + * + * DESCRIPTION: Get a command from the history buffer + * + ******************************************************************************/ + +char * +AcpiDbGetFromHistory ( + char *CommandNumArg) +{ + UINT32 i; + UINT16 HistoryIndex; + UINT32 CmdNum; + + + if (CommandNumArg == NULL) + { + CmdNum = AcpiGbl_NextCmdNum - 1; + } + + else + { + CmdNum = ACPI_STRTOUL (CommandNumArg, NULL, 0); + } + + /* Search history buffer */ + + HistoryIndex = AcpiGbl_LoHistory; + for (i = 0; i < AcpiGbl_NumHistory; i++) + { + if (AcpiGbl_HistoryBuffer[HistoryIndex].CmdNum == CmdNum) + { + /* Found the commnad, return it */ + + return (AcpiGbl_HistoryBuffer[HistoryIndex].Command); + } + + + HistoryIndex++; + if (HistoryIndex >= HISTORY_SIZE) + { + HistoryIndex = 0; + } + } + + AcpiOsPrintf ("Invalid history number: %u\n", HistoryIndex); + return (NULL); +} + +#endif /* ACPI_DEBUGGER */ + diff --git a/source/components/debugger/dbinput.c b/source/components/debugger/dbinput.c new file mode 100644 index 000000000000..0ae313934b40 --- /dev/null +++ b/source/components/debugger/dbinput.c @@ -0,0 +1,1091 @@ +/******************************************************************************* + * + * Module Name: dbinput - user front-end to the AML debugger + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbinput") + +/* Local prototypes */ + +static UINT32 +AcpiDbGetLine ( + char *InputBuffer); + +static UINT32 +AcpiDbMatchCommand ( + char *UserCommand); + +static void +AcpiDbSingleThread ( + void); + +static void +AcpiDbDisplayHelp ( + void); + + +/* + * Top-level debugger commands. + * + * This list of commands must match the string table below it + */ +enum AcpiExDebuggerCommands +{ + CMD_NOT_FOUND = 0, + CMD_NULL, + CMD_ALLOCATIONS, + CMD_ARGS, + CMD_ARGUMENTS, + CMD_BATCH, + CMD_BREAKPOINT, + CMD_BUSINFO, + CMD_CALL, + CMD_CLOSE, + CMD_DEBUG, + CMD_DISASSEMBLE, + CMD_DUMP, + CMD_ENABLEACPI, + CMD_EVENT, + CMD_EXECUTE, + CMD_EXIT, + CMD_FIND, + CMD_GO, + CMD_GPE, + CMD_GPES, + CMD_HANDLERS, + CMD_HELP, + CMD_HELP2, + CMD_HISTORY, + CMD_HISTORY_EXE, + CMD_HISTORY_LAST, + CMD_INFORMATION, + CMD_INTEGRITY, + CMD_INTO, + CMD_LEVEL, + CMD_LIST, + CMD_LOAD, + CMD_LOCALS, + CMD_LOCKS, + CMD_METHODS, + CMD_NAMESPACE, + CMD_NOTIFY, + CMD_OBJECT, + CMD_OPEN, + CMD_OSI, + CMD_OWNER, + CMD_PREDEFINED, + CMD_PREFIX, + CMD_QUIT, + CMD_REFERENCES, + CMD_RESOURCES, + CMD_RESULTS, + CMD_SET, + CMD_SLEEP, + CMD_STATS, + CMD_STOP, + CMD_TABLES, + CMD_TEMPLATE, + CMD_TERMINATE, + CMD_THREADS, + CMD_TRACE, + CMD_TREE, + CMD_TYPE, + CMD_UNLOAD +}; + +#define CMD_FIRST_VALID 2 + + +/* Second parameter is the required argument count */ + +static const COMMAND_INFO AcpiGbl_DbCommands[] = +{ + {"", 0}, + {"", 0}, + {"ALLOCATIONS", 0}, + {"ARGS", 0}, + {"ARGUMENTS", 0}, + {"BATCH", 0}, + {"BREAKPOINT", 1}, + {"BUSINFO", 0}, + {"CALL", 0}, + {"CLOSE", 0}, + {"DEBUG", 1}, + {"DISASSEMBLE", 1}, + {"DUMP", 1}, + {"ENABLEACPI", 0}, + {"EVENT", 1}, + {"EXECUTE", 1}, + {"EXIT", 0}, + {"FIND", 1}, + {"GO", 0}, + {"GPE", 2}, + {"GPES", 0}, + {"HANDLERS", 0}, + {"HELP", 0}, + {"?", 0}, + {"HISTORY", 0}, + {"!", 1}, + {"!!", 0}, + {"INFORMATION", 0}, + {"INTEGRITY", 0}, + {"INTO", 0}, + {"LEVEL", 0}, + {"LIST", 0}, + {"LOAD", 1}, + {"LOCALS", 0}, + {"LOCKS", 0}, + {"METHODS", 0}, + {"NAMESPACE", 0}, + {"NOTIFY", 2}, + {"OBJECT", 1}, + {"OPEN", 1}, + {"OSI", 0}, + {"OWNER", 1}, + {"PREDEFINED", 0}, + {"PREFIX", 0}, + {"QUIT", 0}, + {"REFERENCES", 1}, + {"RESOURCES", 1}, + {"RESULTS", 0}, + {"SET", 3}, + {"SLEEP", 1}, + {"STATS", 0}, + {"STOP", 0}, + {"TABLES", 0}, + {"TEMPLATE", 1}, + {"TERMINATE", 0}, + {"THREADS", 3}, + {"TRACE", 1}, + {"TREE", 0}, + {"TYPE", 1}, + {"UNLOAD", 1}, + {NULL, 0} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayHelp + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print a usage message. + * + ******************************************************************************/ + +static void +AcpiDbDisplayHelp ( + void) +{ + + AcpiOsPrintf ("\nGeneral-Purpose Commands:\n"); + AcpiOsPrintf (" Allocations Display list of current memory allocations\n"); + AcpiOsPrintf (" Dump
|\n"); + AcpiOsPrintf (" [Byte|Word|Dword|Qword] Display ACPI objects or memory\n"); + AcpiOsPrintf (" EnableAcpi Enable ACPI (hardware) mode\n"); + AcpiOsPrintf (" Handlers Info about global handlers\n"); + AcpiOsPrintf (" Help This help screen\n"); + AcpiOsPrintf (" History Display command history buffer\n"); + AcpiOsPrintf (" Level [] [console] Get/Set debug level for file or console\n"); + AcpiOsPrintf (" Locks Current status of internal mutexes\n"); + AcpiOsPrintf (" Osi [Install|Remove ] Display or modify global _OSI list\n"); + AcpiOsPrintf (" Quit or Exit Exit this command\n"); + AcpiOsPrintf (" Stats [Allocations|Memory|Misc|\n"); + AcpiOsPrintf (" Objects|Sizes|Stack|Tables] Display namespace and memory statistics\n"); + AcpiOsPrintf (" Allocations Display list of current memory allocations\n"); + AcpiOsPrintf (" Memory Dump internal memory lists\n"); + AcpiOsPrintf (" Misc Namespace search and mutex stats\n"); + AcpiOsPrintf (" Objects Summary of namespace objects\n"); + AcpiOsPrintf (" Sizes Sizes for each of the internal objects\n"); + AcpiOsPrintf (" Stack Display CPU stack usage\n"); + AcpiOsPrintf (" Tables Info about current ACPI table(s)\n"); + AcpiOsPrintf (" Tables Display info about loaded ACPI tables\n"); + AcpiOsPrintf (" Unload [Instance] Unload an ACPI table\n"); + AcpiOsPrintf (" ! Execute command from history buffer\n"); + AcpiOsPrintf (" !! Execute last command again\n"); + + AcpiOsPrintf ("\nNamespace Access Commands:\n"); + AcpiOsPrintf (" Businfo Display system bus info\n"); + AcpiOsPrintf (" Disassemble Disassemble a control method\n"); + AcpiOsPrintf (" Event Generate AcpiEvent (Fixed/GPE)\n"); + AcpiOsPrintf (" Find (? is wildcard) Find ACPI name(s) with wildcards\n"); + AcpiOsPrintf (" Gpe Simulate a GPE\n"); + AcpiOsPrintf (" Gpes Display info on all GPEs\n"); + AcpiOsPrintf (" Integrity Validate namespace integrity\n"); + AcpiOsPrintf (" Methods Display list of loaded control methods\n"); + AcpiOsPrintf (" Namespace [Object] [Depth] Display loaded namespace tree/subtree\n"); + AcpiOsPrintf (" Notify Send a notification on Object\n"); + AcpiOsPrintf (" Objects Display all objects of the given type\n"); + AcpiOsPrintf (" Owner [Depth] Display loaded namespace by object owner\n"); + AcpiOsPrintf (" Predefined Check all predefined names\n"); + AcpiOsPrintf (" Prefix [] Set or Get current execution prefix\n"); + AcpiOsPrintf (" References Find all references to object at addr\n"); + AcpiOsPrintf (" Resources Display Device resources (* = all devices)\n"); + AcpiOsPrintf (" Set N Set value for named integer\n"); + AcpiOsPrintf (" Sleep Simulate sleep/wake sequence\n"); + AcpiOsPrintf (" Template Format/dump a Buffer/ResourceTemplate\n"); + AcpiOsPrintf (" Terminate Delete namespace and all internal objects\n"); + AcpiOsPrintf (" Type Display object type\n"); + + AcpiOsPrintf ("\nControl Method Execution Commands:\n"); + AcpiOsPrintf (" Arguments (or Args) Display method arguments\n"); + AcpiOsPrintf (" Breakpoint Set an AML execution breakpoint\n"); + AcpiOsPrintf (" Call Run to next control method invocation\n"); + AcpiOsPrintf (" Debug [Arguments] Single Step a control method\n"); + AcpiOsPrintf (" Execute [Arguments] Execute control method\n"); + AcpiOsPrintf (" Hex Integer Integer method argument\n"); + AcpiOsPrintf (" \"Ascii String\" String method argument\n"); + AcpiOsPrintf (" (Byte List) Buffer method argument\n"); + AcpiOsPrintf (" [Package Element List] Package method argument\n"); + AcpiOsPrintf (" Go Allow method to run to completion\n"); + AcpiOsPrintf (" Information Display info about the current method\n"); + AcpiOsPrintf (" Into Step into (not over) a method call\n"); + AcpiOsPrintf (" List [# of Aml Opcodes] Display method ASL statements\n"); + AcpiOsPrintf (" Locals Display method local variables\n"); + AcpiOsPrintf (" Results Display method result stack\n"); + AcpiOsPrintf (" Set <#> Set method data (Arguments/Locals)\n"); + AcpiOsPrintf (" Stop Terminate control method\n"); + AcpiOsPrintf (" Thread Spawn threads to execute method(s)\n"); + AcpiOsPrintf (" Trace Trace method execution\n"); + AcpiOsPrintf (" Tree Display control method calling tree\n"); + AcpiOsPrintf (" Single step next AML opcode (over calls)\n"); + + AcpiOsPrintf ("\nFile I/O Commands:\n"); + AcpiOsPrintf (" Close Close debug output file\n"); + AcpiOsPrintf (" Load Load ACPI table from a file\n"); + AcpiOsPrintf (" Open Open a file for debug output\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetNextToken + * + * PARAMETERS: String - Command buffer + * Next - Return value, end of next token + * + * RETURN: Pointer to the start of the next token. + * + * DESCRIPTION: Command line parsing. Get the next token on the command line + * + ******************************************************************************/ + +char * +AcpiDbGetNextToken ( + char *String, + char **Next, + ACPI_OBJECT_TYPE *ReturnType) +{ + char *Start; + UINT32 Depth; + ACPI_OBJECT_TYPE Type = ACPI_TYPE_INTEGER; + + + /* At end of buffer? */ + + if (!String || !(*String)) + { + return (NULL); + } + + /* Remove any spaces at the beginning */ + + if (*String == ' ') + { + while (*String && (*String == ' ')) + { + String++; + } + + if (!(*String)) + { + return (NULL); + } + } + + switch (*String) + { + case '"': + + /* This is a quoted string, scan until closing quote */ + + String++; + Start = String; + Type = ACPI_TYPE_STRING; + + /* Find end of string */ + + while (*String && (*String != '"')) + { + String++; + } + break; + + case '(': + + /* This is the start of a buffer, scan until closing paren */ + + String++; + Start = String; + Type = ACPI_TYPE_BUFFER; + + /* Find end of buffer */ + + while (*String && (*String != ')')) + { + String++; + } + break; + + case '[': + + /* This is the start of a package, scan until closing bracket */ + + String++; + Depth = 1; + Start = String; + Type = ACPI_TYPE_PACKAGE; + + /* Find end of package (closing bracket) */ + + while (*String) + { + /* Handle String package elements */ + + if (*String == '"') + { + /* Find end of string */ + + String++; + while (*String && (*String != '"')) + { + String++; + } + if (!(*String)) + { + break; + } + } + else if (*String == '[') + { + Depth++; /* A nested package declaration */ + } + else if (*String == ']') + { + Depth--; + if (Depth == 0) /* Found final package closing bracket */ + { + break; + } + } + + String++; + } + break; + + default: + + Start = String; + + /* Find end of token */ + + while (*String && (*String != ' ')) + { + String++; + } + break; + } + + if (!(*String)) + { + *Next = NULL; + } + else + { + *String = 0; + *Next = String + 1; + } + + *ReturnType = Type; + return (Start); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetLine + * + * PARAMETERS: InputBuffer - Command line buffer + * + * RETURN: Count of arguments to the command + * + * DESCRIPTION: Get the next command line from the user. Gets entire line + * up to the next newline + * + ******************************************************************************/ + +static UINT32 +AcpiDbGetLine ( + char *InputBuffer) +{ + UINT32 i; + UINT32 Count; + char *Next; + char *This; + + + ACPI_STRCPY (AcpiGbl_DbParsedBuf, InputBuffer); + + This = AcpiGbl_DbParsedBuf; + for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++) + { + AcpiGbl_DbArgs[i] = AcpiDbGetNextToken (This, &Next, + &AcpiGbl_DbArgTypes[i]); + if (!AcpiGbl_DbArgs[i]) + { + break; + } + + This = Next; + } + + /* Uppercase the actual command */ + + if (AcpiGbl_DbArgs[0]) + { + AcpiUtStrupr (AcpiGbl_DbArgs[0]); + } + + Count = i; + if (Count) + { + Count--; /* Number of args only */ + } + + return (Count); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbMatchCommand + * + * PARAMETERS: UserCommand - User command line + * + * RETURN: Index into command array, -1 if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +static UINT32 +AcpiDbMatchCommand ( + char *UserCommand) +{ + UINT32 i; + + + if (!UserCommand || UserCommand[0] == 0) + { + return (CMD_NULL); + } + + for (i = CMD_FIRST_VALID; AcpiGbl_DbCommands[i].Name; i++) + { + if (ACPI_STRSTR (AcpiGbl_DbCommands[i].Name, UserCommand) == + AcpiGbl_DbCommands[i].Name) + { + return (i); + } + } + + /* Command not recognized */ + + return (CMD_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbCommandDispatch + * + * PARAMETERS: InputBuffer - Command line buffer + * WalkState - Current walk + * Op - Current (executing) parse op + * + * RETURN: Status + * + * DESCRIPTION: Command dispatcher. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbCommandDispatch ( + char *InputBuffer, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + UINT32 Temp; + UINT32 CommandIndex; + UINT32 ParamCount; + char *CommandLine; + ACPI_STATUS Status = AE_CTRL_TRUE; + + + /* If AcpiTerminate has been called, terminate this thread */ + + if (AcpiGbl_DbTerminateThreads) + { + return (AE_CTRL_TERMINATE); + } + + ParamCount = AcpiDbGetLine (InputBuffer); + CommandIndex = AcpiDbMatchCommand (AcpiGbl_DbArgs[0]); + Temp = 0; + + /* Verify that we have the minimum number of params */ + + if (ParamCount < AcpiGbl_DbCommands[CommandIndex].MinArgs) + { + AcpiOsPrintf ("%u parameters entered, [%s] requires %u parameters\n", + ParamCount, AcpiGbl_DbCommands[CommandIndex].Name, + AcpiGbl_DbCommands[CommandIndex].MinArgs); + + return (AE_CTRL_TRUE); + } + + /* Decode and dispatch the command */ + + switch (CommandIndex) + { + case CMD_NULL: + if (Op) + { + return (AE_OK); + } + break; + + case CMD_ALLOCATIONS: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiUtDumpAllocations ((UINT32) -1, NULL); +#endif + break; + + case CMD_ARGS: + case CMD_ARGUMENTS: + AcpiDbDisplayArguments (); + break; + + case CMD_BATCH: + AcpiDbBatchExecute (AcpiGbl_DbArgs[1]); + break; + + case CMD_BREAKPOINT: + AcpiDbSetMethodBreakpoint (AcpiGbl_DbArgs[1], WalkState, Op); + break; + + case CMD_BUSINFO: + AcpiDbGetBusInfo (); + break; + + case CMD_CALL: + AcpiDbSetMethodCallBreakpoint (Op); + Status = AE_OK; + break; + + case CMD_CLOSE: + AcpiDbCloseDebugFile (); + break; + + case CMD_DEBUG: + AcpiDbExecute (AcpiGbl_DbArgs[1], + &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_SINGLE_STEP); + break; + + case CMD_DISASSEMBLE: + (void) AcpiDbDisassembleMethod (AcpiGbl_DbArgs[1]); + break; + + case CMD_DUMP: + AcpiDbDecodeAndDisplayObject (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_ENABLEACPI: +#if (!ACPI_REDUCED_HARDWARE) + + Status = AcpiEnable(); + if (ACPI_FAILURE(Status)) + { + AcpiOsPrintf("AcpiEnable failed (Status=%X)\n", Status); + return (Status); + } +#endif /* !ACPI_REDUCED_HARDWARE */ + break; + + case CMD_EVENT: + AcpiOsPrintf ("Event command not implemented\n"); + break; + + case CMD_EXECUTE: + AcpiDbExecute (AcpiGbl_DbArgs[1], + &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_NO_SINGLE_STEP); + break; + + case CMD_FIND: + Status = AcpiDbFindNameInNamespace (AcpiGbl_DbArgs[1]); + break; + + case CMD_GO: + AcpiGbl_CmSingleStep = FALSE; + return (AE_OK); + + case CMD_GPE: + AcpiDbGenerateGpe (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_GPES: + AcpiDbDisplayGpes (); + break; + + case CMD_HANDLERS: + AcpiDbDisplayHandlers (); + break; + + case CMD_HELP: + case CMD_HELP2: + AcpiDbDisplayHelp (); + break; + + case CMD_HISTORY: + AcpiDbDisplayHistory (); + break; + + case CMD_HISTORY_EXE: + CommandLine = AcpiDbGetFromHistory (AcpiGbl_DbArgs[1]); + if (!CommandLine) + { + return (AE_CTRL_TRUE); + } + + Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op); + return (Status); + + case CMD_HISTORY_LAST: + CommandLine = AcpiDbGetFromHistory (NULL); + if (!CommandLine) + { + return (AE_CTRL_TRUE); + } + + Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op); + return (Status); + + case CMD_INFORMATION: + AcpiDbDisplayMethodInfo (Op); + break; + + case CMD_INTEGRITY: + AcpiDbCheckIntegrity (); + break; + + case CMD_INTO: + if (Op) + { + AcpiGbl_CmSingleStep = TRUE; + return (AE_OK); + } + break; + + case CMD_LEVEL: + if (ParamCount == 0) + { + AcpiOsPrintf ("Current debug level for file output is: %8.8lX\n", + AcpiGbl_DbDebugLevel); + AcpiOsPrintf ("Current debug level for console output is: %8.8lX\n", + AcpiGbl_DbConsoleDebugLevel); + } + else if (ParamCount == 2) + { + Temp = AcpiGbl_DbConsoleDebugLevel; + AcpiGbl_DbConsoleDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1], + NULL, 16); + AcpiOsPrintf ( + "Debug Level for console output was %8.8lX, now %8.8lX\n", + Temp, AcpiGbl_DbConsoleDebugLevel); + } + else + { + Temp = AcpiGbl_DbDebugLevel; + AcpiGbl_DbDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1], NULL, 16); + AcpiOsPrintf ( + "Debug Level for file output was %8.8lX, now %8.8lX\n", + Temp, AcpiGbl_DbDebugLevel); + } + break; + + case CMD_LIST: + AcpiDbDisassembleAml (AcpiGbl_DbArgs[1], Op); + break; + + case CMD_LOAD: + Status = AcpiDbGetTableFromFile (AcpiGbl_DbArgs[1], NULL); + break; + + case CMD_LOCKS: + AcpiDbDisplayLocks (); + break; + + case CMD_LOCALS: + AcpiDbDisplayLocals (); + break; + + case CMD_METHODS: + Status = AcpiDbDisplayObjects ("METHOD", AcpiGbl_DbArgs[1]); + break; + + case CMD_NAMESPACE: + AcpiDbDumpNamespace (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_NOTIFY: + Temp = ACPI_STRTOUL (AcpiGbl_DbArgs[2], NULL, 0); + AcpiDbSendNotify (AcpiGbl_DbArgs[1], Temp); + break; + + case CMD_OBJECT: + AcpiUtStrupr (AcpiGbl_DbArgs[1]); + Status = AcpiDbDisplayObjects (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_OPEN: + AcpiDbOpenDebugFile (AcpiGbl_DbArgs[1]); + break; + + case CMD_OSI: + AcpiDbDisplayInterfaces (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_OWNER: + AcpiDbDumpNamespaceByOwner (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_PREDEFINED: + AcpiDbCheckPredefinedNames (); + break; + + case CMD_PREFIX: + AcpiDbSetScope (AcpiGbl_DbArgs[1]); + break; + + case CMD_REFERENCES: + AcpiDbFindReferences (AcpiGbl_DbArgs[1]); + break; + + case CMD_RESOURCES: + AcpiDbDisplayResources (AcpiGbl_DbArgs[1]); + break; + + case CMD_RESULTS: + AcpiDbDisplayResults (); + break; + + case CMD_SET: + AcpiDbSetMethodData (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2], + AcpiGbl_DbArgs[3]); + break; + + case CMD_SLEEP: + Status = AcpiDbSleep (AcpiGbl_DbArgs[1]); + break; + + case CMD_STATS: + Status = AcpiDbDisplayStatistics (AcpiGbl_DbArgs[1]); + break; + + case CMD_STOP: + return (AE_NOT_IMPLEMENTED); + + case CMD_TABLES: + AcpiDbDisplayTableInfo (AcpiGbl_DbArgs[1]); + break; + + case CMD_TEMPLATE: + AcpiDbDisplayTemplate (AcpiGbl_DbArgs[1]); + break; + + case CMD_TERMINATE: + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + AcpiUtSubsystemShutdown (); + + /* + * TBD: [Restructure] Need some way to re-initialize without + * re-creating the semaphores! + */ + + /* AcpiInitialize (NULL); */ + break; + + case CMD_THREADS: + AcpiDbCreateExecutionThreads (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2], + AcpiGbl_DbArgs[3]); + break; + + case CMD_TRACE: + (void) AcpiDebugTrace (AcpiGbl_DbArgs[1],0,0,1); + break; + + case CMD_TREE: + AcpiDbDisplayCallingTree (); + break; + + case CMD_TYPE: + AcpiDbDisplayObjectType (AcpiGbl_DbArgs[1]); + break; + + case CMD_UNLOAD: + AcpiDbUnloadAcpiTable (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]); + break; + + case CMD_EXIT: + case CMD_QUIT: + if (Op) + { + AcpiOsPrintf ("Method execution terminated\n"); + return (AE_CTRL_TERMINATE); + } + + if (!AcpiGbl_DbOutputToFile) + { + AcpiDbgLevel = ACPI_DEBUG_DEFAULT; + } + + AcpiDbCloseDebugFile (); + AcpiGbl_DbTerminateThreads = TRUE; + return (AE_CTRL_TERMINATE); + + case CMD_NOT_FOUND: + default: + AcpiOsPrintf ("Unknown Command\n"); + return (AE_CTRL_TRUE); + } + + if (ACPI_SUCCESS (Status)) + { + Status = AE_CTRL_TRUE; + } + + /* Add all commands that come here to the history buffer */ + + AcpiDbAddToHistory (InputBuffer); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbExecuteThread + * + * PARAMETERS: Context - Not used + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +void ACPI_SYSTEM_XFACE +AcpiDbExecuteThread ( + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_STATUS MStatus; + + + while (Status != AE_CTRL_TERMINATE) + { + AcpiGbl_MethodExecuting = FALSE; + AcpiGbl_StepToNextCall = FALSE; + + MStatus = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (MStatus)) + { + return; + } + + Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, NULL, NULL); + + MStatus = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (MStatus)) + { + return; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSingleThread + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +static void +AcpiDbSingleThread ( + void) +{ + + AcpiGbl_MethodExecuting = FALSE; + AcpiGbl_StepToNextCall = FALSE; + + (void) AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, NULL, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbUserCommands + * + * PARAMETERS: Prompt - User prompt (depends on mode) + * Op - Current executing parse op + * + * RETURN: None + * + * DESCRIPTION: Command line execution for the AML debugger. Commands are + * matched and dispatched here. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbUserCommands ( + char Prompt, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status = AE_OK; + + + /* TBD: [Restructure] Need a separate command line buffer for step mode */ + + while (!AcpiGbl_DbTerminateThreads) + { + /* Force output to console until a command is entered */ + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!AcpiGbl_MethodExecuting) + { + AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); + } + else + { + AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + Status = AcpiOsGetLine (AcpiGbl_DbLineBuf, + ACPI_DB_LINE_BUFFER_SIZE, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line")); + return (Status); + } + + /* Check for single or multithreaded debug */ + + if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED) + { + /* + * Signal the debug thread that we have a command to execute, + * and wait for the command to complete. + */ + Status = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else + { + /* Just call to the command line interpreter */ + + AcpiDbSingleThread (); + } + } + + /* + * Only this thread (the original thread) should actually terminate the + * subsystem, because all the semaphores are deleted during termination + */ + Status = AcpiTerminate (); + return (Status); +} + +#endif /* ACPI_DEBUGGER */ + diff --git a/source/components/debugger/dbmethod.c b/source/components/debugger/dbmethod.c new file mode 100644 index 000000000000..0d45d68150b4 --- /dev/null +++ b/source/components/debugger/dbmethod.c @@ -0,0 +1,525 @@ +/******************************************************************************* + * + * Module Name: dbmethod - Debug commands for control methods + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "acdisasm.h" +#include "acparser.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbmethod") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDbWalkForExecute ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSetMethodBreakpoint + * + * PARAMETERS: Location - AML offset of breakpoint + * WalkState - Current walk info + * Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ + +void +AcpiDbSetMethodBreakpoint ( + char *Location, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + UINT32 Address; + + + if (!Op) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + /* Get and verify the breakpoint address */ + + Address = ACPI_STRTOUL (Location, NULL, 16); + if (Address <= Op->Common.AmlOffset) + { + AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", + Address, Op->Common.AmlOffset); + } + + /* Save breakpoint in current walk */ + + WalkState->UserBreakpoint = Address; + AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSetMethodCallBreakpoint + * + * PARAMETERS: Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ + +void +AcpiDbSetMethodCallBreakpoint ( + ACPI_PARSE_OBJECT *Op) +{ + + + if (!Op) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + AcpiGbl_StepToNextCall = TRUE; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSetMethodData + * + * PARAMETERS: TypeArg - L for local, A for argument + * IndexArg - which one + * ValueArg - Value to set. + * + * RETURN: None + * + * DESCRIPTION: Set a local or argument for the running control method. + * NOTE: only object supported is Number. + * + ******************************************************************************/ + +void +AcpiDbSetMethodData ( + char *TypeArg, + char *IndexArg, + char *ValueArg) +{ + char Type; + UINT32 Index; + UINT32 Value; + ACPI_WALK_STATE *WalkState; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + /* Validate TypeArg */ + + AcpiUtStrupr (TypeArg); + Type = TypeArg[0]; + if ((Type != 'L') && + (Type != 'A') && + (Type != 'N')) + { + AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); + return; + } + + Value = ACPI_STRTOUL (ValueArg, NULL, 16); + + if (Type == 'N') + { + Node = AcpiDbConvertToNode (IndexArg); + if (Node->Type != ACPI_TYPE_INTEGER) + { + AcpiOsPrintf ("Can only set Integer nodes\n"); + return; + } + ObjDesc = Node->Object; + ObjDesc->Integer.Value = Value; + return; + } + + /* Get the index and value */ + + Index = ACPI_STRTOUL (IndexArg, NULL, 16); + + WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); + if (!WalkState) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + /* Create and initialize the new object */ + + ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); + if (!ObjDesc) + { + AcpiOsPrintf ("Could not create an internal object\n"); + return; + } + + /* Store the new object into the target */ + + switch (Type) + { + case 'A': + + /* Set a method argument */ + + if (Index > ACPI_METHOD_MAX_ARG) + { + AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index); + goto Cleanup; + } + + Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc, + WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + ObjDesc = WalkState->Arguments[Index].Object; + + AcpiOsPrintf ("Arg%u: ", Index); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + break; + + case 'L': + + /* Set a method local */ + + if (Index > ACPI_METHOD_MAX_LOCAL) + { + AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index); + goto Cleanup; + } + + Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc, + WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + ObjDesc = WalkState->LocalVariables[Index].Object; + + AcpiOsPrintf ("Local%u: ", Index); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + break; + + default: + break; + } + +Cleanup: + AcpiUtRemoveReference (ObjDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisassembleAml + * + * PARAMETERS: Statements - Number of statements to disassemble + * Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number + * of statements specified. + * + ******************************************************************************/ + +void +AcpiDbDisassembleAml ( + char *Statements, + ACPI_PARSE_OBJECT *Op) +{ + UINT32 NumStatements = 8; + + + if (!Op) + { + AcpiOsPrintf ("There is no method currently executing\n"); + return; + } + + if (Statements) + { + NumStatements = ACPI_STRTOUL (Statements, NULL, 0); + } + + AcpiDmDisassemble (NULL, Op, NumStatements); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisassembleMethod + * + * PARAMETERS: Name - Name of control method + * + * RETURN: None + * + * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number + * of statements specified. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbDisassembleMethod ( + char *Name) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Op; + ACPI_WALK_STATE *WalkState; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Method; + + + Method = AcpiDbConvertToNode (Name); + if (!Method) + { + return (AE_BAD_PARAMETER); + } + + ObjDesc = Method->Object; + + Op = AcpiPsCreateScopeOp (); + if (!Op) + { + return (AE_NO_MEMORY); + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); + if (!WalkState) + { + return (AE_NO_MEMORY); + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, + ObjDesc->Method.AmlStart, + ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Parse the AML */ + + WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; + WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; + Status = AcpiPsParseAml (WalkState); + + AcpiDmDisassemble (NULL, Op, 0); + AcpiPsDeleteParseTree (Op); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbWalkForExecute + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Batch execution module. Currently only executes predefined + * ACPI names. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbWalkForExecute ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_EXECUTE_WALK *Info = (ACPI_EXECUTE_WALK *) Context; + ACPI_BUFFER ReturnObj; + ACPI_STATUS Status; + char *Pathname; + UINT32 i; + ACPI_DEVICE_INFO *ObjInfo; + ACPI_OBJECT_LIST ParamObjects; + ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; + const ACPI_PREDEFINED_INFO *Predefined; + + + Predefined = AcpiNsCheckForPredefinedName (Node); + if (!Predefined) + { + return (AE_OK); + } + + if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) + { + return (AE_OK); + } + + Pathname = AcpiNsGetExternalPathname (Node); + if (!Pathname) + { + return (AE_OK); + } + + /* Get the object info for number of method parameters */ + + Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParamObjects.Pointer = NULL; + ParamObjects.Count = 0; + + if (ObjInfo->Type == ACPI_TYPE_METHOD) + { + /* Setup default parameters */ + + for (i = 0; i < ObjInfo->ParamCount; i++) + { + Params[i].Type = ACPI_TYPE_INTEGER; + Params[i].Integer.Value = 1; + } + + ParamObjects.Pointer = Params; + ParamObjects.Count = ObjInfo->ParamCount; + } + + ACPI_FREE (ObjInfo); + ReturnObj.Pointer = NULL; + ReturnObj.Length = ACPI_ALLOCATE_BUFFER; + + /* Do the actual method execution */ + + AcpiGbl_MethodExecuting = TRUE; + + Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); + + AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); + AcpiGbl_MethodExecuting = FALSE; + ACPI_FREE (Pathname); + + /* Ignore status from method execution */ + + Status = AE_OK; + + /* Update count, check if we have executed enough methods */ + + Info->Count++; + if (Info->Count >= Info->MaxCount) + { + Status = AE_CTRL_TERMINATE; + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbBatchExecute + * + * PARAMETERS: CountArg - Max number of methods to execute + * + * RETURN: None + * + * DESCRIPTION: Namespace batch execution. Execute predefined names in the + * namespace, up to the max count, if specified. + * + ******************************************************************************/ + +void +AcpiDbBatchExecute ( + char *CountArg) +{ + ACPI_EXECUTE_WALK Info; + + + Info.Count = 0; + Info.MaxCount = ACPI_UINT32_MAX; + + if (CountArg) + { + Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); + } + + + /* Search all nodes in namespace */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbWalkForExecute, NULL, (void *) &Info, NULL); + + AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count); +} + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/debugger/dbnames.c b/source/components/debugger/dbnames.c new file mode 100644 index 000000000000..be326c5390a7 --- /dev/null +++ b/source/components/debugger/dbnames.c @@ -0,0 +1,934 @@ +/******************************************************************************* + * + * Module Name: dbnames - Debugger commands for the acpi namespace + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdebug.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbnames") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDbWalkAndMatchName ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbWalkForPredefinedNames ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbWalkForSpecificObjects ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbIntegrityWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbWalkForReferences ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiDbBusWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +/* + * Arguments for the Objects command + * These object types map directly to the ACPI_TYPES + */ +static ARGUMENT_INFO AcpiDbObjectTypes [] = +{ + {"ANY"}, + {"INTEGERS"}, + {"STRINGS"}, + {"BUFFERS"}, + {"PACKAGES"}, + {"FIELDS"}, + {"DEVICES"}, + {"EVENTS"}, + {"METHODS"}, + {"MUTEXES"}, + {"REGIONS"}, + {"POWERRESOURCES"}, + {"PROCESSORS"}, + {"THERMALZONES"}, + {"BUFFERFIELDS"}, + {"DDBHANDLES"}, + {"DEBUG"}, + {"REGIONFIELDS"}, + {"BANKFIELDS"}, + {"INDEXFIELDS"}, + {"REFERENCES"}, + {"ALIAS"}, + {NULL} /* Must be null terminated */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSetScope + * + * PARAMETERS: Name - New scope path + * + * RETURN: Status + * + * DESCRIPTION: Set the "current scope" as maintained by this utility. + * The scope is used as a prefix to ACPI paths. + * + ******************************************************************************/ + +void +AcpiDbSetScope ( + char *Name) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + if (!Name || Name[0] == 0) + { + AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf); + return; + } + + AcpiDbPrepNamestring (Name); + + if (Name[0] == '\\') + { + /* Validate new scope from the root */ + + Status = AcpiNsGetNode (AcpiGbl_RootNode, Name, ACPI_NS_NO_UPSEARCH, + &Node); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + ACPI_STRCPY (AcpiGbl_DbScopeBuf, Name); + ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\"); + } + else + { + /* Validate new scope relative to old scope */ + + Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name, ACPI_NS_NO_UPSEARCH, + &Node); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + ACPI_STRCAT (AcpiGbl_DbScopeBuf, Name); + ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\"); + } + + AcpiGbl_DbScopeNode = Node; + AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf); + return; + +ErrorExit: + + AcpiOsPrintf ("Could not attach scope: %s, %s\n", + Name, AcpiFormatException (Status)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDumpNamespace + * + * PARAMETERS: StartArg - Node to begin namespace dump + * DepthArg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed + * with type and other information. + * + ******************************************************************************/ + +void +AcpiDbDumpNamespace ( + char *StartArg, + char *DepthArg) +{ + ACPI_HANDLE SubtreeEntry = AcpiGbl_RootNode; + UINT32 MaxDepth = ACPI_UINT32_MAX; + + + /* No argument given, just start at the root and dump entire namespace */ + + if (StartArg) + { + SubtreeEntry = AcpiDbConvertToNode (StartArg); + if (!SubtreeEntry) + { + return; + } + + /* Now we can check for the depth argument */ + + if (DepthArg) + { + MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); + } + } + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + AcpiOsPrintf ("ACPI Namespace (from %4.4s (%p) subtree):\n", + ((ACPI_NAMESPACE_NODE *) SubtreeEntry)->Name.Ascii, SubtreeEntry); + + /* Display the subtree */ + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth, + ACPI_OWNER_ID_MAX, SubtreeEntry); + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDumpNamespaceByOwner + * + * PARAMETERS: OwnerArg - Owner ID whose nodes will be displayed + * DepthArg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump elements of the namespace that are owned by the OwnerId. + * + ******************************************************************************/ + +void +AcpiDbDumpNamespaceByOwner ( + char *OwnerArg, + char *DepthArg) +{ + ACPI_HANDLE SubtreeEntry = AcpiGbl_RootNode; + UINT32 MaxDepth = ACPI_UINT32_MAX; + ACPI_OWNER_ID OwnerId; + + + OwnerId = (ACPI_OWNER_ID) ACPI_STRTOUL (OwnerArg, NULL, 0); + + /* Now we can check for the depth argument */ + + if (DepthArg) + { + MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); + } + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + AcpiOsPrintf ("ACPI Namespace by owner %X:\n", OwnerId); + + /* Display the subtree */ + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth, OwnerId, + SubtreeEntry); + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbWalkAndMatchName + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Find a particular name/names within the namespace. Wildcards + * are supported -- '?' matches any character. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbWalkAndMatchName ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + char *RequestedName = (char *) Context; + UINT32 i; + ACPI_BUFFER Buffer; + ACPI_WALK_INFO Info; + + + /* Check for a name match */ + + for (i = 0; i < 4; i++) + { + /* Wildcard support */ + + if ((RequestedName[i] != '?') && + (RequestedName[i] != ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii[i])) + { + /* No match, just exit */ + + return (AE_OK); + } + } + + /* Get the full pathname to this object */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); + } + else + { + Info.OwnerId = ACPI_OWNER_ID_MAX; + Info.DebugLevel = ACPI_UINT32_MAX; + Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; + + AcpiOsPrintf ("%32s", (char *) Buffer.Pointer); + (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, &Info, NULL); + ACPI_FREE (Buffer.Pointer); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbFindNameInNamespace + * + * PARAMETERS: NameArg - The 4-character ACPI name to find. + * wildcards are supported. + * + * RETURN: None + * + * DESCRIPTION: Search the namespace for a given name (with wildcards) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbFindNameInNamespace ( + char *NameArg) +{ + char AcpiName[5] = "____"; + char *AcpiNamePtr = AcpiName; + + + if (ACPI_STRLEN (NameArg) > 4) + { + AcpiOsPrintf ("Name must be no longer than 4 characters\n"); + return (AE_OK); + } + + /* Pad out name with underscores as necessary to create a 4-char name */ + + AcpiUtStrupr (NameArg); + while (*NameArg) + { + *AcpiNamePtr = *NameArg; + AcpiNamePtr++; + NameArg++; + } + + /* Walk the namespace from the root */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbWalkAndMatchName, NULL, AcpiName, NULL); + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbWalkForPredefinedNames + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Detect and display predefined ACPI names (names that start with + * an underscore) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbWalkForPredefinedNames ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + UINT32 *Count = (UINT32 *) Context; + const ACPI_PREDEFINED_INFO *Predefined; + const ACPI_PREDEFINED_INFO *Package = NULL; + char *Pathname; + + + Predefined = AcpiNsCheckForPredefinedName (Node); + if (!Predefined) + { + return (AE_OK); + } + + Pathname = AcpiNsGetExternalPathname (Node); + if (!Pathname) + { + return (AE_OK); + } + + /* If method returns a package, the info is in the next table entry */ + + if (Predefined->Info.ExpectedBtypes & ACPI_BTYPE_PACKAGE) + { + Package = Predefined + 1; + } + + AcpiOsPrintf ("%-32s arg %X ret %2.2X", Pathname, + Predefined->Info.ParamCount, Predefined->Info.ExpectedBtypes); + + if (Package) + { + AcpiOsPrintf (" PkgType %2.2X ObjType %2.2X Count %2.2X", + Package->RetInfo.Type, Package->RetInfo.ObjectType1, + Package->RetInfo.Count1); + } + + AcpiOsPrintf("\n"); + + AcpiNsCheckParameterCount (Pathname, Node, ACPI_UINT32_MAX, Predefined); + ACPI_FREE (Pathname); + (*Count)++; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbCheckPredefinedNames + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Validate all predefined names in the namespace + * + ******************************************************************************/ + +void +AcpiDbCheckPredefinedNames ( + void) +{ + UINT32 Count = 0; + + + /* Search all nodes in namespace */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbWalkForPredefinedNames, NULL, (void *) &Count, NULL); + + AcpiOsPrintf ("Found %u predefined names in the namespace\n", Count); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbWalkForSpecificObjects + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Display short info about objects in the namespace + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbWalkForSpecificObjects ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_WALK_INFO *Info = (ACPI_WALK_INFO *) Context; + ACPI_BUFFER Buffer; + ACPI_STATUS Status; + + + Info->Count++; + + /* Get and display the full pathname to this object */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); + return (AE_OK); + } + + AcpiOsPrintf ("%32s", (char *) Buffer.Pointer); + ACPI_FREE (Buffer.Pointer); + + /* Dump short info about the object */ + + (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, Info, NULL); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayObjects + * + * PARAMETERS: ObjTypeArg - Type of object to display + * DisplayCountArg - Max depth to display + * + * RETURN: None + * + * DESCRIPTION: Display objects in the namespace of the requested type + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbDisplayObjects ( + char *ObjTypeArg, + char *DisplayCountArg) +{ + ACPI_WALK_INFO Info; + ACPI_OBJECT_TYPE Type; + + + /* Get the object type */ + + Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes); + if (Type == ACPI_TYPE_NOT_FOUND) + { + AcpiOsPrintf ("Invalid or unsupported argument\n"); + return (AE_OK); + } + + AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); + AcpiOsPrintf ( + "Objects of type [%s] defined in the current ACPI Namespace:\n", + AcpiUtGetTypeName (Type)); + + AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); + + Info.Count = 0; + Info.OwnerId = ACPI_OWNER_ID_MAX; + Info.DebugLevel = ACPI_UINT32_MAX; + Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; + + /* Walk the namespace from the root */ + + (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL); + + AcpiOsPrintf ( + "\nFound %u objects of type [%s] in the current ACPI Namespace\n", + Info.Count, AcpiUtGetTypeName (Type)); + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbIntegrityWalk + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Examine one NS node for valid values. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbIntegrityWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_INTEGRITY_INFO *Info = (ACPI_INTEGRITY_INFO *) Context; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_OPERAND_OBJECT *Object; + BOOLEAN Alias = TRUE; + + + Info->Nodes++; + + /* Verify the NS node, and dereference aliases */ + + while (Alias) + { + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + AcpiOsPrintf ("Invalid Descriptor Type for Node %p [%s] - is %2.2X should be %2.2X\n", + Node, AcpiUtGetDescriptorName (Node), ACPI_GET_DESCRIPTOR_TYPE (Node), + ACPI_DESC_TYPE_NAMED); + return (AE_OK); + } + + if ((Node->Type == ACPI_TYPE_LOCAL_ALIAS) || + (Node->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) + { + Node = (ACPI_NAMESPACE_NODE *) Node->Object; + } + else + { + Alias = FALSE; + } + } + + if (Node->Type > ACPI_TYPE_LOCAL_MAX) + { + AcpiOsPrintf ("Invalid Object Type for Node %p, Type = %X\n", + Node, Node->Type); + return (AE_OK); + } + + if (!AcpiUtValidAcpiName (Node->Name.Integer)) + { + AcpiOsPrintf ("Invalid AcpiName for Node %p\n", Node); + return (AE_OK); + } + + Object = AcpiNsGetAttachedObject (Node); + if (Object) + { + Info->Objects++; + if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf ("Invalid Descriptor Type for Object %p [%s]\n", + Object, AcpiUtGetDescriptorName (Object)); + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbCheckIntegrity + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Check entire namespace for data structure integrity + * + ******************************************************************************/ + +void +AcpiDbCheckIntegrity ( + void) +{ + ACPI_INTEGRITY_INFO Info = {0,0}; + + /* Search all nodes in namespace */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbIntegrityWalk, NULL, (void *) &Info, NULL); + + AcpiOsPrintf ("Verified %u namespace nodes with %u Objects\n", + Info.Nodes, Info.Objects); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbWalkForReferences + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Check if this namespace object refers to the target object + * that is passed in as the context value. + * + * Note: Currently doesn't check subobjects within the Node's object + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbWalkForReferences ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_OPERAND_OBJECT *ObjDesc = (ACPI_OPERAND_OBJECT *) Context; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + + + /* Check for match against the namespace node itself */ + + if (Node == (void *) ObjDesc) + { + AcpiOsPrintf ("Object is a Node [%4.4s]\n", + AcpiUtGetNodeName (Node)); + } + + /* Check for match against the object attached to the node */ + + if (AcpiNsGetAttachedObject (Node) == ObjDesc) + { + AcpiOsPrintf ("Reference at Node->Object %p [%4.4s]\n", + Node, AcpiUtGetNodeName (Node)); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbFindReferences + * + * PARAMETERS: ObjectArg - String with hex value of the object + * + * RETURN: None + * + * DESCRIPTION: Search namespace for all references to the input object + * + ******************************************************************************/ + +void +AcpiDbFindReferences ( + char *ObjectArg) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + /* Convert string to object pointer */ + + ObjDesc = ACPI_TO_POINTER (ACPI_STRTOUL (ObjectArg, NULL, 16)); + + /* Search all nodes in namespace */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbWalkForReferences, NULL, (void *) ObjDesc, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbBusWalk + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Display info about device objects that have a corresponding + * _PRT method. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbBusWalk ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_STATUS Status; + ACPI_BUFFER Buffer; + ACPI_NAMESPACE_NODE *TempNode; + ACPI_DEVICE_INFO *Info; + UINT32 i; + + + if ((Node->Type != ACPI_TYPE_DEVICE) && + (Node->Type != ACPI_TYPE_PROCESSOR)) + { + return (AE_OK); + } + + /* Exit if there is no _PRT under this device */ + + Status = AcpiGetHandle (Node, METHOD_NAME__PRT, + ACPI_CAST_PTR (ACPI_HANDLE, &TempNode)); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + /* Get the full path to this device object */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); + return (AE_OK); + } + + Status = AcpiGetObjectInfo (ObjHandle, &Info); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + /* Display the full path */ + + AcpiOsPrintf ("%-32s Type %X", (char *) Buffer.Pointer, Node->Type); + ACPI_FREE (Buffer.Pointer); + + if (Info->Flags & ACPI_PCI_ROOT_BRIDGE) + { + AcpiOsPrintf (" - Is PCI Root Bridge"); + } + AcpiOsPrintf ("\n"); + + /* _PRT info */ + + AcpiOsPrintf ("_PRT: %p\n", TempNode); + + /* Dump _ADR, _HID, _UID, _CID */ + + if (Info->Valid & ACPI_VALID_ADR) + { + AcpiOsPrintf ("_ADR: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Info->Address)); + } + else + { + AcpiOsPrintf ("_ADR: \n"); + } + + if (Info->Valid & ACPI_VALID_HID) + { + AcpiOsPrintf ("_HID: %s\n", Info->HardwareId.String); + } + else + { + AcpiOsPrintf ("_HID: \n"); + } + + if (Info->Valid & ACPI_VALID_UID) + { + AcpiOsPrintf ("_UID: %s\n", Info->UniqueId.String); + } + else + { + AcpiOsPrintf ("_UID: \n"); + } + + if (Info->Valid & ACPI_VALID_CID) + { + for (i = 0; i < Info->CompatibleIdList.Count; i++) + { + AcpiOsPrintf ("_CID: %s\n", + Info->CompatibleIdList.Ids[i].String); + } + } + else + { + AcpiOsPrintf ("_CID: \n"); + } + + ACPI_FREE (Info); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbGetBusInfo + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display info about system busses. + * + ******************************************************************************/ + +void +AcpiDbGetBusInfo ( + void) +{ + /* Search all nodes in namespace */ + + (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + AcpiDbBusWalk, NULL, NULL, NULL); +} + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/debugger/dbstats.c b/source/components/debugger/dbstats.c new file mode 100644 index 000000000000..379493515a61 --- /dev/null +++ b/source/components/debugger/dbstats.c @@ -0,0 +1,549 @@ +/******************************************************************************* + * + * Module Name: dbstats - Generation and display of ACPI table statistics + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" +#include "acnamesp.h" + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbstats") + +/* Local prototypes */ + +static void +AcpiDbCountNamespaceObjects ( + void); + +static void +AcpiDbEnumerateObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +static ACPI_STATUS +AcpiDbClassifyOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE +static void +AcpiDbListInfo ( + ACPI_MEMORY_LIST *List); +#endif + + +/* + * Statistics subcommands + */ +static ARGUMENT_INFO AcpiDbStatTypes [] = +{ + {"ALLOCATIONS"}, + {"OBJECTS"}, + {"MEMORY"}, + {"MISC"}, + {"TABLES"}, + {"SIZES"}, + {"STACK"}, + {NULL} /* Must be null terminated */ +}; + +#define CMD_STAT_ALLOCATIONS 0 +#define CMD_STAT_OBJECTS 1 +#define CMD_STAT_MEMORY 2 +#define CMD_STAT_MISC 3 +#define CMD_STAT_TABLES 4 +#define CMD_STAT_SIZES 5 +#define CMD_STAT_STACK 6 + + +#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: AcpiDbListInfo + * + * PARAMETERS: List - Memory list/cache to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display information about the input memory list or cache. + * + ******************************************************************************/ + +static void +AcpiDbListInfo ( + ACPI_MEMORY_LIST *List) +{ +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + UINT32 Outstanding; +#endif + + AcpiOsPrintf ("\n%s\n", List->ListName); + + /* MaxDepth > 0 indicates a cache object */ + + if (List->MaxDepth > 0) + { + AcpiOsPrintf ( + " Cache: [Depth MaxD Avail Size] %8.2X %8.2X %8.2X %8.2X\n", + List->CurrentDepth, + List->MaxDepth, + List->MaxDepth - List->CurrentDepth, + (List->CurrentDepth * List->ObjectSize)); + } + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if (List->MaxDepth > 0) + { + AcpiOsPrintf ( + " Cache: [Requests Hits Misses ObjSize] %8.2X %8.2X %8.2X %8.2X\n", + List->Requests, + List->Hits, + List->Requests - List->Hits, + List->ObjectSize); + } + + Outstanding = AcpiDbGetCacheInfo (List); + + if (List->ObjectSize) + { + AcpiOsPrintf ( + " Mem: [Alloc Free Max CurSize Outstanding] %8.2X %8.2X %8.2X %8.2X %8.2X\n", + List->TotalAllocated, + List->TotalFreed, + List->MaxOccupied, + Outstanding * List->ObjectSize, + Outstanding); + } + else + { + AcpiOsPrintf ( + " Mem: [Alloc Free Max CurSize Outstanding Total] %8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n", + List->TotalAllocated, + List->TotalFreed, + List->MaxOccupied, + List->CurrentTotalSize, + Outstanding, + List->TotalSize); + } +#endif +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDbEnumerateObject + * + * PARAMETERS: ObjDesc - Object to be counted + * + * RETURN: None + * + * DESCRIPTION: Add this object to the global counts, by object type. + * Limited recursion handles subobjects and packages, and this + * is probably acceptable within the AML debugger only. + * + ******************************************************************************/ + +static void +AcpiDbEnumerateObject ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + UINT32 i; + + + if (!ObjDesc) + { + return; + } + + /* Enumerate this object first */ + + AcpiGbl_NumObjects++; + + if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) + { + AcpiGbl_ObjTypeCountMisc++; + } + else + { + AcpiGbl_ObjTypeCount [ObjDesc->Common.Type]++; + } + + /* Count the sub-objects */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_PACKAGE: + + for (i = 0; i < ObjDesc->Package.Count; i++) + { + AcpiDbEnumerateObject (ObjDesc->Package.Elements[i]); + } + break; + + case ACPI_TYPE_DEVICE: + + AcpiDbEnumerateObject (ObjDesc->Device.SystemNotify); + AcpiDbEnumerateObject (ObjDesc->Device.DeviceNotify); + AcpiDbEnumerateObject (ObjDesc->Device.Handler); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + if (AcpiNsGetSecondaryObject (ObjDesc)) + { + AcpiGbl_ObjTypeCount [ACPI_TYPE_BUFFER_FIELD]++; + } + break; + + case ACPI_TYPE_REGION: + + AcpiGbl_ObjTypeCount [ACPI_TYPE_LOCAL_REGION_FIELD ]++; + AcpiDbEnumerateObject (ObjDesc->Region.Handler); + break; + + case ACPI_TYPE_POWER: + + AcpiDbEnumerateObject (ObjDesc->PowerResource.SystemNotify); + AcpiDbEnumerateObject (ObjDesc->PowerResource.DeviceNotify); + break; + + case ACPI_TYPE_PROCESSOR: + + AcpiDbEnumerateObject (ObjDesc->Processor.SystemNotify); + AcpiDbEnumerateObject (ObjDesc->Processor.DeviceNotify); + AcpiDbEnumerateObject (ObjDesc->Processor.Handler); + break; + + case ACPI_TYPE_THERMAL: + + AcpiDbEnumerateObject (ObjDesc->ThermalZone.SystemNotify); + AcpiDbEnumerateObject (ObjDesc->ThermalZone.DeviceNotify); + AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler); + break; + + default: + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbClassifyOneObject + * + * PARAMETERS: Callback for WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and + * the parent namespace node. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbClassifyOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 Type; + + + AcpiGbl_NumNodes++; + + Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ObjDesc = AcpiNsGetAttachedObject (Node); + + AcpiDbEnumerateObject (ObjDesc); + + Type = Node->Type; + if (Type > ACPI_TYPE_NS_NODE_MAX) + { + AcpiGbl_NodeTypeCountMisc++; + } + else + { + AcpiGbl_NodeTypeCount [Type]++; + } + + return AE_OK; + + +#ifdef ACPI_FUTURE_IMPLEMENTATION + + /* TBD: These need to be counted during the initial parsing phase */ + + if (AcpiPsIsNamedOp (Op->Opcode)) + { + NumNodes++; + } + + if (IsMethod) + { + NumMethodElements++; + } + + NumGrammarElements++; + Op = AcpiPsGetDepthNext (Root, Op); + + SizeOfParseTree = (NumGrammarElements - NumMethodElements) * + (UINT32) sizeof (ACPI_PARSE_OBJECT); + SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT); + SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE); + SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT); +#endif +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbCountNamespaceObjects + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Count and classify the entire namespace, including all + * namespace nodes and attached objects. + * + ******************************************************************************/ + +static void +AcpiDbCountNamespaceObjects ( + void) +{ + UINT32 i; + + + AcpiGbl_NumNodes = 0; + AcpiGbl_NumObjects = 0; + + AcpiGbl_ObjTypeCountMisc = 0; + for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX -1); i++) + { + AcpiGbl_ObjTypeCount [i] = 0; + AcpiGbl_NodeTypeCount [i] = 0; + } + + (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, AcpiDbClassifyOneObject, NULL, NULL, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDisplayStatistics + * + * PARAMETERS: TypeArg - Subcommand + * + * RETURN: Status + * + * DESCRIPTION: Display various statistics + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbDisplayStatistics ( + char *TypeArg) +{ + UINT32 i; + UINT32 Temp; + + + if (!TypeArg) + { + AcpiOsPrintf ("The following subcommands are available:\n ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n"); + return (AE_OK); + } + + AcpiUtStrupr (TypeArg); + Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes); + if (Temp == (UINT32) -1) + { + AcpiOsPrintf ("Invalid or unsupported argument\n"); + return (AE_OK); + } + + + switch (Temp) + { + case CMD_STAT_ALLOCATIONS: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiUtDumpAllocationInfo (); +#endif + break; + + case CMD_STAT_TABLES: + + AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n"); + break; + + case CMD_STAT_OBJECTS: + + AcpiDbCountNamespaceObjects (); + + AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n"); + + AcpiOsPrintf ("%16.16s %10.10s %10.10s\n", + "ACPI_TYPE", "NODES", "OBJECTS"); + + for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) + { + AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i), + AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]); + } + AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", + AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc); + + AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:", + AcpiGbl_NumNodes, AcpiGbl_NumObjects); + break; + + case CMD_STAT_MEMORY: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n"); + + AcpiDbListInfo (AcpiGbl_GlobalList); + AcpiDbListInfo (AcpiGbl_NsNodeList); +#endif + +#ifdef ACPI_USE_LOCAL_CACHE + AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n"); + AcpiDbListInfo (AcpiGbl_OperandCache); + AcpiDbListInfo (AcpiGbl_PsNodeCache); + AcpiDbListInfo (AcpiGbl_PsNodeExtCache); + AcpiDbListInfo (AcpiGbl_StateCache); +#endif + + break; + + case CMD_STAT_MISC: + + AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n"); + AcpiOsPrintf ("Calls to AcpiPsFind:.. ........% 7ld\n", + AcpiGbl_PsFindCount); + AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n", + AcpiGbl_NsLookupCount); + + AcpiOsPrintf ("\n"); + + AcpiOsPrintf ("Mutex usage:\n\n"); + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + AcpiOsPrintf ("%-28s: % 7ld\n", + AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount); + } + break; + + + case CMD_STAT_SIZES: + + AcpiOsPrintf ("\nInternal object sizes:\n\n"); + + AcpiOsPrintf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); + AcpiOsPrintf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); + AcpiOsPrintf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); + AcpiOsPrintf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); + AcpiOsPrintf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); + AcpiOsPrintf ("BufferField %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); + AcpiOsPrintf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); + AcpiOsPrintf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); + AcpiOsPrintf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); + AcpiOsPrintf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); + AcpiOsPrintf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); + AcpiOsPrintf ("PowerResource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); + AcpiOsPrintf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); + AcpiOsPrintf ("ThermalZone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); + AcpiOsPrintf ("RegionField %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); + AcpiOsPrintf ("BankField %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); + AcpiOsPrintf ("IndexField %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); + AcpiOsPrintf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); + AcpiOsPrintf ("Notify %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); + AcpiOsPrintf ("AddressSpace %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); + AcpiOsPrintf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); + AcpiOsPrintf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); + + AcpiOsPrintf ("\n"); + + AcpiOsPrintf ("ParseObject %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); + AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); + AcpiOsPrintf ("ParseObjectAsl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); + AcpiOsPrintf ("OperandObject %3d\n", sizeof (ACPI_OPERAND_OBJECT)); + AcpiOsPrintf ("NamespaceNode %3d\n", sizeof (ACPI_NAMESPACE_NODE)); + AcpiOsPrintf ("AcpiObject %3d\n", sizeof (ACPI_OBJECT)); + + break; + + + case CMD_STAT_STACK: +#if defined(ACPI_DEBUG_OUTPUT) + + Temp = (UINT32) ACPI_PTR_DIFF (AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer); + + AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n"); + AcpiOsPrintf ("Entry Stack Pointer %p\n", AcpiGbl_EntryStackPointer); + AcpiOsPrintf ("Lowest Stack Pointer %p\n", AcpiGbl_LowestStackPointer); + AcpiOsPrintf ("Stack Use %X (%u)\n", Temp, Temp); + AcpiOsPrintf ("Deepest Procedure Nesting %u\n", AcpiGbl_DeepestNesting); +#endif + break; + + default: + break; + } + + AcpiOsPrintf ("\n"); + return (AE_OK); +} + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/debugger/dbutils.c b/source/components/debugger/dbutils.c new file mode 100644 index 000000000000..c44ff2efa906 --- /dev/null +++ b/source/components/debugger/dbutils.c @@ -0,0 +1,526 @@ +/******************************************************************************* + * + * Module Name: dbutils - AML debugger utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "acdisasm.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbutils") + +/* Local prototypes */ + +#ifdef ACPI_OBSOLETE_FUNCTIONS +ACPI_STATUS +AcpiDbSecondPassParse ( + ACPI_PARSE_OBJECT *Root); + +void +AcpiDbDumpBuffer ( + UINT32 Address); +#endif + +static char *Converter = "0123456789ABCDEF"; + + +/******************************************************************************* + * + * FUNCTION: AcpiDbMatchArgument + * + * PARAMETERS: UserArgument - User command line + * Arguments - Array of commands to match against + * + * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +ACPI_OBJECT_TYPE +AcpiDbMatchArgument ( + char *UserArgument, + ARGUMENT_INFO *Arguments) +{ + UINT32 i; + + + if (!UserArgument || UserArgument[0] == 0) + { + return (ACPI_TYPE_NOT_FOUND); + } + + for (i = 0; Arguments[i].Name; i++) + { + if (ACPI_STRSTR (Arguments[i].Name, UserArgument) == Arguments[i].Name) + { + return (i); + } + } + + /* Argument not recognized */ + + return (ACPI_TYPE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSetOutputDestination + * + * PARAMETERS: OutputFlags - Current flags word + * + * RETURN: None + * + * DESCRIPTION: Set the current destination for debugger output. Also sets + * the debug output level accordingly. + * + ******************************************************************************/ + +void +AcpiDbSetOutputDestination ( + UINT32 OutputFlags) +{ + + AcpiGbl_DbOutputFlags = (UINT8) OutputFlags; + + if ((OutputFlags & ACPI_DB_REDIRECTABLE_OUTPUT) && AcpiGbl_DbOutputToFile) + { + AcpiDbgLevel = AcpiGbl_DbDebugLevel; + } + else + { + AcpiDbgLevel = AcpiGbl_DbConsoleDebugLevel; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDumpExternalObject + * + * PARAMETERS: ObjDesc - External ACPI object to dump + * Level - Nesting level. + * + * RETURN: None + * + * DESCRIPTION: Dump the contents of an ACPI external object + * + ******************************************************************************/ + +void +AcpiDbDumpExternalObject ( + ACPI_OBJECT *ObjDesc, + UINT32 Level) +{ + UINT32 i; + + + if (!ObjDesc) + { + AcpiOsPrintf ("[Null Object]\n"); + return; + } + + for (i = 0; i < Level; i++) + { + AcpiOsPrintf (" "); + } + + switch (ObjDesc->Type) + { + case ACPI_TYPE_ANY: + + AcpiOsPrintf ("[Null Object] (Type=0)\n"); + break; + + + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("[String] Length %.2X = ", ObjDesc->String.Length); + for (i = 0; i < ObjDesc->String.Length; i++) + { + AcpiOsPrintf ("%c", ObjDesc->String.Pointer[i]); + } + AcpiOsPrintf ("\n"); + break; + + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length); + if (ObjDesc->Buffer.Length) + { + if (ObjDesc->Buffer.Length > 16) + { + AcpiOsPrintf ("\n"); + } + AcpiUtDumpBuffer (ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer), + ObjDesc->Buffer.Length, DB_BYTE_DISPLAY, _COMPONENT); + } + else + { + AcpiOsPrintf ("\n"); + } + break; + + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("[Package] Contains %u Elements:\n", + ObjDesc->Package.Count); + + for (i = 0; i < ObjDesc->Package.Count; i++) + { + AcpiDbDumpExternalObject (&ObjDesc->Package.Elements[i], Level+1); + } + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("[Object Reference] = "); + AcpiDmDisplayInternalObject (ObjDesc->Reference.Handle, NULL); + break; + + + case ACPI_TYPE_PROCESSOR: + + AcpiOsPrintf ("[Processor]\n"); + break; + + + case ACPI_TYPE_POWER: + + AcpiOsPrintf ("[Power Resource]\n"); + break; + + + default: + + AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Type); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbPrepNamestring + * + * PARAMETERS: Name - String to prepare + * + * RETURN: None + * + * DESCRIPTION: Translate all forward slashes and dots to backslashes. + * + ******************************************************************************/ + +void +AcpiDbPrepNamestring ( + char *Name) +{ + + if (!Name) + { + return; + } + + AcpiUtStrupr (Name); + + /* Convert a leading forward slash to a backslash */ + + if (*Name == '/') + { + *Name = '\\'; + } + + /* Ignore a leading backslash, this is the root prefix */ + + if (*Name == '\\') + { + Name++; + } + + /* Convert all slash path separators to dots */ + + while (*Name) + { + if ((*Name == '/') || + (*Name == '\\')) + { + *Name = '.'; + } + + Name++; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbLocalNsLookup + * + * PARAMETERS: Name - Name to lookup + * + * RETURN: Pointer to a namespace node, null on failure + * + * DESCRIPTION: Lookup a name in the ACPI namespace + * + * Note: Currently begins search from the root. Could be enhanced to use + * the current prefix (scope) node as the search beginning point. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiDbLocalNsLookup ( + char *Name) +{ + char *InternalPath; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node = NULL; + + + AcpiDbPrepNamestring (Name); + + /* Build an internal namestring */ + + Status = AcpiNsInternalizeName (Name, &InternalPath); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Invalid namestring: %s\n", Name); + return (NULL); + } + + /* + * Lookup the name. + * (Uses root node as the search starting point) + */ + Status = AcpiNsLookup (NULL, InternalPath, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not locate name: %s, %s\n", + Name, AcpiFormatException (Status)); + } + + ACPI_FREE (InternalPath); + return (Node); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbUInt32ToHexString + * + * PARAMETERS: Value - The value to be converted to string + * Buffer - Buffer for result (not less than 11 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image + * + * NOTE: It is the caller's responsibility to ensure that the length of buffer + * is sufficient. + * + ******************************************************************************/ + +void +AcpiDbUInt32ToHexString ( + UINT32 Value, + char *Buffer) +{ + int i; + + + if (Value == 0) + { + ACPI_STRCPY (Buffer, "0"); + return; + } + + Buffer[8] = '\0'; + + for (i = 7; i >= 0; i--) + { + Buffer[i] = Converter [Value & 0x0F]; + Value = Value >> 4; + } +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiDbSecondPassParse + * + * PARAMETERS: Root - Root of the parse tree + * + * RETURN: Status + * + * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until + * second pass to parse the control methods + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbSecondPassParse ( + ACPI_PARSE_OBJECT *Root) +{ + ACPI_PARSE_OBJECT *Op = Root; + ACPI_PARSE_OBJECT *Method; + ACPI_PARSE_OBJECT *SearchOp; + ACPI_PARSE_OBJECT *StartOp; + ACPI_STATUS Status = AE_OK; + UINT32 BaseAmlOffset; + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_ENTRY (); + + + AcpiOsPrintf ("Pass two parse ....\n"); + + while (Op) + { + if (Op->Common.AmlOpcode == AML_METHOD_OP) + { + Method = Op; + + /* Create a new walk state for the parse */ + + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + return (AE_NO_MEMORY); + } + + /* Init the Walk State */ + + WalkState->ParserState.Aml = + WalkState->ParserState.AmlStart = Method->Named.Data; + WalkState->ParserState.AmlEnd = + WalkState->ParserState.PkgEnd = Method->Named.Data + + Method->Named.Length; + WalkState->ParserState.StartScope = Op; + + WalkState->DescendingCallback = AcpiDsLoad1BeginOp; + WalkState->AscendingCallback = AcpiDsLoad1EndOp; + + /* Perform the AML parse */ + + Status = AcpiPsParseAml (WalkState); + + BaseAmlOffset = (Method->Common.Value.Arg)->Common.AmlOffset + 1; + StartOp = (Method->Common.Value.Arg)->Common.Next; + SearchOp = StartOp; + + while (SearchOp) + { + SearchOp->Common.AmlOffset += BaseAmlOffset; + SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); + } + } + + if (Op->Common.AmlOpcode == AML_REGION_OP) + { + /* TBD: [Investigate] this isn't quite the right thing to do! */ + /* + * + * Method = (ACPI_DEFERRED_OP *) Op; + * Status = AcpiPsParseAml (Op, Method->Body, Method->BodyLength); + */ + } + + if (ACPI_FAILURE (Status)) + { + break; + } + + Op = AcpiPsGetDepthNext (Root, Op); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbDumpBuffer + * + * PARAMETERS: Address - Pointer to the buffer + * + * RETURN: None + * + * DESCRIPTION: Print a portion of a buffer + * + ******************************************************************************/ + +void +AcpiDbDumpBuffer ( + UINT32 Address) +{ + + AcpiOsPrintf ("\nLocation %X:\n", Address); + + AcpiDbgLevel |= ACPI_LV_TABLES; + AcpiUtDumpBuffer (ACPI_TO_POINTER (Address), 64, DB_BYTE_DISPLAY, + ACPI_UINT32_MAX); +} +#endif + +#endif /* ACPI_DEBUGGER */ + + diff --git a/source/components/debugger/dbxface.c b/source/components/debugger/dbxface.c new file mode 100644 index 000000000000..cd3027343459 --- /dev/null +++ b/source/components/debugger/dbxface.c @@ -0,0 +1,536 @@ +/******************************************************************************* + * + * Module Name: dbxface - AML Debugger external interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdebug.h" +#include "acdisasm.h" + + +#ifdef ACPI_DEBUGGER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbxface") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDbStartCommand ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +void +AcpiDbMethodEnd ( + ACPI_WALK_STATE *WalkState); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDbStartCommand + * + * PARAMETERS: WalkState - Current walk + * Op - Current executing Op, from AML interpreter + * + * RETURN: Status + * + * DESCRIPTION: Enter debugger command loop + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDbStartCommand ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + + + /* TBD: [Investigate] are there namespace locking issues here? */ + + /* AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); */ + + /* Go into the command loop and await next user command */ + + + AcpiGbl_MethodExecuting = TRUE; + Status = AE_CTRL_TRUE; + while (Status == AE_CTRL_TRUE) + { + if (AcpiGbl_DebuggerConfiguration == DEBUGGER_MULTI_THREADED) + { + /* Handshake with the front-end that gets user command lines */ + + Status = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else + { + /* Single threaded, we must get a command line ourselves */ + + /* Force output to console until a command is entered */ + + AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!AcpiGbl_MethodExecuting) + { + AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); + } + else + { + AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + Status = AcpiOsGetLine (AcpiGbl_DbLineBuf, + ACPI_DB_LINE_BUFFER_SIZE, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line")); + return (Status); + } + } + + Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, WalkState, Op); + } + + /* AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); */ + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbSingleStep + * + * PARAMETERS: WalkState - Current walk + * Op - Current executing op (from aml interpreter) + * OpcodeClass - Class of the current AML Opcode + * + * RETURN: Status + * + * DESCRIPTION: Called just before execution of an AML opcode. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbSingleStep ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 OpcodeClass) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_STATUS Status = AE_OK; + UINT32 OriginalDebugLevel; + ACPI_PARSE_OBJECT *DisplayOp; + ACPI_PARSE_OBJECT *ParentOp; + + + ACPI_FUNCTION_ENTRY (); + + + /* Check the abort flag */ + + if (AcpiGbl_AbortMethod) + { + AcpiGbl_AbortMethod = FALSE; + return (AE_ABORT_METHOD); + } + + /* Check for single-step breakpoint */ + + if (WalkState->MethodBreakpoint && + (WalkState->MethodBreakpoint <= Op->Common.AmlOffset)) + { + /* Check if the breakpoint has been reached or passed */ + /* Hit the breakpoint, resume single step, reset breakpoint */ + + AcpiOsPrintf ("***Break*** at AML offset %X\n", Op->Common.AmlOffset); + AcpiGbl_CmSingleStep = TRUE; + AcpiGbl_StepToNextCall = FALSE; + WalkState->MethodBreakpoint = 0; + } + + /* Check for user breakpoint (Must be on exact Aml offset) */ + + else if (WalkState->UserBreakpoint && + (WalkState->UserBreakpoint == Op->Common.AmlOffset)) + { + AcpiOsPrintf ("***UserBreakpoint*** at AML offset %X\n", + Op->Common.AmlOffset); + AcpiGbl_CmSingleStep = TRUE; + AcpiGbl_StepToNextCall = FALSE; + WalkState->MethodBreakpoint = 0; + } + + /* + * Check if this is an opcode that we are interested in -- + * namely, opcodes that have arguments + */ + if (Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) + { + return (AE_OK); + } + + switch (OpcodeClass) + { + case AML_CLASS_UNKNOWN: + case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ + return (AE_OK); + + default: + /* All other opcodes -- continue */ + break; + } + + /* + * Under certain debug conditions, display this opcode and its operands + */ + if ((AcpiGbl_DbOutputToFile) || + (AcpiGbl_CmSingleStep) || + (AcpiDbgLevel & ACPI_LV_PARSE)) + { + if ((AcpiGbl_DbOutputToFile) || + (AcpiDbgLevel & ACPI_LV_PARSE)) + { + AcpiOsPrintf ("\n[AmlDebug] Next AML Opcode to execute:\n"); + } + + /* + * Display this op (and only this op - zero out the NEXT field + * temporarily, and disable parser trace output for the duration of + * the display because we don't want the extraneous debug output) + */ + OriginalDebugLevel = AcpiDbgLevel; + AcpiDbgLevel &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); + Next = Op->Common.Next; + Op->Common.Next = NULL; + + + DisplayOp = Op; + ParentOp = Op->Common.Parent; + if (ParentOp) + { + if ((WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_PREDICATE_EXECUTING)) + { + /* + * We are executing the predicate of an IF or WHILE statement + * Search upwards for the containing IF or WHILE so that the + * entire predicate can be displayed. + */ + while (ParentOp) + { + if ((ParentOp->Common.AmlOpcode == AML_IF_OP) || + (ParentOp->Common.AmlOpcode == AML_WHILE_OP)) + { + DisplayOp = ParentOp; + break; + } + ParentOp = ParentOp->Common.Parent; + } + } + else + { + while (ParentOp) + { + if ((ParentOp->Common.AmlOpcode == AML_IF_OP) || + (ParentOp->Common.AmlOpcode == AML_ELSE_OP) || + (ParentOp->Common.AmlOpcode == AML_SCOPE_OP) || + (ParentOp->Common.AmlOpcode == AML_METHOD_OP) || + (ParentOp->Common.AmlOpcode == AML_WHILE_OP)) + { + break; + } + DisplayOp = ParentOp; + ParentOp = ParentOp->Common.Parent; + } + } + } + + /* Now we can display it */ + + AcpiDmDisassemble (WalkState, DisplayOp, ACPI_UINT32_MAX); + + if ((Op->Common.AmlOpcode == AML_IF_OP) || + (Op->Common.AmlOpcode == AML_WHILE_OP)) + { + if (WalkState->ControlState->Common.Value) + { + AcpiOsPrintf ("Predicate = [True], IF block was executed\n"); + } + else + { + AcpiOsPrintf ("Predicate = [False], Skipping IF block\n"); + } + } + else if (Op->Common.AmlOpcode == AML_ELSE_OP) + { + AcpiOsPrintf ("Predicate = [False], ELSE block was executed\n"); + } + + /* Restore everything */ + + Op->Common.Next = Next; + AcpiOsPrintf ("\n"); + if ((AcpiGbl_DbOutputToFile) || + (AcpiDbgLevel & ACPI_LV_PARSE)) + { + AcpiOsPrintf ("\n"); + } + AcpiDbgLevel = OriginalDebugLevel; + } + + /* If we are not single stepping, just continue executing the method */ + + if (!AcpiGbl_CmSingleStep) + { + return (AE_OK); + } + + /* + * If we are executing a step-to-call command, + * Check if this is a method call. + */ + if (AcpiGbl_StepToNextCall) + { + if (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP) + { + /* Not a method call, just keep executing */ + + return (AE_OK); + } + + /* Found a method call, stop executing */ + + AcpiGbl_StepToNextCall = FALSE; + } + + /* + * If the next opcode is a method call, we will "step over" it + * by default. + */ + if (Op->Common.AmlOpcode == AML_INT_METHODCALL_OP) + { + /* Force no more single stepping while executing called method */ + + AcpiGbl_CmSingleStep = FALSE; + + /* + * Set the breakpoint on/before the call, it will stop execution + * as soon as we return + */ + WalkState->MethodBreakpoint = 1; /* Must be non-zero! */ + } + + + Status = AcpiDbStartCommand (WalkState, Op); + + /* User commands complete, continue execution of the interrupted method */ + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init and start debugger + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDbInitialize ( + void) +{ + ACPI_STATUS Status; + + + /* Init globals */ + + AcpiGbl_DbBuffer = NULL; + AcpiGbl_DbFilename = NULL; + AcpiGbl_DbOutputToFile = FALSE; + + AcpiGbl_DbDebugLevel = ACPI_LV_VERBOSITY2; + AcpiGbl_DbConsoleDebugLevel = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; + AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; + + AcpiGbl_DbOpt_tables = FALSE; + AcpiGbl_DbOpt_disasm = FALSE; + AcpiGbl_DbOpt_stats = FALSE; + AcpiGbl_DbOpt_verbose = TRUE; + AcpiGbl_DbOpt_ini_methods = TRUE; + + AcpiGbl_DbBuffer = AcpiOsAllocate (ACPI_DEBUG_BUFFER_SIZE); + if (!AcpiGbl_DbBuffer) + { + return (AE_NO_MEMORY); + } + ACPI_MEMSET (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE); + + /* Initial scope is the root */ + + AcpiGbl_DbScopeBuf [0] = '\\'; + AcpiGbl_DbScopeBuf [1] = 0; + AcpiGbl_DbScopeNode = AcpiGbl_RootNode; + + /* + * If configured for multi-thread support, the debug executor runs in + * a separate thread so that the front end can be in another address + * space, environment, or even another machine. + */ + if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED) + { + /* These were created with one unit, grab it */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get debugger mutex\n"); + return (Status); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not get debugger mutex\n"); + return (Status); + } + + /* Create the debug execution thread to execute commands */ + + Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbExecuteThread, NULL); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not start debugger thread\n"); + return (Status); + } + } + + if (!AcpiGbl_DbOpt_verbose) + { + AcpiGbl_DbOpt_disasm = TRUE; + AcpiGbl_DbOpt_stats = FALSE; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDbTerminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Stop debugger + * + ******************************************************************************/ + +void +AcpiDbTerminate ( + void) +{ + + if (AcpiGbl_DbBuffer) + { + AcpiOsFree (AcpiGbl_DbBuffer); + } +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiDbMethodEnd + * + * PARAMETERS: WalkState - Current walk + * + * RETURN: Status + * + * DESCRIPTION: Called at method termination + * + ******************************************************************************/ + +void +AcpiDbMethodEnd ( + ACPI_WALK_STATE *WalkState) +{ + + if (!AcpiGbl_CmSingleStep) + { + return; + } + + AcpiOsPrintf ("\n"); + + AcpiDbStartCommand (WalkState, NULL); +} +#endif + +#endif /* ACPI_DEBUGGER */ diff --git a/source/components/disassembler/dmbuffer.c b/source/components/disassembler/dmbuffer.c new file mode 100644 index 000000000000..9f49f92e4743 --- /dev/null +++ b/source/components/disassembler/dmbuffer.c @@ -0,0 +1,542 @@ +/******************************************************************************* + * + * Module Name: dmbuffer - AML disassembler, buffer and string support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" +#include "acparser.h" +#include "amlcode.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmbuffer") + +/* Local prototypes */ + +static void +AcpiDmUnicode ( + ACPI_PARSE_OBJECT *Op); + +static void +AcpiDmIsEisaIdElement ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisasmByteList + * + * PARAMETERS: Level - Current source code indentation level + * ByteData - Pointer to the byte list + * ByteCount - Length of the byte list + * + * RETURN: None + * + * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed + * with the hex buffer offset. + * + ******************************************************************************/ + +void +AcpiDmDisasmByteList ( + UINT32 Level, + UINT8 *ByteData, + UINT32 ByteCount) +{ + UINT32 i; + + + if (!ByteCount) + { + return; + } + + /* Dump the byte list */ + + for (i = 0; i < ByteCount; i++) + { + /* New line every 8 bytes */ + + if (((i % 8) == 0) && (i < ByteCount)) + { + if (i > 0) + { + AcpiOsPrintf ("\n"); + } + + AcpiDmIndent (Level); + if (ByteCount > 8) + { + AcpiOsPrintf ("/* %04X */ ", i); + } + } + + AcpiOsPrintf (" 0x%2.2X", (UINT32) ByteData[i]); + + /* Add comma if there are more bytes to display */ + + if (i < (ByteCount -1)) + { + AcpiOsPrintf (","); + } + } + + if (Level) + { + AcpiOsPrintf ("\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmByteList + * + * PARAMETERS: Info - Parse tree walk info + * Op - Byte list op + * + * RETURN: None + * + * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers. + * Buffer type must be already set in the Op DisasmOpcode. + * + ******************************************************************************/ + +void +AcpiDmByteList ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op) +{ + UINT8 *ByteData; + UINT32 ByteCount; + + + ByteData = Op->Named.Data; + ByteCount = (UINT32) Op->Common.Value.Integer; + + /* + * The byte list belongs to a buffer, and can be produced by either + * a ResourceTemplate, Unicode, quoted string, or a plain byte list. + */ + switch (Op->Common.Parent->Common.DisasmOpcode) + { + case ACPI_DASM_RESOURCE: + + AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount); + break; + + case ACPI_DASM_STRING: + + AcpiDmIndent (Info->Level); + AcpiUtPrintString ((char *) ByteData, ACPI_UINT8_MAX); + AcpiOsPrintf ("\n"); + break; + + case ACPI_DASM_UNICODE: + + AcpiDmUnicode (Op); + break; + + case ACPI_DASM_BUFFER: + default: + + /* + * Not a resource, string, or unicode string. + * Just dump the buffer + */ + AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIsUnicodeBuffer + * + * PARAMETERS: Op - Buffer Object to be examined + * + * RETURN: TRUE if buffer contains a UNICODE string + * + * DESCRIPTION: Determine if a buffer Op contains a Unicode string + * + ******************************************************************************/ + +BOOLEAN +AcpiDmIsUnicodeBuffer ( + ACPI_PARSE_OBJECT *Op) +{ + UINT8 *ByteData; + UINT32 ByteCount; + UINT32 WordCount; + ACPI_PARSE_OBJECT *SizeOp; + ACPI_PARSE_OBJECT *NextOp; + UINT32 i; + + + /* Buffer size is the buffer argument */ + + SizeOp = Op->Common.Value.Arg; + + /* Next, the initializer byte list to examine */ + + NextOp = SizeOp->Common.Next; + if (!NextOp) + { + return (FALSE); + } + + /* Extract the byte list info */ + + ByteData = NextOp->Named.Data; + ByteCount = (UINT32) NextOp->Common.Value.Integer; + WordCount = ACPI_DIV_2 (ByteCount); + + /* + * Unicode string must have an even number of bytes and last + * word must be zero + */ + if ((!ByteCount) || + (ByteCount < 4) || + (ByteCount & 1) || + ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0) + { + return (FALSE); + } + + /* For each word, 1st byte must be ascii, 2nd byte must be zero */ + + for (i = 0; i < (ByteCount - 2); i += 2) + { + if ((!ACPI_IS_PRINT (ByteData[i])) || + (ByteData[(ACPI_SIZE) i + 1] != 0)) + { + return (FALSE); + } + } + + /* Ignore the Size argument in the disassembly of this buffer op */ + + SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIsStringBuffer + * + * PARAMETERS: Op - Buffer Object to be examined + * + * RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise + * + * DESCRIPTION: Determine if a buffer Op contains a ASCII string + * + ******************************************************************************/ + +BOOLEAN +AcpiDmIsStringBuffer ( + ACPI_PARSE_OBJECT *Op) +{ + UINT8 *ByteData; + UINT32 ByteCount; + ACPI_PARSE_OBJECT *SizeOp; + ACPI_PARSE_OBJECT *NextOp; + UINT32 i; + + + /* Buffer size is the buffer argument */ + + SizeOp = Op->Common.Value.Arg; + + /* Next, the initializer byte list to examine */ + + NextOp = SizeOp->Common.Next; + if (!NextOp) + { + return (FALSE); + } + + /* Extract the byte list info */ + + ByteData = NextOp->Named.Data; + ByteCount = (UINT32) NextOp->Common.Value.Integer; + + /* Last byte must be the null terminator */ + + if ((!ByteCount) || + (ByteCount < 2) || + (ByteData[ByteCount-1] != 0)) + { + return (FALSE); + } + + for (i = 0; i < (ByteCount - 1); i++) + { + /* TBD: allow some escapes (non-ascii chars). + * they will be handled in the string output routine + */ + + if (!ACPI_IS_PRINT (ByteData[i])) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmUnicode + * + * PARAMETERS: Op - Byte List op containing Unicode string + * + * RETURN: None + * + * DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove + * the extra zero bytes). + * + ******************************************************************************/ + +static void +AcpiDmUnicode ( + ACPI_PARSE_OBJECT *Op) +{ + UINT16 *WordData; + UINT32 WordCount; + UINT32 i; + + + /* Extract the buffer info as a WORD buffer */ + + WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data); + WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer)); + + + AcpiOsPrintf ("\""); + + /* Write every other byte as an ASCII character */ + + for (i = 0; i < (WordCount - 1); i++) + { + AcpiOsPrintf ("%c", (int) WordData[i]); + } + + AcpiOsPrintf ("\")"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIsEisaIdElement + * + * PARAMETERS: Op - Op to be examined + * + * RETURN: None + * + * DESCRIPTION: Determine if an Op (argument to _HID or _CID) can be converted + * to an EISA ID. + * + ******************************************************************************/ + +static void +AcpiDmIsEisaIdElement ( + ACPI_PARSE_OBJECT *Op) +{ + UINT32 BigEndianId; + UINT32 Prefix[3]; + UINT32 i; + + + /* The parameter must be either a word or a dword */ + + if ((Op->Common.AmlOpcode != AML_DWORD_OP) && + (Op->Common.AmlOpcode != AML_WORD_OP)) + { + return; + } + + /* Swap from little-endian to big-endian to simplify conversion */ + + BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer); + + /* Create the 3 leading ASCII letters */ + + Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40; + Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40; + Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40; + + /* Verify that all 3 are ascii and alpha */ + + for (i = 0; i < 3; i++) + { + if (!ACPI_IS_ASCII (Prefix[i]) || + !ACPI_IS_ALPHA (Prefix[i])) + { + return; + } + } + + /* OK - mark this node as convertable to an EISA ID */ + + Op->Common.DisasmOpcode = ACPI_DASM_EISAID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIsEisaId + * + * PARAMETERS: Op - Op to be examined + * + * RETURN: None + * + * DESCRIPTION: Determine if a Name() Op can be converted to an EisaId. + * + ******************************************************************************/ + +void +AcpiDmIsEisaId ( + ACPI_PARSE_OBJECT *Op) +{ + UINT32 Name; + ACPI_PARSE_OBJECT *NextOp; + + + /* Get the NameSegment */ + + Name = AcpiPsGetName (Op); + if (!Name) + { + return; + } + + NextOp = AcpiPsGetDepthNext (NULL, Op); + if (!NextOp) + { + return; + } + + /* Check for _HID - has one argument */ + + if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID)) + { + AcpiDmIsEisaIdElement (NextOp); + return; + } + + /* Exit if not _CID */ + + if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID)) + { + return; + } + + /* _CID can contain a single argument or a package */ + + if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP) + { + AcpiDmIsEisaIdElement (NextOp); + return; + } + + /* _CID with Package: get the package length */ + + NextOp = AcpiPsGetDepthNext (NULL, NextOp); + + /* Don't need to use the length, just walk the peer list */ + + NextOp = NextOp->Common.Next; + while (NextOp) + { + AcpiDmIsEisaIdElement (NextOp); + NextOp = NextOp->Common.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmEisaId + * + * PARAMETERS: EncodedId - Raw encoded EISA ID. + * + * RETURN: None + * + * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String. + * + ******************************************************************************/ + +void +AcpiDmEisaId ( + UINT32 EncodedId) +{ + UINT32 BigEndianId; + + + /* Swap from little-endian to big-endian to simplify conversion */ + + BigEndianId = AcpiUtDwordByteSwap (EncodedId); + + + /* Split to form "AAANNNN" string */ + + AcpiOsPrintf ("EisaId (\"%c%c%c%4.4X\")", + + /* Three Alpha characters (AAA), 5 bits each */ + + (int) ((BigEndianId >> 26) & 0x1F) + 0x40, + (int) ((BigEndianId >> 21) & 0x1F) + 0x40, + (int) ((BigEndianId >> 16) & 0x1F) + 0x40, + + /* Numeric part (NNNN) is simply the lower 16 bits */ + + (UINT32) (BigEndianId & 0xFFFF)); +} + +#endif diff --git a/source/components/disassembler/dmnames.c b/source/components/disassembler/dmnames.c new file mode 100644 index 000000000000..92e67c2e0a8c --- /dev/null +++ b/source/components/disassembler/dmnames.c @@ -0,0 +1,453 @@ +/******************************************************************************* + * + * Module Name: dmnames - AML disassembler, names, namestrings, pathnames + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdisasm.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmnames") + +/* Local prototypes */ + +#ifdef ACPI_OBSOLETE_FUNCTIONS +void +AcpiDmDisplayPath ( + ACPI_PARSE_OBJECT *Op); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpName + * + * PARAMETERS: Name - 4 character ACPI name + * + * RETURN: Final length of name + * + * DESCRIPTION: Dump an ACPI name, minus any trailing underscores. + * + ******************************************************************************/ + +UINT32 +AcpiDmDumpName ( + UINT32 Name) +{ + UINT32 i; + UINT32 Length; + char NewName[4]; + + + /* Copy name locally in case the original name is not writeable */ + + *ACPI_CAST_PTR (UINT32, &NewName[0]) = Name; + + /* Ensure that the name is printable, even if we have to fix it */ + + AcpiUtRepairName (NewName); + + /* Remove all trailing underscores from the name */ + + Length = ACPI_NAME_SIZE; + for (i = (ACPI_NAME_SIZE - 1); i != 0; i--) + { + if (NewName[i] == '_') + { + Length--; + } + else + { + break; + } + } + + /* Dump the name, up to the start of the trailing underscores */ + + for (i = 0; i < Length; i++) + { + AcpiOsPrintf ("%c", NewName[i]); + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsDisplayObjectPathname + * + * PARAMETERS: WalkState - Current walk state + * Op - Object whose pathname is to be obtained + * + * RETURN: Status + * + * DESCRIPTION: Diplay the pathname associated with a named object. Two + * versions. One searches the parse tree (for parser-only + * applications suchas AcpiDump), and the other searches the + * ACPI namespace (the parse tree is probably deleted) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsDisplayObjectPathname ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_BUFFER Buffer; + UINT32 DebugLevel; + + + /* Save current debug level so we don't get extraneous debug output */ + + DebugLevel = AcpiDbgLevel; + AcpiDbgLevel = 0; + + /* Just get the Node out of the Op object */ + + Node = Op->Common.Node; + if (!Node) + { + /* Node not defined in this scope, look it up */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + WalkState, &(Node)); + + if (ACPI_FAILURE (Status)) + { + /* + * We can't get the pathname since the object + * is not in the namespace. This can happen during single + * stepping where a dynamic named object is *about* to be created. + */ + AcpiOsPrintf (" [Path not found]"); + goto Exit; + } + + /* Save it for next time. */ + + Op->Common.Node = Node; + } + + /* Convert NamedDesc/handle to a full pathname */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (Node, &Buffer); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("****Could not get pathname****)"); + goto Exit; + } + + AcpiOsPrintf (" (Path %s)", (char *) Buffer.Pointer); + ACPI_FREE (Buffer.Pointer); + + +Exit: + /* Restore the debug level */ + + AcpiDbgLevel = DebugLevel; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmNamestring + * + * PARAMETERS: Name - ACPI Name string to store + * + * RETURN: None + * + * DESCRIPTION: Decode and dump an ACPI namestring. Handles prefix characters + * + ******************************************************************************/ + +void +AcpiDmNamestring ( + char *Name) +{ + UINT32 SegCount; + + + if (!Name) + { + return; + } + + /* Handle all Scope Prefix operators */ + + while (AcpiPsIsPrefixChar (ACPI_GET8 (Name))) + { + /* Append prefix character */ + + AcpiOsPrintf ("%1c", ACPI_GET8 (Name)); + Name++; + } + + switch (ACPI_GET8 (Name)) + { + case 0: + SegCount = 0; + break; + + case AML_DUAL_NAME_PREFIX: + SegCount = 2; + Name++; + break; + + case AML_MULTI_NAME_PREFIX_OP: + SegCount = (UINT32) ACPI_GET8 (Name + 1); + Name += 2; + break; + + default: + SegCount = 1; + break; + } + + while (SegCount) + { + /* Append Name segment */ + + AcpiDmDumpName (*ACPI_CAST_PTR (UINT32, Name)); + + SegCount--; + if (SegCount) + { + /* Not last name, append dot separator */ + + AcpiOsPrintf ("."); + } + Name += ACPI_NAME_SIZE; + } +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiDmDisplayPath + * + * PARAMETERS: Op - Named Op whose path is to be constructed + * + * RETURN: None + * + * DESCRIPTION: Walk backwards from current scope and display the name + * of each previous level of scope up to the root scope + * (like "pwd" does with file systems) + * + ******************************************************************************/ + +void +AcpiDmDisplayPath ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Prev; + ACPI_PARSE_OBJECT *Search; + UINT32 Name; + BOOLEAN DoDot = FALSE; + ACPI_PARSE_OBJECT *NamePath; + const ACPI_OPCODE_INFO *OpInfo; + + + /* We are only interested in named objects */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (!(OpInfo->Flags & AML_NSNODE)) + { + return; + } + + if (OpInfo->Flags & AML_CREATE) + { + /* Field creation - check for a fully qualified namepath */ + + if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) + { + NamePath = AcpiPsGetArg (Op, 3); + } + else + { + NamePath = AcpiPsGetArg (Op, 2); + } + + if ((NamePath) && + (NamePath->Common.Value.String) && + (NamePath->Common.Value.String[0] == '\\')) + { + AcpiDmNamestring (NamePath->Common.Value.String); + return; + } + } + + Prev = NULL; /* Start with Root Node */ + + while (Prev != Op) + { + /* Search upwards in the tree to find scope with "prev" as its parent */ + + Search = Op; + for (; ;) + { + if (Search->Common.Parent == Prev) + { + break; + } + + /* Go up one level */ + + Search = Search->Common.Parent; + } + + if (Prev) + { + OpInfo = AcpiPsGetOpcodeInfo (Search->Common.AmlOpcode); + if (!(OpInfo->Flags & AML_FIELD)) + { + /* Below root scope, append scope name */ + + if (DoDot) + { + /* Append dot */ + + AcpiOsPrintf ("."); + } + + if (OpInfo->Flags & AML_CREATE) + { + if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) + { + NamePath = AcpiPsGetArg (Op, 3); + } + else + { + NamePath = AcpiPsGetArg (Op, 2); + } + + if ((NamePath) && + (NamePath->Common.Value.String)) + { + AcpiDmDumpName (NamePath->Common.Value.String); + } + } + else + { + Name = AcpiPsGetName (Search); + AcpiDmDumpName ((char *) &Name); + } + + DoDot = TRUE; + } + } + Prev = Search; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmValidateName + * + * PARAMETERS: Name - 4 character ACPI name + * + * RETURN: None + * + * DESCRIPTION: Lookup the name + * + ******************************************************************************/ + +void +AcpiDmValidateName ( + char *Name, + ACPI_PARSE_OBJECT *Op) +{ + + if ((!Name) || + (!Op->Common.Parent)) + { + return; + } + + if (!Op->Common.Node) + { + AcpiOsPrintf ( + " /**** Name not found or not accessible from this scope ****/ "); + } + + ACPI_PARSE_OBJECT *TargetOp; + + + if ((!Name) || + (!Op->Common.Parent)) + { + return; + } + + TargetOp = AcpiPsFind (Op, Name, 0, 0); + if (!TargetOp) + { + /* + * Didn't find the name in the parse tree. This may be + * a problem, or it may simply be one of the predefined names + * (such as _OS_). Rather than worry about looking up all + * the predefined names, just display the name as given + */ + AcpiOsPrintf ( + " /**** Name not found or not accessible from this scope ****/ "); + } +} +#endif + +#endif + + diff --git a/source/components/disassembler/dmobject.c b/source/components/disassembler/dmobject.c new file mode 100644 index 000000000000..cb515e94279d --- /dev/null +++ b/source/components/disassembler/dmobject.c @@ -0,0 +1,589 @@ +/******************************************************************************* + * + * Module Name: dmobject - ACPI object decode and display + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdisasm.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmnames") + +/* Local prototypes */ + +static void +AcpiDmDecodeNode ( + ACPI_NAMESPACE_NODE *Node); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMethodInfo + * + * PARAMETERS: Status - Method execution status + * WalkState - Current state of the parse tree walk + * Op - Executing parse op + * + * RETURN: None + * + * DESCRIPTION: Called when a method has been aborted because of an error. + * Dumps the method execution stack, and the method locals/args, + * and disassembles the AML opcode that failed. + * + ******************************************************************************/ + +void +AcpiDmDumpMethodInfo ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_THREAD_STATE *Thread; + ACPI_WALK_STATE *NextWalkState; + ACPI_NAMESPACE_NODE *PreviousMethod = NULL; + + + /* Ignore control codes, they are not errors */ + + if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL) + { + return; + } + + /* We may be executing a deferred opcode */ + + if (WalkState->DeferredNode) + { + AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n"); + return; + } + + /* + * If there is no Thread, we are not actually executing a method. + * This can happen when the iASL compiler calls the interpreter + * to perform constant folding. + */ + Thread = WalkState->Thread; + if (!Thread) + { + return; + } + + /* Display exception and method name */ + + AcpiOsPrintf ("\n**** Exception %s during execution of method ", + AcpiFormatException (Status)); + AcpiNsPrintNodePathname (WalkState->MethodNode, NULL); + + /* Display stack of executing methods */ + + AcpiOsPrintf ("\n\nMethod Execution Stack:\n"); + NextWalkState = Thread->WalkStateList; + + /* Walk list of linked walk states */ + + while (NextWalkState) + { + AcpiOsPrintf (" Method [%4.4s] executing: ", + AcpiUtGetNodeName (NextWalkState->MethodNode)); + + /* First method is the currently executing method */ + + if (NextWalkState == WalkState) + { + if (Op) + { + /* Display currently executing ASL statement */ + + Next = Op->Common.Next; + Op->Common.Next = NULL; + + AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); + Op->Common.Next = Next; + } + } + else + { + /* + * This method has called another method + * NOTE: the method call parse subtree is already deleted at this + * point, so we cannot disassemble the method invocation. + */ + AcpiOsPrintf ("Call to method "); + AcpiNsPrintNodePathname (PreviousMethod, NULL); + } + + PreviousMethod = NextWalkState->MethodNode; + NextWalkState = NextWalkState->Next; + AcpiOsPrintf ("\n"); + } + + /* Display the method locals and arguments */ + + AcpiOsPrintf ("\n"); + AcpiDmDisplayLocals (WalkState); + AcpiOsPrintf ("\n"); + AcpiDmDisplayArguments (WalkState); + AcpiOsPrintf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDecodeInternalObject + * + * PARAMETERS: ObjDesc - Object to be displayed + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers. + * + ******************************************************************************/ + +void +AcpiDmDecodeInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + UINT32 i; + + + if (!ObjDesc) + { + AcpiOsPrintf (" Uninitialized"); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf (" %p [%s]", ObjDesc, AcpiUtGetDescriptorName (ObjDesc)); + return; + } + + AcpiOsPrintf (" %s", AcpiUtGetObjectTypeName (ObjDesc)); + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf (" %8.8X%8.8X", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("(%u) \"%.24s", + ObjDesc->String.Length, ObjDesc->String.Pointer); + + if (ObjDesc->String.Length > 24) + { + AcpiOsPrintf ("..."); + } + else + { + AcpiOsPrintf ("\""); + } + break; + + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length); + for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++) + { + AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]); + } + break; + + + default: + + AcpiOsPrintf (" %p", ObjDesc); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDecodeNode + * + * PARAMETERS: Node - Object to be displayed + * + * RETURN: None + * + * DESCRIPTION: Short display of a namespace node + * + ******************************************************************************/ + +static void +AcpiDmDecodeNode ( + ACPI_NAMESPACE_NODE *Node) +{ + + AcpiOsPrintf (" Name %4.4s", + AcpiUtGetNodeName (Node)); + + if (Node->Flags & ANOBJ_METHOD_ARG) + { + AcpiOsPrintf (" [Method Arg]"); + } + if (Node->Flags & ANOBJ_METHOD_LOCAL) + { + AcpiOsPrintf (" [Method Local]"); + } + + switch (Node->Type) + { + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + AcpiOsPrintf (" Device"); + break; + + case ACPI_TYPE_THERMAL: + AcpiOsPrintf (" Thermal Zone"); + break; + + default: + AcpiDmDecodeInternalObject (AcpiNsGetAttachedObject (Node)); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisplayInternalObject + * + * PARAMETERS: ObjDesc - Object to be displayed + * WalkState - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object + * + ******************************************************************************/ + +void +AcpiDmDisplayInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + UINT8 Type; + + + AcpiOsPrintf ("%p ", ObjDesc); + + if (!ObjDesc) + { + AcpiOsPrintf ("\n"); + return; + } + + /* Decode the object type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) + { + case ACPI_DESC_TYPE_PARSER: + + AcpiOsPrintf (" "); + break; + + + case ACPI_DESC_TYPE_NAMED: + + AcpiDmDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc); + break; + + + case ACPI_DESC_TYPE_OPERAND: + + Type = ObjDesc->Common.Type; + if (Type > ACPI_TYPE_LOCAL_MAX) + { + AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type); + return; + } + + /* Decode the ACPI object type */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc)); + + /* Decode the refererence */ + + switch (ObjDesc->Reference.Class) + { + case ACPI_REFCLASS_LOCAL: + + AcpiOsPrintf ("%X ", ObjDesc->Reference.Value); + if (WalkState) + { + ObjDesc = WalkState->LocalVariables + [ObjDesc->Reference.Value].Object; + AcpiOsPrintf ("%p", ObjDesc); + AcpiDmDecodeInternalObject (ObjDesc); + } + break; + + + case ACPI_REFCLASS_ARG: + + AcpiOsPrintf ("%X ", ObjDesc->Reference.Value); + if (WalkState) + { + ObjDesc = WalkState->Arguments + [ObjDesc->Reference.Value].Object; + AcpiOsPrintf ("%p", ObjDesc); + AcpiDmDecodeInternalObject (ObjDesc); + } + break; + + + case ACPI_REFCLASS_INDEX: + + switch (ObjDesc->Reference.TargetType) + { + case ACPI_TYPE_BUFFER_FIELD: + + AcpiOsPrintf ("%p", ObjDesc->Reference.Object); + AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); + break; + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("%p", ObjDesc->Reference.Where); + if (!ObjDesc->Reference.Where) + { + AcpiOsPrintf (" Uninitialized WHERE pointer"); + } + else + { + AcpiDmDecodeInternalObject ( + *(ObjDesc->Reference.Where)); + } + break; + + default: + + AcpiOsPrintf ("Unknown index target type"); + break; + } + break; + + + case ACPI_REFCLASS_REFOF: + + if (!ObjDesc->Reference.Object) + { + AcpiOsPrintf ("Uninitialized reference subobject pointer"); + break; + } + + /* Reference can be to a Node or an Operand object */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object)) + { + case ACPI_DESC_TYPE_NAMED: + AcpiDmDecodeNode (ObjDesc->Reference.Object); + break; + + case ACPI_DESC_TYPE_OPERAND: + AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); + break; + + default: + break; + } + break; + + + case ACPI_REFCLASS_NAME: + + AcpiDmDecodeNode (ObjDesc->Reference.Node); + break; + + + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: + + AcpiOsPrintf ("\n"); + break; + + + default: /* Unknown reference class */ + + AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class); + break; + } + break; + + + default: + + AcpiOsPrintf (" "); + AcpiDmDecodeInternalObject (ObjDesc); + break; + } + break; + + + default: + + AcpiOsPrintf (" [%s]", + AcpiUtGetDescriptorName (ObjDesc)); + break; + } + + AcpiOsPrintf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisplayLocals + * + * PARAMETERS: WalkState - State for current method + * + * RETURN: None + * + * DESCRIPTION: Display all locals for the currently running control method + * + ******************************************************************************/ + +void +AcpiDmDisplayLocals ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + + + ObjDesc = WalkState->MethodDesc; + Node = WalkState->MethodNode; + if (!Node) + { + AcpiOsPrintf ( + "No method node (Executing subtree for buffer or opregion)\n"); + return; + } + + if (Node->Type != ACPI_TYPE_METHOD) + { + AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n"); + return; + } + + AcpiOsPrintf ("Local Variables for method [%4.4s]:\n", + AcpiUtGetNodeName (Node)); + + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) + { + ObjDesc = WalkState->LocalVariables[i].Object; + AcpiOsPrintf (" Local%X: ", i); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisplayArguments + * + * PARAMETERS: WalkState - State for current method + * + * RETURN: None + * + * DESCRIPTION: Display all arguments for the currently running control method + * + ******************************************************************************/ + +void +AcpiDmDisplayArguments ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + + + ObjDesc = WalkState->MethodDesc; + Node = WalkState->MethodNode; + if (!Node) + { + AcpiOsPrintf ( + "No method node (Executing subtree for buffer or opregion)\n"); + return; + } + + if (Node->Type != ACPI_TYPE_METHOD) + { + AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n"); + return; + } + + AcpiOsPrintf ( + "Arguments for Method [%4.4s]: (%X arguments defined, max concurrency = %X)\n", + AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount, ObjDesc->Method.SyncLevel); + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + ObjDesc = WalkState->Arguments[i].Object; + AcpiOsPrintf (" Arg%u: ", i); + AcpiDmDisplayInternalObject (ObjDesc, WalkState); + } +} + +#endif + + diff --git a/source/components/disassembler/dmopcode.c b/source/components/disassembler/dmopcode.c new file mode 100644 index 000000000000..6d2c3e1ecf55 --- /dev/null +++ b/source/components/disassembler/dmopcode.c @@ -0,0 +1,607 @@ +/******************************************************************************* + * + * Module Name: dmopcode - AML disassembler, specific AML opcodes + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdisasm.h" + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmopcode") + +/* Local prototypes */ + +static void +AcpiDmMatchKeyword ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMethodFlags + * + * PARAMETERS: Op - Method Object to be examined + * + * RETURN: None + * + * DESCRIPTION: Decode control method flags + * + ******************************************************************************/ + +void +AcpiDmMethodFlags ( + ACPI_PARSE_OBJECT *Op) +{ + UINT32 Flags; + UINT32 Args; + + + /* The next Op contains the flags */ + + Op = AcpiPsGetDepthNext (NULL, Op); + Flags = (UINT8) Op->Common.Value.Integer; + Args = Flags & 0x07; + + /* Mark the Op as completed */ + + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + + /* 1) Method argument count */ + + AcpiOsPrintf (", %u, ", Args); + + /* 2) Serialize rule */ + + if (!(Flags & 0x08)) + { + AcpiOsPrintf ("Not"); + } + + AcpiOsPrintf ("Serialized"); + + /* 3) SyncLevel */ + + if (Flags & 0xF0) + { + AcpiOsPrintf (", %u", Flags >> 4); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFieldFlags + * + * PARAMETERS: Op - Field Object to be examined + * + * RETURN: None + * + * DESCRIPTION: Decode Field definition flags + * + ******************************************************************************/ + +void +AcpiDmFieldFlags ( + ACPI_PARSE_OBJECT *Op) +{ + UINT32 Flags; + + + Op = Op->Common.Next; + Flags = (UINT8) Op->Common.Value.Integer; + + /* Mark the Op as completed */ + + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + + AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]); + AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]); + AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddressSpace + * + * PARAMETERS: SpaceId - ID to be translated + * + * RETURN: None + * + * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword + * + ******************************************************************************/ + +void +AcpiDmAddressSpace ( + UINT8 SpaceId) +{ + + if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) + { + if (SpaceId == 0x7F) + { + AcpiOsPrintf ("FFixedHW, "); + } + else + { + AcpiOsPrintf ("0x%.2X, ", SpaceId); + } + } + else + { + AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmRegionFlags + * + * PARAMETERS: Op - Object to be examined + * + * RETURN: None + * + * DESCRIPTION: Decode OperationRegion flags + * + ******************************************************************************/ + +void +AcpiDmRegionFlags ( + ACPI_PARSE_OBJECT *Op) +{ + + + /* The next Op contains the SpaceId */ + + Op = AcpiPsGetDepthNext (NULL, Op); + + /* Mark the Op as completed */ + + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + + AcpiOsPrintf (", "); + AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMatchOp + * + * PARAMETERS: Op - Match Object to be examined + * + * RETURN: None + * + * DESCRIPTION: Decode Match opcode operands + * + ******************************************************************************/ + +void +AcpiDmMatchOp ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *NextOp; + + + NextOp = AcpiPsGetDepthNext (NULL, Op); + NextOp = NextOp->Common.Next; + + if (!NextOp) + { + /* Handle partial tree during single-step */ + + return; + } + + /* Mark the two nodes that contain the encoding for the match keywords */ + + NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; + + NextOp = NextOp->Common.Next; + NextOp = NextOp->Common.Next; + NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMatchKeyword + * + * PARAMETERS: Op - Match Object to be examined + * + * RETURN: None + * + * DESCRIPTION: Decode Match opcode operands + * + ******************************************************************************/ + +static void +AcpiDmMatchKeyword ( + ACPI_PARSE_OBJECT *Op) +{ + + + if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE) + { + AcpiOsPrintf ("/* Unknown Match Keyword encoding */"); + } + else + { + AcpiOsPrintf ("%s", ACPI_CAST_PTR (char, + AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer])); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisassembleOneOp + * + * PARAMETERS: WalkState - Current walk info + * Info - Parse tree walk info + * Op - Op that is to be printed + * + * RETURN: None + * + * DESCRIPTION: Disassemble a single AML opcode + * + ******************************************************************************/ + +void +AcpiDmDisassembleOneOp ( + ACPI_WALK_STATE *WalkState, + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *OpInfo = NULL; + UINT32 Offset; + UINT32 Length; + ACPI_PARSE_OBJECT *Child; + ACPI_STATUS Status; + UINT8 *Aml; + + + if (!Op) + { + AcpiOsPrintf (""); + return; + } + + switch (Op->Common.DisasmOpcode) + { + case ACPI_DASM_MATCHOP: + + AcpiDmMatchKeyword (Op); + return; + + case ACPI_DASM_LNOT_SUFFIX: + switch (Op->Common.AmlOpcode) + { + case AML_LEQUAL_OP: + AcpiOsPrintf ("LNotEqual"); + break; + + case AML_LGREATER_OP: + AcpiOsPrintf ("LLessEqual"); + break; + + case AML_LLESS_OP: + AcpiOsPrintf ("LGreaterEqual"); + break; + + default: + break; + } + Op->Common.DisasmOpcode = 0; + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + return; + + default: + break; + } + + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + /* The op and arguments */ + + switch (Op->Common.AmlOpcode) + { + case AML_LNOT_OP: + + Child = Op->Common.Value.Arg; + if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) || + (Child->Common.AmlOpcode == AML_LGREATER_OP) || + (Child->Common.AmlOpcode == AML_LLESS_OP)) + { + Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; + Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; + } + else + { + AcpiOsPrintf ("%s", OpInfo->Name); + } + break; + + case AML_BYTE_OP: + + AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer); + break; + + + case AML_WORD_OP: + + if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) + { + AcpiDmEisaId ((UINT32) Op->Common.Value.Integer); + } + else + { + AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer); + } + break; + + + case AML_DWORD_OP: + + if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) + { + AcpiDmEisaId ((UINT32) Op->Common.Value.Integer); + } + else + { + AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer); + } + break; + + + case AML_QWORD_OP: + + AcpiOsPrintf ("0x%8.8X%8.8X", + ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); + break; + + + case AML_STRING_OP: + + AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT8_MAX); + break; + + + case AML_BUFFER_OP: + + /* + * Determine the type of buffer. We can have one of the following: + * + * 1) ResourceTemplate containing Resource Descriptors. + * 2) Unicode String buffer + * 3) ASCII String buffer + * 4) Raw data buffer (if none of the above) + * + * Since there are no special AML opcodes to differentiate these + * types of buffers, we have to closely look at the data in the + * buffer to determine the type. + */ + if (!AcpiGbl_NoResourceDisassembly) + { + Status = AcpiDmIsResourceTemplate (Op); + if (ACPI_SUCCESS (Status)) + { + Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; + AcpiOsPrintf ("ResourceTemplate"); + break; + } + else if (Status == AE_AML_NO_RESOURCE_END_TAG) + { + AcpiOsPrintf ("/**** Is ResourceTemplate, but EndTag not at buffer end ****/ "); + } + } + + if (AcpiDmIsUnicodeBuffer (Op)) + { + Op->Common.DisasmOpcode = ACPI_DASM_UNICODE; + AcpiOsPrintf ("Unicode ("); + } + else if (AcpiDmIsStringBuffer (Op)) + { + Op->Common.DisasmOpcode = ACPI_DASM_STRING; + AcpiOsPrintf ("Buffer"); + } + else + { + Op->Common.DisasmOpcode = ACPI_DASM_BUFFER; + AcpiOsPrintf ("Buffer"); + } + break; + + + case AML_INT_STATICSTRING_OP: + + if (Op->Common.Value.String) + { + AcpiOsPrintf ("%s", Op->Common.Value.String); + } + else + { + AcpiOsPrintf ("\"\""); + } + break; + + + case AML_INT_NAMEPATH_OP: + + AcpiDmNamestring (Op->Common.Value.Name); + break; + + + case AML_INT_NAMEDFIELD_OP: + + Length = AcpiDmDumpName (Op->Named.Name); + AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length), " ", + (UINT32) Op->Common.Value.Integer); + AcpiDmCommaIfFieldMember (Op); + + Info->BitOffset += (UINT32) Op->Common.Value.Integer; + break; + + + case AML_INT_RESERVEDFIELD_OP: + + /* Offset() -- Must account for previous offsets */ + + Offset = (UINT32) Op->Common.Value.Integer; + Info->BitOffset += Offset; + + if (Info->BitOffset % 8 == 0) + { + AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset)); + } + else + { + AcpiOsPrintf (" , %u", Offset); + } + + AcpiDmCommaIfFieldMember (Op); + break; + + + case AML_INT_ACCESSFIELD_OP: + case AML_INT_EXTACCESSFIELD_OP: + + AcpiOsPrintf ("AccessAs (%s, ", + AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]); + + AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8)); + + if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP) + { + AcpiOsPrintf (" (0x%2.2X)", (unsigned) ((Op->Common.Value.Integer >> 16) & 0xFF)); + } + + AcpiOsPrintf (")"); + AcpiDmCommaIfFieldMember (Op); + break; + + + case AML_INT_CONNECTION_OP: + + /* + * Two types of Connection() - one with a buffer object, the + * other with a namestring that points to a buffer object. + */ + AcpiOsPrintf ("Connection ("); + Child = Op->Common.Value.Arg; + + if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP) + { + AcpiOsPrintf ("\n"); + + Aml = Child->Named.Data; + Length = (UINT32) Child->Common.Value.Integer; + + Info->Level += 1; + Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; + AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length); + + Info->Level -= 1; + AcpiDmIndent (Info->Level); + } + else + { + AcpiDmNamestring (Child->Common.Value.Name); + } + + AcpiOsPrintf (")"); + AcpiDmCommaIfFieldMember (Op); + AcpiOsPrintf ("\n"); + + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */ + Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + break; + + case AML_INT_BYTELIST_OP: + + AcpiDmByteList (Info, Op); + break; + + + case AML_INT_METHODCALL_OP: + + Op = AcpiPsGetDepthNext (NULL, Op); + Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + + AcpiDmNamestring (Op->Common.Value.Name); + break; + + + default: + + /* Just get the opcode name and print it */ + + AcpiOsPrintf ("%s", OpInfo->Name); + + +#ifdef ACPI_DEBUGGER + + if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) && + (WalkState) && + (WalkState->Results) && + (WalkState->ResultCount)) + { + AcpiDmDecodeInternalObject ( + WalkState->Results->Results.ObjDesc [ + (WalkState->ResultCount - 1) % + ACPI_RESULTS_FRAME_OBJ_NUM]); + } +#endif + + break; + } +} + +#endif /* ACPI_DISASSEMBLER */ diff --git a/source/components/disassembler/dmresrc.c b/source/components/disassembler/dmresrc.c new file mode 100644 index 000000000000..9c07bf7e9462 --- /dev/null +++ b/source/components/disassembler/dmresrc.c @@ -0,0 +1,434 @@ +/******************************************************************************* + * + * Module Name: dmresrc.c - Resource Descriptor disassembly + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdisasm.h" + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbresrc") + + +/* Dispatch tables for Resource disassembly functions */ + +static ACPI_RESOURCE_HANDLER AcpiGbl_DmResourceDispatch [] = +{ + /* Small descriptors */ + + NULL, /* 0x00, Reserved */ + NULL, /* 0x01, Reserved */ + NULL, /* 0x02, Reserved */ + NULL, /* 0x03, Reserved */ + AcpiDmIrqDescriptor, /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */ + AcpiDmDmaDescriptor, /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */ + AcpiDmStartDependentDescriptor, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ + AcpiDmEndDependentDescriptor, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ + AcpiDmIoDescriptor, /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */ + AcpiDmFixedIoDescriptor, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */ + AcpiDmFixedDmaDescriptor, /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */ + NULL, /* 0x0B, Reserved */ + NULL, /* 0x0C, Reserved */ + NULL, /* 0x0D, Reserved */ + AcpiDmVendorSmallDescriptor, /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */ + NULL, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */ + + /* Large descriptors */ + + NULL, /* 0x00, Reserved */ + AcpiDmMemory24Descriptor, /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */ + AcpiDmGenericRegisterDescriptor,/* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ + NULL, /* 0x03, Reserved */ + AcpiDmVendorLargeDescriptor, /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */ + AcpiDmMemory32Descriptor, /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */ + AcpiDmFixedMemory32Descriptor, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */ + AcpiDmDwordDescriptor, /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */ + AcpiDmWordDescriptor, /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */ + AcpiDmInterruptDescriptor, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */ + AcpiDmQwordDescriptor, /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */ + AcpiDmExtendedDescriptor, /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */ + AcpiDmGpioDescriptor, /* 0x0C, ACPI_RESOURCE_NAME_GPIO */ + NULL, /* 0x0D, Reserved */ + AcpiDmSerialBusDescriptor /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS */ +}; + + +/* Only used for single-threaded applications */ +/* TBD: remove when name is passed as parameter to the dump functions */ + +static UINT32 ResourceName; + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDescriptorName + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Emit a name for the descriptor if one is present (indicated + * by the name being changed from the default name.) A name is only + * emitted if a reference to the descriptor has been made somewhere + * in the original ASL code. + * + ******************************************************************************/ + +void +AcpiDmDescriptorName ( + void) +{ + + if (ResourceName == ACPI_DEFAULT_RESNAME) + { + return; + } + + AcpiOsPrintf ("%4.4s", (char *) &ResourceName); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpInteger* + * + * PARAMETERS: Value - Value to emit + * Name - Associated name (emitted as a comment) + * + * RETURN: None + * + * DESCRIPTION: Integer output helper functions + * + ******************************************************************************/ + +void +AcpiDmDumpInteger8 ( + UINT8 Value, + char *Name) +{ + AcpiOsPrintf ("0x%2.2X, // %s\n", Value, Name); +} + +void +AcpiDmDumpInteger16 ( + UINT16 Value, + char *Name) +{ + AcpiOsPrintf ("0x%4.4X, // %s\n", Value, Name); +} + +void +AcpiDmDumpInteger32 ( + UINT32 Value, + char *Name) +{ + AcpiOsPrintf ("0x%8.8X, // %s\n", Value, Name); +} + +void +AcpiDmDumpInteger64 ( + UINT64 Value, + char *Name) +{ + AcpiOsPrintf ("0x%8.8X%8.8X, // %s\n", ACPI_FORMAT_UINT64 (Value), Name); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmBitList + * + * PARAMETERS: Mask - 16-bit value corresponding to 16 interrupt + * or DMA values + * + * RETURN: None + * + * DESCRIPTION: Dump a bit mask as a list of individual interrupt/DMA levels. + * + ******************************************************************************/ + +void +AcpiDmBitList ( + UINT16 Mask) +{ + UINT32 i; + BOOLEAN Previous = FALSE; + + + /* Open the initializer list */ + + AcpiOsPrintf ("{"); + + /* Examine each bit */ + + for (i = 0; i < 16; i++) + { + /* Only interested in bits that are set to 1 */ + + if (Mask & 1) + { + if (Previous) + { + AcpiOsPrintf (","); + } + Previous = TRUE; + AcpiOsPrintf ("%u", i); + } + + Mask >>= 1; + } + + /* Close list */ + + AcpiOsPrintf ("}\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmResourceTemplate + * + * PARAMETERS: Info - Curent parse tree walk info + * ByteData - Pointer to the byte list data + * ByteCount - Length of the byte list + * + * RETURN: None + * + * DESCRIPTION: Dump the contents of a Resource Template containing a set of + * Resource Descriptors. + * + ******************************************************************************/ + +void +AcpiDmResourceTemplate ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op, + UINT8 *ByteData, + UINT32 ByteCount) +{ + ACPI_STATUS Status; + UINT32 CurrentByteOffset; + UINT8 ResourceType; + UINT32 ResourceLength; + void *Aml; + UINT32 Level; + BOOLEAN DependentFns = FALSE; + UINT8 ResourceIndex; + ACPI_NAMESPACE_NODE *Node; + + + Level = Info->Level; + ResourceName = ACPI_DEFAULT_RESNAME; + Node = Op->Common.Node; + if (Node) + { + Node = Node->Child; + } + + for (CurrentByteOffset = 0; CurrentByteOffset < ByteCount;) + { + Aml = &ByteData[CurrentByteOffset]; + + /* Get the descriptor type and length */ + + ResourceType = AcpiUtGetResourceType (Aml); + ResourceLength = AcpiUtGetResourceLength (Aml); + + /* Validate the Resource Type and Resource Length */ + + Status = AcpiUtValidateResource (Aml, &ResourceIndex); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("/*** Could not validate Resource, type (%X) %s***/\n", + ResourceType, AcpiFormatException (Status)); + return; + } + + /* Point to next descriptor */ + + CurrentByteOffset += AcpiUtGetDescriptorLength (Aml); + + /* Descriptor pre-processing */ + + switch (ResourceType) + { + case ACPI_RESOURCE_NAME_START_DEPENDENT: + + /* Finish a previous StartDependentFns */ + + if (DependentFns) + { + Level--; + AcpiDmIndent (Level); + AcpiOsPrintf ("}\n"); + } + break; + + case ACPI_RESOURCE_NAME_END_DEPENDENT: + + Level--; + DependentFns = FALSE; + break; + + case ACPI_RESOURCE_NAME_END_TAG: + + /* Normal exit, the resource list is finished */ + + if (DependentFns) + { + /* + * Close an open StartDependentDescriptor. This indicates a + * missing EndDependentDescriptor. + */ + Level--; + DependentFns = FALSE; + + /* Go ahead and insert EndDependentFn() */ + + AcpiDmEndDependentDescriptor (Aml, ResourceLength, Level); + + AcpiDmIndent (Level); + AcpiOsPrintf ( + "/*** Disassembler: inserted missing EndDependentFn () ***/\n"); + } + return; + + default: + break; + } + + /* Disassemble the resource structure */ + + if (Node) + { + ResourceName = Node->Name.Integer; + Node = Node->Peer; + } + + AcpiGbl_DmResourceDispatch [ResourceIndex] ( + Aml, ResourceLength, Level); + + /* Descriptor post-processing */ + + if (ResourceType == ACPI_RESOURCE_NAME_START_DEPENDENT) + { + DependentFns = TRUE; + Level++; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIsResourceTemplate + * + * PARAMETERS: Op - Buffer Op to be examined + * + * RETURN: Status. AE_OK if valid template + * + * DESCRIPTION: Walk a byte list to determine if it consists of a valid set + * of resource descriptors. Nothing is output. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDmIsResourceTemplate ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *NextOp; + UINT8 *Aml; + UINT8 *EndAml; + ACPI_SIZE Length; + + + /* This op must be a buffer */ + + if (Op->Common.AmlOpcode != AML_BUFFER_OP) + { + return (AE_TYPE); + } + + /* Get the ByteData list and length */ + + NextOp = Op->Common.Value.Arg; + NextOp = NextOp->Common.Next; + if (!NextOp) + { + return (AE_TYPE); + } + + Aml = NextOp->Named.Data; + Length = (ACPI_SIZE) NextOp->Common.Value.Integer; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + Status = AcpiUtWalkAmlResources (Aml, Length, NULL, &EndAml); + if (ACPI_FAILURE (Status)) + { + return (AE_TYPE); + } + + /* + * For the resource template to be valid, one EndTag must appear + * at the very end of the ByteList, not before. (For proper disassembly + * of a ResourceTemplate, the buffer must not have any extra data after + * the EndTag.) + */ + if ((Aml + Length - sizeof (AML_RESOURCE_END_TAG)) != EndAml) + { + return (AE_AML_NO_RESOURCE_END_TAG); + } + + /* + * All resource descriptors are valid, therefore this list appears + * to be a valid resource template + */ + return (AE_OK); +} + +#endif diff --git a/source/components/disassembler/dmresrcl.c b/source/components/disassembler/dmresrcl.c new file mode 100644 index 000000000000..ed78b31c707b --- /dev/null +++ b/source/components/disassembler/dmresrcl.c @@ -0,0 +1,1052 @@ +/******************************************************************************* + * + * Module Name: dmresrcl.c - "Large" Resource Descriptor disassembly + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbresrcl") + + +/* Common names for address and memory descriptors */ + +static char *AcpiDmAddressNames[] = +{ + "Granularity", + "Range Minimum", + "Range Maximum", + "Translation Offset", + "Length" +}; + +static char *AcpiDmMemoryNames[] = +{ + "Range Minimum", + "Range Maximum", + "Alignment", + "Length" +}; + + +/* Local prototypes */ + +static void +AcpiDmSpaceFlags ( + UINT8 Flags); + +static void +AcpiDmIoFlags ( + UINT8 Flags); + +static void +AcpiDmIoFlags2 ( + UINT8 SpecificFlags); + +static void +AcpiDmMemoryFlags ( + UINT8 Flags, + UINT8 SpecificFlags); + +static void +AcpiDmMemoryFlags2 ( + UINT8 SpecificFlags); + +static void +AcpiDmResourceSource ( + AML_RESOURCE *Resource, + ACPI_SIZE MinimumLength, + UINT32 Length); + +static void +AcpiDmAddressFields ( + void *Source, + UINT8 Type, + UINT32 Level); + +static void +AcpiDmAddressPrefix ( + UINT8 Type); + +static void +AcpiDmAddressCommon ( + AML_RESOURCE *Resource, + UINT8 Type, + UINT32 Level); + +static void +AcpiDmAddressFlags ( + AML_RESOURCE *Resource); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMemoryFields + * + * PARAMETERS: Source - Pointer to the contiguous data fields + * Type - 16 or 32 (bit) + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode fields common to Memory24 and Memory32 descriptors + * + ******************************************************************************/ + +static void +AcpiDmMemoryFields ( + void *Source, + UINT8 Type, + UINT32 Level) +{ + UINT32 i; + + + for (i = 0; i < 4; i++) + { + AcpiDmIndent (Level + 1); + + switch (Type) + { + case 16: + AcpiDmDumpInteger16 (ACPI_CAST_PTR (UINT16, Source)[i], + AcpiDmMemoryNames[i]); + break; + + case 32: + AcpiDmDumpInteger32 (ACPI_CAST_PTR (UINT32, Source)[i], + AcpiDmMemoryNames[i]); + break; + + default: + return; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddressFields + * + * PARAMETERS: Source - Pointer to the contiguous data fields + * Type - 16, 32, or 64 (bit) + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode fields common to address descriptors + * + ******************************************************************************/ + +static void +AcpiDmAddressFields ( + void *Source, + UINT8 Type, + UINT32 Level) +{ + UINT32 i; + + + AcpiOsPrintf ("\n"); + + for (i = 0; i < 5; i++) + { + AcpiDmIndent (Level + 1); + + switch (Type) + { + case 16: + AcpiDmDumpInteger16 (ACPI_CAST_PTR (UINT16, Source)[i], + AcpiDmAddressNames[i]); + break; + + case 32: + AcpiDmDumpInteger32 (ACPI_CAST_PTR (UINT32, Source)[i], + AcpiDmAddressNames[i]); + break; + + case 64: + AcpiDmDumpInteger64 (ACPI_CAST_PTR (UINT64, Source)[i], + AcpiDmAddressNames[i]); + break; + + default: + return; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddressPrefix + * + * PARAMETERS: Type - Descriptor type + * + * RETURN: None + * + * DESCRIPTION: Emit name prefix representing the address descriptor type + * + ******************************************************************************/ + +static void +AcpiDmAddressPrefix ( + UINT8 Type) +{ + + switch (Type) + { + case ACPI_RESOURCE_TYPE_ADDRESS16: + AcpiOsPrintf ("Word"); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS32: + AcpiOsPrintf ("DWord"); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS64: + AcpiOsPrintf ("QWord"); + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + AcpiOsPrintf ("Extended"); + break; + + default: + return; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddressCommon + * + * PARAMETERS: Resource - Raw AML descriptor + * Type - Descriptor type + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Emit common name and flag fields common to address descriptors + * + ******************************************************************************/ + +static void +AcpiDmAddressCommon ( + AML_RESOURCE *Resource, + UINT8 Type, + UINT32 Level) +{ + UINT8 ResourceType; + UINT8 SpecificFlags; + UINT8 Flags; + + + ResourceType = Resource->Address.ResourceType; + SpecificFlags = Resource->Address.SpecificFlags; + Flags = Resource->Address.Flags; + + AcpiDmIndent (Level); + + /* Validate ResourceType */ + + if ((ResourceType > 2) && (ResourceType < 0xC0)) + { + AcpiOsPrintf ("/**** Invalid Resource Type: 0x%X ****/", ResourceType); + return; + } + + /* Prefix is either Word, DWord, QWord, or Extended */ + + AcpiDmAddressPrefix (Type); + + /* Resource Types above 0xC0 are vendor-defined */ + + if (ResourceType > 2) + { + AcpiOsPrintf ("Space (0x%2.2X, ", ResourceType); + AcpiDmSpaceFlags (Flags); + AcpiOsPrintf (" 0x%2.2X,", SpecificFlags); + return; + } + + /* This is either a Memory, IO, or BusNumber descriptor (0,1,2) */ + + AcpiOsPrintf ("%s (", AcpiGbl_WordDecode [ResourceType & 0x3]); + + /* Decode the general and type-specific flags */ + + if (ResourceType == ACPI_MEMORY_RANGE) + { + AcpiDmMemoryFlags (Flags, SpecificFlags); + } + else /* IO range or BusNumberRange */ + { + AcpiDmIoFlags (Flags); + if (ResourceType == ACPI_IO_RANGE) + { + AcpiOsPrintf (" %s,", AcpiGbl_RngDecode [SpecificFlags & 0x3]); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddressFlags + * + * PARAMETERS: Resource - Raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Emit flags common to address descriptors + * + ******************************************************************************/ + +static void +AcpiDmAddressFlags ( + AML_RESOURCE *Resource) +{ + + if (Resource->Address.ResourceType == ACPI_IO_RANGE) + { + AcpiDmIoFlags2 (Resource->Address.SpecificFlags); + } + else if (Resource->Address.ResourceType == ACPI_MEMORY_RANGE) + { + AcpiDmMemoryFlags2 (Resource->Address.SpecificFlags); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmSpaceFlags + * + * PARAMETERS: Flags - Flag byte to be decoded + * + * RETURN: None + * + * DESCRIPTION: Decode the flags specific to Space Address space descriptors + * + ******************************************************************************/ + +static void +AcpiDmSpaceFlags ( + UINT8 Flags) +{ + + AcpiOsPrintf ("%s, %s, %s, %s,", + AcpiGbl_ConsumeDecode [(Flags & 1)], + AcpiGbl_DecDecode [(Flags & 0x2) >> 1], + AcpiGbl_MinDecode [(Flags & 0x4) >> 2], + AcpiGbl_MaxDecode [(Flags & 0x8) >> 3]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIoFlags + * + * PARAMETERS: Flags - Flag byte to be decoded + * + * RETURN: None + * + * DESCRIPTION: Decode the flags specific to IO Address space descriptors + * + ******************************************************************************/ + +static void +AcpiDmIoFlags ( + UINT8 Flags) +{ + AcpiOsPrintf ("%s, %s, %s, %s,", + AcpiGbl_ConsumeDecode [(Flags & 1)], + AcpiGbl_MinDecode [(Flags & 0x4) >> 2], + AcpiGbl_MaxDecode [(Flags & 0x8) >> 3], + AcpiGbl_DecDecode [(Flags & 0x2) >> 1]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIoFlags2 + * + * PARAMETERS: SpecificFlags - "Specific" flag byte to be decoded + * + * RETURN: None + * + * DESCRIPTION: Decode the flags specific to IO Address space descriptors + * + ******************************************************************************/ + +static void +AcpiDmIoFlags2 ( + UINT8 SpecificFlags) +{ + + AcpiOsPrintf (", %s", + AcpiGbl_TtpDecode [(SpecificFlags & 0x10) >> 4]); + + /* TRS is only used if TTP is TypeTranslation */ + + if (SpecificFlags & 0x10) + { + AcpiOsPrintf (", %s", + AcpiGbl_TrsDecode [(SpecificFlags & 0x20) >> 5]); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMemoryFlags + * + * PARAMETERS: Flags - Flag byte to be decoded + * SpecificFlags - "Specific" flag byte to be decoded + * + * RETURN: None + * + * DESCRIPTION: Decode flags specific to Memory Address Space descriptors + * + ******************************************************************************/ + +static void +AcpiDmMemoryFlags ( + UINT8 Flags, + UINT8 SpecificFlags) +{ + + AcpiOsPrintf ("%s, %s, %s, %s, %s, %s,", + AcpiGbl_ConsumeDecode [(Flags & 1)], + AcpiGbl_DecDecode [(Flags & 0x2) >> 1], + AcpiGbl_MinDecode [(Flags & 0x4) >> 2], + AcpiGbl_MaxDecode [(Flags & 0x8) >> 3], + AcpiGbl_MemDecode [(SpecificFlags & 0x6) >> 1], + AcpiGbl_RwDecode [(SpecificFlags & 0x1)]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMemoryFlags2 + * + * PARAMETERS: SpecificFlags - "Specific" flag byte to be decoded + * + * RETURN: None + * + * DESCRIPTION: Decode flags specific to Memory Address Space descriptors + * + ******************************************************************************/ + +static void +AcpiDmMemoryFlags2 ( + UINT8 SpecificFlags) +{ + + AcpiOsPrintf (", %s, %s", + AcpiGbl_MtpDecode [(SpecificFlags & 0x18) >> 3], + AcpiGbl_TtpDecode [(SpecificFlags & 0x20) >> 5]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmResourceSource + * + * PARAMETERS: Resource - Raw AML descriptor + * MinimumLength - descriptor length without optional fields + * ResourceLength + * + * RETURN: None + * + * DESCRIPTION: Dump optional ResourceSource fields of an address descriptor + * + ******************************************************************************/ + +static void +AcpiDmResourceSource ( + AML_RESOURCE *Resource, + ACPI_SIZE MinimumTotalLength, + UINT32 ResourceLength) +{ + UINT8 *AmlResourceSource; + UINT32 TotalLength; + + + TotalLength = ResourceLength + sizeof (AML_RESOURCE_LARGE_HEADER); + + /* Check if the optional ResourceSource fields are present */ + + if (TotalLength <= MinimumTotalLength) + { + /* The two optional fields are not used */ + + AcpiOsPrintf (",, "); + return; + } + + /* Get a pointer to the ResourceSource */ + + AmlResourceSource = ACPI_ADD_PTR (UINT8, Resource, MinimumTotalLength); + + /* + * Always emit the ResourceSourceIndex (Byte) + * + * NOTE: Some ASL compilers always create a 0 byte (in the AML) for the + * Index even if the String does not exist. Although this is in violation + * of the ACPI specification, it is very important to emit ASL code that + * can be compiled back to the identical AML. There may be fields and/or + * indexes into the resource template buffer that are compiled to absolute + * offsets, and these will be broken if the AML length is changed. + */ + AcpiOsPrintf ("0x%2.2X,", (UINT32) AmlResourceSource[0]); + + /* Make sure that the ResourceSource string exists before dumping it */ + + if (TotalLength > (MinimumTotalLength + 1)) + { + AcpiOsPrintf (" "); + AcpiUtPrintString ((char *) &AmlResourceSource[1], ACPI_UINT8_MAX); + } + + AcpiOsPrintf (", "); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmWordDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Word Address Space descriptor + * + ******************************************************************************/ + +void +AcpiDmWordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump resource name and flags */ + + AcpiDmAddressCommon (Resource, ACPI_RESOURCE_TYPE_ADDRESS16, Level); + + /* Dump the 5 contiguous WORD values */ + + AcpiDmAddressFields (&Resource->Address16.Granularity, 16, Level); + + /* The ResourceSource fields are optional */ + + AcpiDmIndent (Level + 1); + AcpiDmResourceSource (Resource, sizeof (AML_RESOURCE_ADDRESS16), Length); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + + /* Type-specific flags */ + + AcpiDmAddressFlags (Resource); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDwordDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a DWord Address Space descriptor + * + ******************************************************************************/ + +void +AcpiDmDwordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump resource name and flags */ + + AcpiDmAddressCommon (Resource, ACPI_RESOURCE_TYPE_ADDRESS32, Level); + + /* Dump the 5 contiguous DWORD values */ + + AcpiDmAddressFields (&Resource->Address32.Granularity, 32, Level); + + /* The ResourceSource fields are optional */ + + AcpiDmIndent (Level + 1); + AcpiDmResourceSource (Resource, sizeof (AML_RESOURCE_ADDRESS32), Length); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + + /* Type-specific flags */ + + AcpiDmAddressFlags (Resource); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmQwordDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a QWord Address Space descriptor + * + ******************************************************************************/ + +void +AcpiDmQwordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump resource name and flags */ + + AcpiDmAddressCommon (Resource, ACPI_RESOURCE_TYPE_ADDRESS64, Level); + + /* Dump the 5 contiguous QWORD values */ + + AcpiDmAddressFields (&Resource->Address64.Granularity, 64, Level); + + /* The ResourceSource fields are optional */ + + AcpiDmIndent (Level + 1); + AcpiDmResourceSource (Resource, sizeof (AML_RESOURCE_ADDRESS64), Length); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + + /* Type-specific flags */ + + AcpiDmAddressFlags (Resource); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmExtendedDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Extended Address Space descriptor + * + ******************************************************************************/ + +void +AcpiDmExtendedDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump resource name and flags */ + + AcpiDmAddressCommon (Resource, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, Level); + + /* Dump the 5 contiguous QWORD values */ + + AcpiDmAddressFields (&Resource->ExtAddress64.Granularity, 64, Level); + + /* Extra field for this descriptor only */ + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger64 (Resource->ExtAddress64.TypeSpecific, + "Type-Specific Attributes"); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + + /* Type-specific flags */ + + AcpiDmAddressFlags (Resource); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMemory24Descriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Memory24 descriptor + * + ******************************************************************************/ + +void +AcpiDmMemory24Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump name and read/write flag */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("Memory24 (%s,\n", + AcpiGbl_RwDecode [Resource->Memory24.Flags & 1]); + + /* Dump the 4 contiguous WORD values */ + + AcpiDmMemoryFields (&Resource->Memory24.Minimum, 16, Level); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmMemory32Descriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Memory32 descriptor + * + ******************************************************************************/ + +void +AcpiDmMemory32Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump name and read/write flag */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("Memory32 (%s,\n", + AcpiGbl_RwDecode [Resource->Memory32.Flags & 1]); + + /* Dump the 4 contiguous DWORD values */ + + AcpiDmMemoryFields (&Resource->Memory32.Minimum, 32, Level); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFixedMemory32Descriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Fixed Memory32 descriptor + * + ******************************************************************************/ + +void +AcpiDmFixedMemory32Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump name and read/write flag */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("Memory32Fixed (%s,\n", + AcpiGbl_RwDecode [Resource->FixedMemory32.Flags & 1]); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger32 (Resource->FixedMemory32.Address, "Address Base"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger32 (Resource->FixedMemory32.AddressLength, "Address Length"); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGenericRegisterDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Generic Register descriptor + * + ******************************************************************************/ + +void +AcpiDmGenericRegisterDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("Register ("); + AcpiDmAddressSpace (Resource->GenericReg.AddressSpaceId); + AcpiOsPrintf ("\n"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger8 (Resource->GenericReg.BitWidth, "Bit Width"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger8 (Resource->GenericReg.BitOffset, "Bit Offset"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger64 (Resource->GenericReg.Address, "Address"); + + /* Optional field for ACPI 3.0 */ + + AcpiDmIndent (Level + 1); + if (Resource->GenericReg.AccessSize) + { + AcpiOsPrintf ("0x%2.2X, // %s\n", + Resource->GenericReg.AccessSize, "Access Size"); + AcpiDmIndent (Level + 1); + } + else + { + AcpiOsPrintf (","); + } + + /* DescriptorName was added for ACPI 3.0+ */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmInterruptDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a extended Interrupt descriptor + * + ******************************************************************************/ + +void +AcpiDmInterruptDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + UINT32 i; + + + AcpiDmIndent (Level); + AcpiOsPrintf ("Interrupt (%s, %s, %s, %s, ", + AcpiGbl_ConsumeDecode [(Resource->ExtendedIrq.Flags & 1)], + AcpiGbl_HeDecode [(Resource->ExtendedIrq.Flags >> 1) & 1], + AcpiGbl_LlDecode [(Resource->ExtendedIrq.Flags >> 2) & 1], + AcpiGbl_ShrDecode [(Resource->ExtendedIrq.Flags >> 3) & 1]); + + /* + * The ResourceSource fields are optional and appear after the interrupt + * list. Must compute length based on length of the list. First xrupt + * is included in the struct (reason for -1 below) + */ + AcpiDmResourceSource (Resource, + sizeof (AML_RESOURCE_EXTENDED_IRQ) + + ((UINT32) Resource->ExtendedIrq.InterruptCount - 1) * sizeof (UINT32), + Resource->ExtendedIrq.ResourceLength); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); + + /* Dump the interrupt list */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("{\n"); + for (i = 0; i < Resource->ExtendedIrq.InterruptCount; i++) + { + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%8.8X,\n", + (UINT32) Resource->ExtendedIrq.Interrupts[i]); + } + + AcpiDmIndent (Level); + AcpiOsPrintf ("}\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmVendorCommon + * + * PARAMETERS: Name - Descriptor name suffix + * ByteData - Pointer to the vendor byte data + * Length - Length of the byte data + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Vendor descriptor, both Large and Small + * + ******************************************************************************/ + +void +AcpiDmVendorCommon ( + char *Name, + UINT8 *ByteData, + UINT32 Length, + UINT32 Level) +{ + + /* Dump macro name */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("Vendor%s (", Name); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (") // Length = 0x%.2X\n", Length); + + /* Dump the vendor bytes */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("{\n"); + + AcpiDmDisasmByteList (Level + 1, ByteData, Length); + + AcpiDmIndent (Level); + AcpiOsPrintf ("}\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmVendorLargeDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Vendor Large descriptor + * + ******************************************************************************/ + +void +AcpiDmVendorLargeDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmVendorCommon ("Long ", + ACPI_ADD_PTR (UINT8, Resource, sizeof (AML_RESOURCE_LARGE_HEADER)), + Length, Level); +} + +#endif diff --git a/source/components/disassembler/dmresrcl2.c b/source/components/disassembler/dmresrcl2.c new file mode 100644 index 000000000000..e79307ee72d0 --- /dev/null +++ b/source/components/disassembler/dmresrcl2.c @@ -0,0 +1,700 @@ +/******************************************************************************* + * + * Module Name: dmresrcl2.c - "Large" Resource Descriptor disassembly (#2) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbresrcl2") + +/* Local prototypes */ + +static void +AcpiDmI2cSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +static void +AcpiDmSpiSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +static void +AcpiDmUartSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +static void +AcpiDmGpioCommon ( + AML_RESOURCE *Resource, + UINT32 Level); + +static void +AcpiDmDumpRawDataBuffer ( + UINT8 *Buffer, + UINT32 Length, + UINT32 Level); + + +/* Dispatch table for the serial bus descriptors */ + +static ACPI_RESOURCE_HANDLER SerialBusResourceDispatch [] = +{ + NULL, + AcpiDmI2cSerialBusDescriptor, + AcpiDmSpiSerialBusDescriptor, + AcpiDmUartSerialBusDescriptor +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpRawDataBuffer + * + * PARAMETERS: Buffer - Pointer to the data bytes + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Dump a data buffer as a RawDataBuffer() object. Used for + * vendor data bytes. + * + ******************************************************************************/ + +static void +AcpiDmDumpRawDataBuffer ( + UINT8 *Buffer, + UINT32 Length, + UINT32 Level) +{ + UINT32 Index; + UINT32 i; + UINT32 j; + + + if (!Length) + { + return; + } + + AcpiOsPrintf ("RawDataBuffer (0x%.2X) // Vendor Data", Length); + + AcpiOsPrintf ("\n"); + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("{\n"); + AcpiDmIndent (Level + 2); + + for (i = 0; i < Length;) + { + for (j = 0; j < 8; j++) + { + Index = i + j; + if (Index >= Length) + { + goto Finish; + } + + AcpiOsPrintf ("0x%2.2X", Buffer[Index]); + if ((Index + 1) >= Length) + { + goto Finish; + } + + AcpiOsPrintf (", "); + } + AcpiOsPrintf ("\n"); + AcpiDmIndent (Level + 2); + + i += 8; + } + +Finish: + AcpiOsPrintf ("\n"); + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("}"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGpioCommon + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode common parts of a GPIO Interrupt descriptor + * + ******************************************************************************/ + +static void +AcpiDmGpioCommon ( + AML_RESOURCE *Resource, + UINT32 Level) +{ + UINT32 PinCount; + UINT16 *PinList; + UINT8 *VendorData; + UINT32 i; + + + /* ResourceSource, ResourceSourceIndex, ResourceType */ + + AcpiDmIndent (Level + 1); + if (Resource->Gpio.ResSourceOffset) + { + AcpiUtPrintString ( + ACPI_ADD_PTR (char, Resource, Resource->Gpio.ResSourceOffset), + ACPI_UINT8_MAX); + } + + AcpiOsPrintf (", "); + AcpiOsPrintf ("0x%2.2X, ", Resource->Gpio.ResSourceIndex); + AcpiOsPrintf ("%s, ", + AcpiGbl_ConsumeDecode [(Resource->Gpio.Flags & 1)]); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (","); + + /* Dump the vendor data */ + + if (Resource->Gpio.VendorOffset) + { + AcpiOsPrintf ("\n"); + AcpiDmIndent (Level + 1); + VendorData = ACPI_ADD_PTR (UINT8, Resource, + Resource->Gpio.VendorOffset); + + AcpiDmDumpRawDataBuffer (VendorData, + Resource->Gpio.VendorLength, Level); + } + + AcpiOsPrintf (")\n"); + + /* Dump the interrupt list */ + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("{ // Pin list\n"); + + PinCount = ((UINT32) (Resource->Gpio.ResSourceOffset - + Resource->Gpio.PinTableOffset)) / + sizeof (UINT16); + + PinList = (UINT16 *) ACPI_ADD_PTR (char, Resource, + Resource->Gpio.PinTableOffset); + + for (i = 0; i < PinCount; i++) + { + AcpiDmIndent (Level + 2); + AcpiOsPrintf ("0x%4.4X%s\n", PinList[i], ((i + 1) < PinCount) ? "," : ""); + } + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("}\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGpioIntDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a GPIO Interrupt descriptor + * + ******************************************************************************/ + +static void +AcpiDmGpioIntDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump the GpioInt-specific portion of the descriptor */ + + /* EdgeLevel, ActiveLevel, Shared */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("GpioInt (%s, %s, %s, ", + AcpiGbl_HeDecode [(Resource->Gpio.IntFlags & 1)], + AcpiGbl_LlDecode [(Resource->Gpio.IntFlags >> 1) & 1], + AcpiGbl_ShrDecode [(Resource->Gpio.IntFlags >> 3) & 1]); + + /* PinConfig, DebounceTimeout */ + + if (Resource->Gpio.PinConfig <= 3) + { + AcpiOsPrintf ("%s, ", + AcpiGbl_PpcDecode[Resource->Gpio.PinConfig]); + } + else + { + AcpiOsPrintf ("0x%2.2X, ", Resource->Gpio.PinConfig); + } + AcpiOsPrintf ("0x%4.4X,\n", Resource->Gpio.DebounceTimeout); + + /* Dump the GpioInt/GpioIo common portion of the descriptor */ + + AcpiDmGpioCommon (Resource, Level); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGpioIoDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a GPIO Interrupt descriptor + * + ******************************************************************************/ + +static void +AcpiDmGpioIoDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + /* Dump the GpioIo-specific portion of the descriptor */ + + /* Shared, PinConfig */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("GpioIo (%s, ", + AcpiGbl_ShrDecode [(Resource->Gpio.IntFlags >> 3) & 1]); + + if (Resource->Gpio.PinConfig <= 3) + { + AcpiOsPrintf ("%s, ", + AcpiGbl_PpcDecode[Resource->Gpio.PinConfig]); + } + else + { + AcpiOsPrintf ("0x%2.2X, ", Resource->Gpio.PinConfig); + } + + /* DebounceTimeout, DriveStrength, IoRestriction */ + + AcpiOsPrintf ("0x%4.4X, ", Resource->Gpio.DebounceTimeout); + AcpiOsPrintf ("0x%4.4X, ", Resource->Gpio.DriveStrength); + AcpiOsPrintf ("%s,\n", + AcpiGbl_IorDecode [Resource->Gpio.IntFlags & 3]); + + /* Dump the GpioInt/GpioIo common portion of the descriptor */ + + AcpiDmGpioCommon (Resource, Level); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmGpioDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a GpioInt/GpioIo GPIO Interrupt/IO descriptor + * + ******************************************************************************/ + +void +AcpiDmGpioDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + UINT8 ConnectionType; + + + ConnectionType = Resource->Gpio.ConnectionType; + + switch (ConnectionType) + { + case AML_RESOURCE_GPIO_TYPE_INT: + AcpiDmGpioIntDescriptor (Resource, Length, Level); + break; + + case AML_RESOURCE_GPIO_TYPE_IO: + AcpiDmGpioIoDescriptor (Resource, Length, Level); + break; + + default: + AcpiOsPrintf ("Unknown GPIO type\n"); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpSerialBusVendorData + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * + * RETURN: None + * + * DESCRIPTION: Dump optional serial bus vendor data + * + ******************************************************************************/ + +static void +AcpiDmDumpSerialBusVendorData ( + AML_RESOURCE *Resource, + UINT32 Level) +{ + UINT8 *VendorData; + UINT32 VendorLength; + + + /* Get the (optional) vendor data and length */ + + switch (Resource->CommonSerialBus.Type) + { + case AML_RESOURCE_I2C_SERIALBUSTYPE: + + VendorLength = Resource->CommonSerialBus.TypeDataLength - + AML_RESOURCE_I2C_MIN_DATA_LEN; + + VendorData = ACPI_ADD_PTR (UINT8, Resource, + sizeof (AML_RESOURCE_I2C_SERIALBUS)); + break; + + case AML_RESOURCE_SPI_SERIALBUSTYPE: + + VendorLength = Resource->CommonSerialBus.TypeDataLength - + AML_RESOURCE_SPI_MIN_DATA_LEN; + + VendorData = ACPI_ADD_PTR (UINT8, Resource, + sizeof (AML_RESOURCE_SPI_SERIALBUS)); + break; + + case AML_RESOURCE_UART_SERIALBUSTYPE: + + VendorLength = Resource->CommonSerialBus.TypeDataLength - + AML_RESOURCE_UART_MIN_DATA_LEN; + + VendorData = ACPI_ADD_PTR (UINT8, Resource, + sizeof (AML_RESOURCE_UART_SERIALBUS)); + break; + + default: + return; + } + + /* Dump the vendor bytes as a RawDataBuffer object */ + + AcpiDmDumpRawDataBuffer (VendorData, VendorLength, Level); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmI2cSerialBusDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a I2C serial bus descriptor + * + ******************************************************************************/ + +static void +AcpiDmI2cSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + UINT32 ResourceSourceOffset; + + + /* SlaveAddress, SlaveMode, ConnectionSpeed, AddressingMode */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("I2cSerialBus (0x%4.4X, %s, 0x%8.8X,\n", + Resource->I2cSerialBus.SlaveAddress, + AcpiGbl_SmDecode [(Resource->I2cSerialBus.Flags & 1)], + Resource->I2cSerialBus.ConnectionSpeed); + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("%s, ", + AcpiGbl_AmDecode [(Resource->I2cSerialBus.TypeSpecificFlags & 1)]); + + /* ResourceSource is a required field */ + + ResourceSourceOffset = sizeof (AML_RESOURCE_COMMON_SERIALBUS) + + Resource->CommonSerialBus.TypeDataLength; + + AcpiUtPrintString ( + ACPI_ADD_PTR (char, Resource, ResourceSourceOffset), + ACPI_UINT8_MAX); + + /* ResourceSourceIndex, ResourceUsage */ + + AcpiOsPrintf (",\n"); + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%2.2X, ", Resource->I2cSerialBus.ResSourceIndex); + + AcpiOsPrintf ("%s, ", + AcpiGbl_ConsumeDecode [(Resource->I2cSerialBus.Flags >> 1) & 1]); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (",\n"); + + /* Dump the vendor data */ + + AcpiDmIndent (Level + 1); + AcpiDmDumpSerialBusVendorData (Resource, Level); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmSpiSerialBusDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a SPI serial bus descriptor + * + ******************************************************************************/ + +static void +AcpiDmSpiSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + UINT32 ResourceSourceOffset; + + + /* DeviceSelection, DeviceSelectionPolarity, WireMode, DataBitLength */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("SpiSerialBus (0x%4.4X, %s, %s, 0x%2.2X,\n", + Resource->SpiSerialBus.DeviceSelection, + AcpiGbl_DpDecode [(Resource->SpiSerialBus.TypeSpecificFlags >> 1) & 1], + AcpiGbl_WmDecode [(Resource->SpiSerialBus.TypeSpecificFlags & 1)], + Resource->SpiSerialBus.DataBitLength); + + /* SlaveMode, ConnectionSpeed, ClockPolarity, ClockPhase */ + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("%s, 0x%8.8X, %s,\n", + AcpiGbl_SmDecode [(Resource->SpiSerialBus.Flags & 1)], + Resource->SpiSerialBus.ConnectionSpeed, + AcpiGbl_CpoDecode [(Resource->SpiSerialBus.ClockPolarity & 1)]); + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("%s, ", + AcpiGbl_CphDecode [(Resource->SpiSerialBus.ClockPhase & 1)]); + + /* ResourceSource is a required field */ + + ResourceSourceOffset = sizeof (AML_RESOURCE_COMMON_SERIALBUS) + + Resource->CommonSerialBus.TypeDataLength; + + AcpiUtPrintString ( + ACPI_ADD_PTR (char, Resource, ResourceSourceOffset), + ACPI_UINT8_MAX); + + /* ResourceSourceIndex, ResourceUsage */ + + AcpiOsPrintf (",\n"); + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%2.2X, ", Resource->SpiSerialBus.ResSourceIndex); + + AcpiOsPrintf ("%s, ", + AcpiGbl_ConsumeDecode [(Resource->SpiSerialBus.Flags >> 1) & 1]); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (",\n"); + + /* Dump the vendor data */ + + AcpiDmIndent (Level + 1); + AcpiDmDumpSerialBusVendorData (Resource, Level); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmUartSerialBusDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a UART serial bus descriptor + * + ******************************************************************************/ + +static void +AcpiDmUartSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + UINT32 ResourceSourceOffset; + + + /* ConnectionSpeed, BitsPerByte, StopBits */ + + AcpiDmIndent (Level); + AcpiOsPrintf ("UartSerialBus (0x%8.8X, %s, %s,\n", + Resource->UartSerialBus.DefaultBaudRate, + AcpiGbl_BpbDecode [(Resource->UartSerialBus.TypeSpecificFlags >> 4) & 3], + AcpiGbl_SbDecode [(Resource->UartSerialBus.TypeSpecificFlags >> 2) & 3]); + + /* LinesInUse, IsBigEndian, Parity, FlowControl */ + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%2.2X, %s, %s, %s,\n", + Resource->UartSerialBus.LinesEnabled, + AcpiGbl_EdDecode [(Resource->UartSerialBus.TypeSpecificFlags >> 7) & 1], + AcpiGbl_PtDecode [Resource->UartSerialBus.Parity & 7], + AcpiGbl_FcDecode [Resource->UartSerialBus.TypeSpecificFlags & 3]); + + /* ReceiveBufferSize, TransmitBufferSize */ + + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%4.4X, 0x%4.4X, ", + Resource->UartSerialBus.RxFifoSize, + Resource->UartSerialBus.TxFifoSize); + + /* ResourceSource is a required field */ + + ResourceSourceOffset = sizeof (AML_RESOURCE_COMMON_SERIALBUS) + + Resource->CommonSerialBus.TypeDataLength; + + AcpiUtPrintString ( + ACPI_ADD_PTR (char, Resource, ResourceSourceOffset), + ACPI_UINT8_MAX); + + /* ResourceSourceIndex, ResourceUsage */ + + AcpiOsPrintf (",\n"); + AcpiDmIndent (Level + 1); + AcpiOsPrintf ("0x%2.2X, ", Resource->UartSerialBus.ResSourceIndex); + + AcpiOsPrintf ("%s, ", + AcpiGbl_ConsumeDecode [(Resource->UartSerialBus.Flags >> 1) & 1]); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (",\n"); + + /* Dump the vendor data */ + + AcpiDmIndent (Level + 1); + AcpiDmDumpSerialBusVendorData (Resource, Level); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmSerialBusDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a I2C/SPI/UART serial bus descriptor + * + ******************************************************************************/ + +void +AcpiDmSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + SerialBusResourceDispatch [Resource->CommonSerialBus.Type] ( + Resource, Length, Level); +} + +#endif + diff --git a/source/components/disassembler/dmresrcs.c b/source/components/disassembler/dmresrcs.c new file mode 100644 index 000000000000..32759d991bb5 --- /dev/null +++ b/source/components/disassembler/dmresrcs.c @@ -0,0 +1,358 @@ +/******************************************************************************* + * + * Module Name: dmresrcs.c - "Small" Resource Descriptor disassembly + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dbresrcs") + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIrqDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a IRQ descriptor, either Irq() or IrqNoFlags() + * + ******************************************************************************/ + +void +AcpiDmIrqDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("%s (", + AcpiGbl_IrqDecode [Length & 1]); + + /* Decode flags byte if present */ + + if (Length & 1) + { + AcpiOsPrintf ("%s, %s, %s, ", + AcpiGbl_HeDecode [Resource->Irq.Flags & 1], + AcpiGbl_LlDecode [(Resource->Irq.Flags >> 3) & 1], + AcpiGbl_ShrDecode [(Resource->Irq.Flags >> 4) & 1]); + } + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); + + AcpiDmIndent (Level + 1); + AcpiDmBitList (Resource->Irq.IrqMask); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDmaDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a DMA descriptor + * + ******************************************************************************/ + +void +AcpiDmDmaDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("DMA (%s, %s, %s, ", + AcpiGbl_TypDecode [(Resource->Dma.Flags >> 5) & 3], + AcpiGbl_BmDecode [(Resource->Dma.Flags >> 2) & 1], + AcpiGbl_SizDecode [(Resource->Dma.Flags >> 0) & 3]); + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); + + AcpiDmIndent (Level + 1); + AcpiDmBitList (Resource->Dma.DmaChannelMask); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFixedDmaDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a FixedDMA descriptor + * + ******************************************************************************/ + +void +AcpiDmFixedDmaDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("FixedDMA (0x%4.4X, 0x%4.4X, ", + Resource->FixedDma.RequestLines, + Resource->FixedDma.Channels); + + if (Resource->FixedDma.Width <= 5) + { + AcpiOsPrintf ("%s, ", + AcpiGbl_DtsDecode [Resource->FixedDma.Width]); + } + else + { + AcpiOsPrintf ("%X /* INVALID DMA WIDTH */, ", Resource->FixedDma.Width); + } + + /* Insert a descriptor name */ + + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIoDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode an IO descriptor + * + ******************************************************************************/ + +void +AcpiDmIoDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("IO (%s,\n", + AcpiGbl_IoDecode [(Resource->Io.Flags & 1)]); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger16 (Resource->Io.Minimum, "Range Minimum"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger16 (Resource->Io.Maximum, "Range Maximum"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger8 (Resource->Io.Alignment, "Alignment"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger8 (Resource->Io.AddressLength, "Length"); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmFixedIoDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Fixed IO descriptor + * + ******************************************************************************/ + +void +AcpiDmFixedIoDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("FixedIO (\n"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger16 (Resource->FixedIo.Address, "Address"); + + AcpiDmIndent (Level + 1); + AcpiDmDumpInteger8 (Resource->FixedIo.AddressLength, "Length"); + + /* Insert a descriptor name */ + + AcpiDmIndent (Level + 1); + AcpiDmDescriptorName (); + AcpiOsPrintf (")\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmStartDependentDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Start Dependendent functions descriptor + * + ******************************************************************************/ + +void +AcpiDmStartDependentDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + + if (Length & 1) + { + AcpiOsPrintf ("StartDependentFn (0x%2.2X, 0x%2.2X)\n", + (UINT32) Resource->StartDpf.Flags & 3, + (UINT32) (Resource->StartDpf.Flags >> 2) & 3); + } + else + { + AcpiOsPrintf ("StartDependentFnNoPri ()\n"); + } + + AcpiDmIndent (Level); + AcpiOsPrintf ("{\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmEndDependentDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode an End Dependent functions descriptor + * + ******************************************************************************/ + +void +AcpiDmEndDependentDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmIndent (Level); + AcpiOsPrintf ("}\n"); + AcpiDmIndent (Level); + AcpiOsPrintf ("EndDependentFn ()\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmVendorSmallDescriptor + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Length - Length of the descriptor in bytes + * Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Decode a Vendor Small Descriptor + * + ******************************************************************************/ + +void +AcpiDmVendorSmallDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level) +{ + + AcpiDmVendorCommon ("Short", + ACPI_ADD_PTR (UINT8, Resource, sizeof (AML_RESOURCE_SMALL_HEADER)), + Length, Level); +} + +#endif + diff --git a/source/components/disassembler/dmutils.c b/source/components/disassembler/dmutils.c new file mode 100644 index 000000000000..ce3443ec3fc1 --- /dev/null +++ b/source/components/disassembler/dmutils.c @@ -0,0 +1,321 @@ +/******************************************************************************* + * + * Module Name: dmutils - AML disassembler utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdisasm.h" + +#ifdef ACPI_ASL_COMPILER +#include +#endif + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmutils") + + +/* Data used in keeping track of fields */ +#if 0 +const char *AcpiGbl_FENames[] = +{ + "skip", + "?access?" +}; /* FE = Field Element */ +#endif + +/* Operators for Match() */ + +const char *AcpiGbl_MatchOps[] = +{ + "MTR", + "MEQ", + "MLE", + "MLT", + "MGE", + "MGT" +}; + +/* Access type decoding */ + +const char *AcpiGbl_AccessTypes[] = +{ + "AnyAcc", + "ByteAcc", + "WordAcc", + "DWordAcc", + "QWordAcc", + "BufferAcc", + "InvalidAccType", + "InvalidAccType" +}; + +/* Lock rule decoding */ + +const char *AcpiGbl_LockRule[] = +{ + "NoLock", + "Lock" +}; + +/* Update rule decoding */ + +const char *AcpiGbl_UpdateRules[] = +{ + "Preserve", + "WriteAsOnes", + "WriteAsZeros", + "InvalidUpdateRule" +}; + +/* Strings used to decode resource descriptors */ + +const char *AcpiGbl_WordDecode[] = +{ + "Memory", + "IO", + "BusNumber", + "UnknownResourceType" +}; + +const char *AcpiGbl_IrqDecode[] = +{ + "IRQNoFlags", + "IRQ" +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDecodeAttribute + * + * PARAMETERS: Attribute - Attribute field of AccessAs keyword + * + * RETURN: None + * + * DESCRIPTION: Decode the AccessAs attribute byte. (Mostly SMBus and + * GenericSerialBus stuff.) + * + ******************************************************************************/ + +void +AcpiDmDecodeAttribute ( + UINT8 Attribute) +{ + + switch (Attribute) + { + case AML_FIELD_ATTRIB_QUICK: + + AcpiOsPrintf ("AttribQuick"); + break; + + case AML_FIELD_ATTRIB_SEND_RCV: + + AcpiOsPrintf ("AttribSendReceive"); + break; + + case AML_FIELD_ATTRIB_BYTE: + + AcpiOsPrintf ("AttribByte"); + break; + + case AML_FIELD_ATTRIB_WORD: + + AcpiOsPrintf ("AttribWord"); + break; + + case AML_FIELD_ATTRIB_BLOCK: + + AcpiOsPrintf ("AttribBlock"); + break; + + case AML_FIELD_ATTRIB_MULTIBYTE: + + AcpiOsPrintf ("AttribBytes"); + break; + + case AML_FIELD_ATTRIB_WORD_CALL: + + AcpiOsPrintf ("AttribProcessCall"); + break; + + case AML_FIELD_ATTRIB_BLOCK_CALL: + + AcpiOsPrintf ("AttribBlockProcessCall"); + break; + + case AML_FIELD_ATTRIB_RAW_BYTES: + + AcpiOsPrintf ("AttribRawBytes"); + break; + + case AML_FIELD_ATTRIB_RAW_PROCESS: + + AcpiOsPrintf ("AttribRawProcessBytes"); + break; + + default: + + /* A ByteConst is allowed by the grammar */ + + AcpiOsPrintf ("0x%2.2X", Attribute); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmIndent + * + * PARAMETERS: Level - Current source code indentation level + * + * RETURN: None + * + * DESCRIPTION: Indent 4 spaces per indentation level. + * + ******************************************************************************/ + +void +AcpiDmIndent ( + UINT32 Level) +{ + + if (!Level) + { + return; + } + + AcpiOsPrintf ("%*.s", ACPI_MUL_4 (Level), " "); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCommaIfListMember + * + * PARAMETERS: Op - Current operator/operand + * + * RETURN: TRUE if a comma was inserted + * + * DESCRIPTION: Insert a comma if this Op is a member of an argument list. + * + ******************************************************************************/ + +BOOLEAN +AcpiDmCommaIfListMember ( + ACPI_PARSE_OBJECT *Op) +{ + + if (!Op->Common.Next) + { + return FALSE; + } + + if (AcpiDmListType (Op->Common.Parent) & BLOCK_COMMA_LIST) + { + /* Check for a NULL target operand */ + + if ((Op->Common.Next->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + (!Op->Common.Next->Common.Value.String)) + { + /* + * To handle the Divide() case where there are two optional + * targets, look ahead one more op. If null, this null target + * is the one and only target -- no comma needed. Otherwise, + * we need a comma to prepare for the next target. + */ + if (!Op->Common.Next->Common.Next) + { + return FALSE; + } + } + + if ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) && + (!(Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))) + { + return FALSE; + } + + AcpiOsPrintf (", "); + return (TRUE); + } + + else if ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) && + (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) + { + AcpiOsPrintf (", "); + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmCommaIfFieldMember + * + * PARAMETERS: Op - Current operator/operand + * + * RETURN: None + * + * DESCRIPTION: Insert a comma if this Op is a member of a Field argument list. + * + ******************************************************************************/ + +void +AcpiDmCommaIfFieldMember ( + ACPI_PARSE_OBJECT *Op) +{ + + if (Op->Common.Next) + { + AcpiOsPrintf (", "); + } +} + +#endif diff --git a/source/components/disassembler/dmwalk.c b/source/components/disassembler/dmwalk.c new file mode 100644 index 000000000000..dd3ee002557b --- /dev/null +++ b/source/components/disassembler/dmwalk.c @@ -0,0 +1,935 @@ +/******************************************************************************* + * + * Module Name: dmwalk - AML disassembly tree walk + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdisasm.h" +#include "acdebug.h" + + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT ACPI_CA_DEBUGGER + ACPI_MODULE_NAME ("dmwalk") + + +#define DB_FULL_OP_INFO "[%4.4s] @%5.5X #%4.4X: " + +/* Stub for non-compiler code */ + +#ifndef ACPI_ASL_COMPILER +void +AcpiDmEmitExternals ( + void) +{ + return; +} +#endif + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDmDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static ACPI_STATUS +AcpiDmAscendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); + +static UINT32 +AcpiDmBlockType ( + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDisassemble + * + * PARAMETERS: WalkState - Current state + * Origin - Starting object + * NumOpcodes - Max number of opcodes to be displayed + * + * RETURN: None + * + * DESCRIPTION: Disassemble parser object and its children. This is the + * main entry point of the disassembler. + * + ******************************************************************************/ + +void +AcpiDmDisassemble ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Origin, + UINT32 NumOpcodes) +{ + ACPI_PARSE_OBJECT *Op = Origin; + ACPI_OP_WALK_INFO Info; + + + if (!Op) + { + return; + } + + Info.Flags = 0; + Info.Level = 0; + Info.Count = 0; + Info.WalkState = WalkState; + AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmWalkParseTree + * + * PARAMETERS: Op - Root Op object + * DescendingCallback - Called during tree descent + * AscendingCallback - Called during tree ascent + * Context - To be passed to the callbacks + * + * RETURN: Status from callback(s) + * + * DESCRIPTION: Walk the entire parse tree. + * + ******************************************************************************/ + +void +AcpiDmWalkParseTree ( + ACPI_PARSE_OBJECT *Op, + ASL_WALK_CALLBACK DescendingCallback, + ASL_WALK_CALLBACK AscendingCallback, + void *Context) +{ + BOOLEAN NodePreviouslyVisited; + ACPI_PARSE_OBJECT *StartOp = Op; + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Next; + ACPI_OP_WALK_INFO *Info = Context; + + + Info->Level = 0; + NodePreviouslyVisited = FALSE; + + while (Op) + { + if (NodePreviouslyVisited) + { + if (AscendingCallback) + { + Status = AscendingCallback (Op, Info->Level, Context); + if (ACPI_FAILURE (Status)) + { + return; + } + } + } + else + { + /* Let the callback process the node */ + + Status = DescendingCallback (Op, Info->Level, Context); + if (ACPI_SUCCESS (Status)) + { + /* Visit children first, once */ + + Next = AcpiPsGetArg (Op, 0); + if (Next) + { + Info->Level++; + Op = Next; + continue; + } + } + else if (Status != AE_CTRL_DEPTH) + { + /* Exit immediately on any error */ + + return; + } + } + + /* Terminate walk at start op */ + + if (Op == StartOp) + { + break; + } + + /* No more children, re-visit this node */ + + if (!NodePreviouslyVisited) + { + NodePreviouslyVisited = TRUE; + continue; + } + + /* No more children, visit peers */ + + if (Op->Common.Next) + { + Op = Op->Common.Next; + NodePreviouslyVisited = FALSE; + } + else + { + /* No peers, re-visit parent */ + + if (Info->Level != 0 ) + { + Info->Level--; + } + + Op = Op->Common.Parent; + NodePreviouslyVisited = TRUE; + } + } + + /* If we get here, the walk completed with no errors */ + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmBlockType + * + * PARAMETERS: Op - Object to be examined + * + * RETURN: BlockType - not a block, parens, braces, or even both. + * + * DESCRIPTION: Type of block for this op (parens or braces) + * + ******************************************************************************/ + +static UINT32 +AcpiDmBlockType ( + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *OpInfo; + + + if (!Op) + { + return (BLOCK_NONE); + } + + switch (Op->Common.AmlOpcode) + { + case AML_ELSE_OP: + + return (BLOCK_BRACE); + + case AML_METHOD_OP: + case AML_DEVICE_OP: + case AML_SCOPE_OP: + case AML_PROCESSOR_OP: + case AML_POWER_RES_OP: + case AML_THERMAL_ZONE_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_FIELD_OP: + case AML_INDEX_FIELD_OP: + case AML_BANK_FIELD_OP: + + return (BLOCK_PAREN | BLOCK_BRACE); + + case AML_BUFFER_OP: + + if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) + { + return (BLOCK_NONE); + } + + /*lint -fallthrough */ + + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + return (BLOCK_PAREN | BLOCK_BRACE); + + case AML_EVENT_OP: + + return (BLOCK_PAREN); + + default: + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (OpInfo->Flags & AML_HAS_ARGS) + { + return (BLOCK_PAREN); + } + + return (BLOCK_NONE); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmListType + * + * PARAMETERS: Op - Object to be examined + * + * RETURN: ListType - has commas or not. + * + * DESCRIPTION: Type of block for this op (parens or braces) + * + ******************************************************************************/ + +UINT32 +AcpiDmListType ( + ACPI_PARSE_OBJECT *Op) +{ + const ACPI_OPCODE_INFO *OpInfo; + + + if (!Op) + { + return (BLOCK_NONE); + } + + switch (Op->Common.AmlOpcode) + { + + case AML_ELSE_OP: + case AML_METHOD_OP: + case AML_DEVICE_OP: + case AML_SCOPE_OP: + case AML_POWER_RES_OP: + case AML_PROCESSOR_OP: + case AML_THERMAL_ZONE_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_FIELD_OP: + case AML_INDEX_FIELD_OP: + case AML_BANK_FIELD_OP: + + return (BLOCK_NONE); + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + return (BLOCK_COMMA_LIST); + + default: + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (OpInfo->Flags & AML_HAS_ARGS) + { + return (BLOCK_COMMA_LIST); + } + + return (BLOCK_NONE); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmDescendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: First visitation of a parse object during tree descent. + * Decode opcode name and begin parameter list(s), if any. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmDescendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + const ACPI_OPCODE_INFO *OpInfo; + UINT32 Name; + ACPI_PARSE_OBJECT *NextOp; + + + if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) + { + /* Ignore this op -- it was handled elsewhere */ + + return (AE_CTRL_DEPTH); + } + + /* Level 0 is at the Definition Block level */ + + if (Level == 0) + { + /* In verbose mode, print the AML offset, opcode and depth count */ + + if (Info->WalkState) + { + VERBOSE_PRINT ((DB_FULL_OP_INFO, + (Info->WalkState->MethodNode ? + Info->WalkState->MethodNode->Name.Ascii : " "), + Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode)); + } + + if (Op->Common.AmlOpcode == AML_SCOPE_OP) + { + /* This is the beginning of the Definition Block */ + + AcpiOsPrintf ("{\n"); + + /* Emit all External() declarations here */ + + AcpiDmEmitExternals (); + return (AE_OK); + } + } + else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && + (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && + (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) + { + /* + * This is a first-level element of a term list, + * indent a new line + */ + AcpiDmIndent (Level); + Info->LastLevel = Level; + Info->Count = 0; + } + + /* + * This is an inexpensive mechanism to try and keep lines from getting + * too long. When the limit is hit, start a new line at the previous + * indent plus one. A better but more expensive mechanism would be to + * keep track of the current column. + */ + Info->Count++; + if (Info->Count /*+Info->LastLevel*/ > 10) + { + Info->Count = 0; + AcpiOsPrintf ("\n"); + AcpiDmIndent (Info->LastLevel + 1); + } + + /* Print the opcode name */ + + AcpiDmDisassembleOneOp (NULL, Info, Op); + + if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) || + (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)) + { + return (AE_OK); + } + + if ((Op->Common.AmlOpcode == AML_NAME_OP) || + (Op->Common.AmlOpcode == AML_RETURN_OP)) + { + Info->Level--; + } + + /* Start the opcode argument list if necessary */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + if ((OpInfo->Flags & AML_HAS_ARGS) || + (Op->Common.AmlOpcode == AML_EVENT_OP)) + { + /* This opcode has an argument list */ + + if (AcpiDmBlockType (Op) & BLOCK_PAREN) + { + AcpiOsPrintf (" ("); + } + + /* If this is a named opcode, print the associated name value */ + + if (OpInfo->Flags & AML_NAMED) + { + switch (Op->Common.AmlOpcode) + { + case AML_ALIAS_OP: + + NextOp = AcpiPsGetDepthNext (NULL, Op); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + AcpiDmNamestring (NextOp->Common.Value.Name); + AcpiOsPrintf (", "); + + /*lint -fallthrough */ + + default: + + Name = AcpiPsGetName (Op); + if (Op->Named.Path) + { + AcpiDmNamestring ((char *) Op->Named.Path); + } + else + { + AcpiDmDumpName (Name); + } + + if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP) + { + if (AcpiGbl_DbOpt_verbose) + { + (void) AcpiPsDisplayObjectPathname (NULL, Op); + } + } + break; + } + + switch (Op->Common.AmlOpcode) + { + case AML_METHOD_OP: + + AcpiDmMethodFlags (Op); + AcpiOsPrintf (")"); + break; + + + case AML_NAME_OP: + + /* Check for _HID and related EISAID() */ + + AcpiDmIsEisaId (Op); + AcpiOsPrintf (", "); + break; + + + case AML_REGION_OP: + + AcpiDmRegionFlags (Op); + break; + + + case AML_POWER_RES_OP: + + /* Mark the next two Ops as part of the parameter list */ + + AcpiOsPrintf (", "); + NextOp = AcpiPsGetDepthNext (NULL, Op); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + + NextOp = NextOp->Common.Next; + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + return (AE_OK); + + + case AML_PROCESSOR_OP: + + /* Mark the next three Ops as part of the parameter list */ + + AcpiOsPrintf (", "); + NextOp = AcpiPsGetDepthNext (NULL, Op); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + + NextOp = NextOp->Common.Next; + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + + NextOp = NextOp->Common.Next; + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + return (AE_OK); + + + case AML_MUTEX_OP: + case AML_DATA_REGION_OP: + + AcpiOsPrintf (", "); + return (AE_OK); + + + case AML_EVENT_OP: + case AML_ALIAS_OP: + + return (AE_OK); + + + case AML_SCOPE_OP: + case AML_DEVICE_OP: + case AML_THERMAL_ZONE_OP: + + AcpiOsPrintf (")"); + break; + + + default: + + AcpiOsPrintf ("*** Unhandled named opcode %X\n", Op->Common.AmlOpcode); + break; + } + } + + else switch (Op->Common.AmlOpcode) + { + case AML_FIELD_OP: + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + + Info->BitOffset = 0; + + /* Name of the parent OperationRegion */ + + NextOp = AcpiPsGetDepthNext (NULL, Op); + AcpiDmNamestring (NextOp->Common.Value.Name); + AcpiOsPrintf (", "); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + + switch (Op->Common.AmlOpcode) + { + case AML_BANK_FIELD_OP: + + /* Namestring - Bank Name */ + + NextOp = AcpiPsGetDepthNext (NULL, NextOp); + AcpiDmNamestring (NextOp->Common.Value.Name); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + AcpiOsPrintf (", "); + + /* + * Bank Value. This is a TermArg in the middle of the parameter + * list, must handle it here. + * + * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST + * eliminates newline in the output. + */ + NextOp = NextOp->Common.Next; + + Info->Flags = ACPI_PARSEOP_PARAMLIST; + AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, AcpiDmAscendingOp, Info); + Info->Flags = 0; + Info->Level = Level; + + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + AcpiOsPrintf (", "); + break; + + case AML_INDEX_FIELD_OP: + + /* Namestring - Data Name */ + + NextOp = AcpiPsGetDepthNext (NULL, NextOp); + AcpiDmNamestring (NextOp->Common.Value.Name); + AcpiOsPrintf (", "); + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + break; + + default: + + break; + } + + AcpiDmFieldFlags (NextOp); + break; + + + case AML_BUFFER_OP: + + /* The next op is the size parameter */ + + NextOp = AcpiPsGetDepthNext (NULL, Op); + if (!NextOp) + { + /* Single-step support */ + + return (AE_OK); + } + + if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE) + { + /* + * We have a resource list. Don't need to output + * the buffer size Op. Open up a new block + */ + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; + NextOp = NextOp->Common.Next; + AcpiOsPrintf (")\n"); + AcpiDmIndent (Info->Level); + AcpiOsPrintf ("{\n"); + return (AE_OK); + } + + /* Normal Buffer, mark size as in the parameter list */ + + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + return (AE_OK); + + + case AML_VAR_PACKAGE_OP: + case AML_IF_OP: + case AML_WHILE_OP: + + /* The next op is the size or predicate parameter */ + + NextOp = AcpiPsGetDepthNext (NULL, Op); + if (NextOp) + { + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + } + return (AE_OK); + + + case AML_PACKAGE_OP: + + /* The next op is the size or predicate parameter */ + + NextOp = AcpiPsGetDepthNext (NULL, Op); + if (NextOp) + { + NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; + } + return (AE_OK); + + + case AML_MATCH_OP: + + AcpiDmMatchOp (Op); + break; + + + default: + + break; + } + + if (AcpiDmBlockType (Op) & BLOCK_BRACE) + { + AcpiOsPrintf ("\n"); + AcpiDmIndent (Level); + AcpiOsPrintf ("{\n"); + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAscendingOp + * + * PARAMETERS: ASL_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Second visitation of a parse object, during ascent of parse + * tree. Close out any parameter lists and complete the opcode. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDmAscendingOp ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context) +{ + ACPI_OP_WALK_INFO *Info = Context; + + + if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) + { + /* Ignore this op -- it was handled elsewhere */ + + return (AE_OK); + } + + if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP)) + { + /* Indicates the end of the current descriptor block (table) */ + + AcpiOsPrintf ("}\n\n"); + return (AE_OK); + } + + switch (AcpiDmBlockType (Op)) + { + case BLOCK_PAREN: + + /* Completed an op that has arguments, add closing paren */ + + AcpiOsPrintf (")"); + + /* Could be a nested operator, check if comma required */ + + if (!AcpiDmCommaIfListMember (Op)) + { + if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && + (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && + (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) + { + /* + * This is a first-level element of a term list + * start a new line + */ + if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST)) + { + AcpiOsPrintf ("\n"); + } + } + } + break; + + + case BLOCK_BRACE: + case (BLOCK_BRACE | BLOCK_PAREN): + + /* Completed an op that has a term list, add closing brace */ + + if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST) + { + AcpiOsPrintf ("}"); + } + else + { + AcpiDmIndent (Level); + AcpiOsPrintf ("}"); + } + + AcpiDmCommaIfListMember (Op); + + if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN) + { + AcpiOsPrintf ("\n"); + if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)) + { + if ((Op->Common.AmlOpcode == AML_IF_OP) && + (Op->Common.Next) && + (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP)) + { + break; + } + + if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && + (!Op->Common.Next)) + { + break; + } + AcpiOsPrintf ("\n"); + } + } + break; + + + case BLOCK_NONE: + default: + + /* Could be a nested operator, check if comma required */ + + if (!AcpiDmCommaIfListMember (Op)) + { + if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && + (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && + (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) + { + /* + * This is a first-level element of a term list + * start a new line + */ + AcpiOsPrintf ("\n"); + } + } + else if (Op->Common.Parent) + { + switch (Op->Common.Parent->Common.AmlOpcode) + { + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) + { + AcpiOsPrintf ("\n"); + } + break; + + default: + + break; + } + } + break; + } + + if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) + { + if ((Op->Common.Next) && + (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) + { + return (AE_OK); + } + + /* + * Just completed a parameter node for something like "Buffer (param)". + * Close the paren and open up the term list block with a brace + */ + if (Op->Common.Next) + { + AcpiOsPrintf (")\n"); + AcpiDmIndent (Level - 1); + AcpiOsPrintf ("{\n"); + } + else + { + Op->Common.Parent->Common.DisasmFlags |= + ACPI_PARSEOP_EMPTY_TERMLIST; + AcpiOsPrintf (") {"); + } + } + + if ((Op->Common.AmlOpcode == AML_NAME_OP) || + (Op->Common.AmlOpcode == AML_RETURN_OP)) + { + Info->Level++; + } + return (AE_OK); +} + + +#endif /* ACPI_DISASSEMBLER */ diff --git a/source/components/dispatcher/dsargs.c b/source/components/dispatcher/dsargs.c new file mode 100644 index 000000000000..ea0d7bee88f7 --- /dev/null +++ b/source/components/dispatcher/dsargs.c @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * Module Name: dsargs - Support for execution of dynamic arguments for static + * objects (regions, fields, buffer fields, etc.) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSARGS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsargs") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsExecuteArguments ( + ACPI_NAMESPACE_NODE *Node, + ACPI_NAMESPACE_NODE *ScopeNode, + UINT32 AmlLength, + UINT8 *AmlStart); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsExecuteArguments + * + * PARAMETERS: Node - Object NS node + * ScopeNode - Parent NS node + * AmlLength - Length of executable AML + * AmlStart - Pointer to the AML + * + * RETURN: Status. + * + * DESCRIPTION: Late (deferred) execution of region or field arguments + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsExecuteArguments ( + ACPI_NAMESPACE_NODE *Node, + ACPI_NAMESPACE_NODE *ScopeNode, + UINT32 AmlLength, + UINT8 *AmlStart) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Op; + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_TRACE (DsExecuteArguments); + + + /* Allocate a new parser op to be the root of the parsed tree */ + + Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Save the Node for use in AcpiPsParseAml */ + + Op->Common.Node = ScopeNode; + + /* Create and initialize a new parser state */ + + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, + AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + /* Mark this parse as a deferred opcode */ + + WalkState->ParseFlags = ACPI_PARSE_DEFERRED_OP; + WalkState->DeferredNode = Node; + + /* Pass1: Parse the entire declaration */ + + Status = AcpiPsParseAml (WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Get and init the Op created above */ + + Op->Common.Node = Node; + AcpiPsDeleteParseTree (Op); + + /* Evaluate the deferred arguments */ + + Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Op->Common.Node = ScopeNode; + + /* Create and initialize a new parser state */ + + WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); + if (!WalkState) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Execute the opcode and arguments */ + + Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, + AmlLength, NULL, ACPI_IMODE_EXECUTE); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + /* Mark this execution as a deferred opcode */ + + WalkState->DeferredNode = Node; + Status = AcpiPsParseAml (WalkState); + +Cleanup: + AcpiPsDeleteParseTree (Op); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetBufferFieldArguments + * + * PARAMETERS: ObjDesc - A valid BufferField object + * + * RETURN: Status. + * + * DESCRIPTION: Get BufferField Buffer and Index. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsGetBufferFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_OPERAND_OBJECT *ExtraDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsGetBufferFieldArguments, ObjDesc); + + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the AML pointer (method object) and BufferField node */ + + ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); + Node = ObjDesc->BufferField.Node; + + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_BUFFER_FIELD, + Node, NULL)); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", + AcpiUtGetNodeName (Node))); + + /* Execute the AML code for the TermArg arguments */ + + Status = AcpiDsExecuteArguments (Node, Node->Parent, + ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetBankFieldArguments + * + * PARAMETERS: ObjDesc - A valid BankField object + * + * RETURN: Status. + * + * DESCRIPTION: Get BankField BankValue. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsGetBankFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_OPERAND_OBJECT *ExtraDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsGetBankFieldArguments, ObjDesc); + + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the AML pointer (method object) and BankField node */ + + ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); + Node = ObjDesc->BankField.Node; + + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_LOCAL_BANK_FIELD, + Node, NULL)); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", + AcpiUtGetNodeName (Node))); + + /* Execute the AML code for the TermArg arguments */ + + Status = AcpiDsExecuteArguments (Node, Node->Parent, + ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetBufferArguments + * + * PARAMETERS: ObjDesc - A valid Buffer object + * + * RETURN: Status. + * + * DESCRIPTION: Get Buffer length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsGetBufferArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsGetBufferArguments, ObjDesc); + + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the Buffer node */ + + Node = ObjDesc->Buffer.Node; + if (!Node) + { + ACPI_ERROR ((AE_INFO, + "No pointer back to namespace node in buffer object %p", ObjDesc)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n")); + + /* Execute the AML code for the TermArg arguments */ + + Status = AcpiDsExecuteArguments (Node, Node, + ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetPackageArguments + * + * PARAMETERS: ObjDesc - A valid Package object + * + * RETURN: Status. + * + * DESCRIPTION: Get Package length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsGetPackageArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc); + + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the Package node */ + + Node = ObjDesc->Package.Node; + if (!Node) + { + ACPI_ERROR ((AE_INFO, + "No pointer back to namespace node in package %p", ObjDesc)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n")); + + /* Execute the AML code for the TermArg arguments */ + + Status = AcpiDsExecuteArguments (Node, Node, + ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetRegionArguments + * + * PARAMETERS: ObjDesc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsGetRegionArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ExtraDesc; + + + ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc); + + + if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) + { + return_ACPI_STATUS (AE_OK); + } + + ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); + if (!ExtraDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Get the Region node */ + + Node = ObjDesc->Region.Node; + + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_REGION, Node, NULL)); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", + AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart)); + + /* Execute the argument AML */ + + Status = AcpiDsExecuteArguments (Node, ExtraDesc->Extra.ScopeNode, + ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiUtAddAddressRange (ObjDesc->Region.SpaceId, + ObjDesc->Region.Address, ObjDesc->Region.Length, + Node); + return_ACPI_STATUS (Status); +} diff --git a/source/components/dispatcher/dscontrol.c b/source/components/dispatcher/dscontrol.c new file mode 100644 index 000000000000..5c5c51a573e6 --- /dev/null +++ b/source/components/dispatcher/dscontrol.c @@ -0,0 +1,424 @@ +/****************************************************************************** + * + * Module Name: dscontrol - Support for execution control opcodes - + * if/else/while/return + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSCONTROL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dscontrol") + + +/******************************************************************************* + * + * FUNCTION: AcpiDsExecBeginControlOp + * + * PARAMETERS: WalkList - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsExecBeginControlOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *ControlState; + + + ACPI_FUNCTION_NAME (DsExecBeginControlOp); + + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", + Op, Op->Common.AmlOpcode, WalkState)); + + switch (Op->Common.AmlOpcode) + { + case AML_WHILE_OP: + + /* + * If this is an additional iteration of a while loop, continue. + * There is no need to allocate a new control state. + */ + if (WalkState->ControlState) + { + if (WalkState->ControlState->Control.AmlPredicateStart == + (WalkState->ParserState.Aml - 1)) + { + /* Reset the state to start-of-loop */ + + WalkState->ControlState->Common.State = + ACPI_CONTROL_CONDITIONAL_EXECUTING; + break; + } + } + + /*lint -fallthrough */ + + case AML_IF_OP: + + /* + * IF/WHILE: Create a new control state to manage these + * constructs. We need to manage these as a stack, in order + * to handle nesting. + */ + ControlState = AcpiUtCreateControlState (); + if (!ControlState) + { + Status = AE_NO_MEMORY; + break; + } + /* + * Save a pointer to the predicate for multiple executions + * of a loop + */ + ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1; + ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd; + ControlState->Control.Opcode = Op->Common.AmlOpcode; + + + /* Push the control state on this walk's control stack */ + + AcpiUtPushGenericState (&WalkState->ControlState, ControlState); + break; + + case AML_ELSE_OP: + + /* Predicate is in the state object */ + /* If predicate is true, the IF was executed, ignore ELSE part */ + + if (WalkState->LastPredicate) + { + Status = AE_CTRL_TRUE; + } + + break; + + case AML_RETURN_OP: + + break; + + default: + break; + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsExecEndControlOp + * + * PARAMETERS: WalkList - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsExecEndControlOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *ControlState; + + + ACPI_FUNCTION_NAME (DsExecEndControlOp); + + + switch (Op->Common.AmlOpcode) + { + case AML_IF_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op)); + + /* + * Save the result of the predicate in case there is an + * ELSE to come + */ + WalkState->LastPredicate = + (BOOLEAN) WalkState->ControlState->Common.Value; + + /* + * Pop the control state that was created at the start + * of the IF and free it + */ + ControlState = AcpiUtPopGenericState (&WalkState->ControlState); + AcpiUtDeleteGenericState (ControlState); + break; + + + case AML_ELSE_OP: + + break; + + + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op)); + + ControlState = WalkState->ControlState; + if (ControlState->Common.Value) + { + /* Predicate was true, the body of the loop was just executed */ + + /* + * This loop counter mechanism allows the interpreter to escape + * possibly infinite loops. This can occur in poorly written AML + * when the hardware does not respond within a while loop and the + * loop does not implement a timeout. + */ + ControlState->Control.LoopCount++; + if (ControlState->Control.LoopCount > ACPI_MAX_LOOP_ITERATIONS) + { + Status = AE_AML_INFINITE_LOOP; + break; + } + + /* + * Go back and evaluate the predicate and maybe execute the loop + * another time + */ + Status = AE_CTRL_PENDING; + WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart; + break; + } + + /* Predicate was false, terminate this while loop */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "[WHILE_OP] termination! Op=%p\n",Op)); + + /* Pop this control state and free it */ + + ControlState = AcpiUtPopGenericState (&WalkState->ControlState); + AcpiUtDeleteGenericState (ControlState); + break; + + + case AML_RETURN_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg)); + + /* + * One optional operand -- the return value + * It can be either an immediate operand or a result that + * has been bubbled up the tree + */ + if (Op->Common.Value.Arg) + { + /* Since we have a real Return(), delete any implicit return */ + + AcpiDsClearImplicitReturn (WalkState); + + /* Return statement has an immediate operand */ + + Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + */ + Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Get the return value and save as the last result + * value. This is the only place where WalkState->ReturnDesc + * is set to anything other than zero! + */ + WalkState->ReturnDesc = WalkState->Operands[0]; + } + else if (WalkState->ResultCount) + { + /* Since we have a real Return(), delete any implicit return */ + + AcpiDsClearImplicitReturn (WalkState); + + /* + * The return value has come from a previous calculation. + * + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + * + * Allow references created by the Index operator to return + * unchanged. + */ + if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) && + ((WalkState->Results->Results.ObjDesc [0])->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + ((WalkState->Results->Results.ObjDesc [0])->Reference.Class != ACPI_REFCLASS_INDEX)) + { + Status = AcpiExResolveToValue (&WalkState->Results->Results.ObjDesc [0], WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0]; + } + else + { + /* No return operand */ + + if (WalkState->NumOperands) + { + AcpiUtRemoveReference (WalkState->Operands [0]); + } + + WalkState->Operands [0] = NULL; + WalkState->NumOperands = 0; + WalkState->ReturnDesc = NULL; + } + + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Completed RETURN_OP State=%p, RetVal=%p\n", + WalkState, WalkState->ReturnDesc)); + + /* End the control method execution right now */ + + Status = AE_CTRL_TERMINATE; + break; + + + case AML_NOOP_OP: + + /* Just do nothing! */ + break; + + + case AML_BREAK_POINT_OP: + + /* + * Set the single-step flag. This will cause the debugger (if present) + * to break to the console within the AML debugger at the start of the + * next AML instruction. + */ + ACPI_DEBUGGER_EXEC ( + AcpiGbl_CmSingleStep = TRUE); + ACPI_DEBUGGER_EXEC ( + AcpiOsPrintf ("**break** Executed AML BreakPoint opcode\n")); + + /* Call to the OSL in case OS wants a piece of the action */ + + Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT, + "Executed AML Breakpoint opcode"); + break; + + + case AML_BREAK_OP: + case AML_CONTINUE_OP: /* ACPI 2.0 */ + + + /* Pop and delete control states until we find a while */ + + while (WalkState->ControlState && + (WalkState->ControlState->Control.Opcode != AML_WHILE_OP)) + { + ControlState = AcpiUtPopGenericState (&WalkState->ControlState); + AcpiUtDeleteGenericState (ControlState); + } + + /* No while found? */ + + if (!WalkState->ControlState) + { + return (AE_AML_NO_WHILE); + } + + /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */ + + WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd; + + /* Return status depending on opcode */ + + if (Op->Common.AmlOpcode == AML_BREAK_OP) + { + Status = AE_CTRL_BREAK; + } + else + { + Status = AE_CTRL_CONTINUE; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p", + Op->Common.AmlOpcode, Op)); + + Status = AE_AML_BAD_OPCODE; + break; + } + + return (Status); +} diff --git a/source/components/dispatcher/dsfield.c b/source/components/dispatcher/dsfield.c new file mode 100644 index 000000000000..1c3c523720cf --- /dev/null +++ b/source/components/dispatcher/dsfield.c @@ -0,0 +1,748 @@ +/****************************************************************************** + * + * Module Name: dsfield - Dispatcher field routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSFIELD_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsfield") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsGetFieldNames ( + ACPI_CREATE_FIELD_INFO *Info, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Arg); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateBufferField + * + * PARAMETERS: Op - Current parse op (CreateXXField) + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Execute the CreateField operators: + * CreateBitFieldOp, + * CreateByteFieldOp, + * CreateWordFieldOp, + * CreateDWordFieldOp, + * CreateQWordFieldOp, + * CreateFieldOp (all of which define a field in a buffer) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateBufferField ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *Arg; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *SecondDesc = NULL; + UINT32 Flags; + + + ACPI_FUNCTION_TRACE (DsCreateBufferField); + + + /* + * Get the NameString argument (name of the new BufferField) + */ + if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) + { + /* For CreateField, name is the 4th argument */ + + Arg = AcpiPsGetArg (Op, 3); + } + else + { + /* For all other CreateXXXField operators, name is the 3rd argument */ + + Arg = AcpiPsGetArg (Op, 2); + } + + if (!Arg) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + if (WalkState->DeferredNode) + { + Node = WalkState->DeferredNode; + Status = AE_OK; + } + else + { + /* Execute flag should always be set when this function is entered */ + + if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE)) + { + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* Creating new namespace node, should not already exist */ + + Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* + * Mark node temporary if we are executing a normal control + * method. (Don't mark if this is a module-level code method) + */ + if (WalkState->MethodNode && + !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) + { + Flags |= ACPI_NS_TEMPORARY; + } + + /* Enter the NameString into the namespace */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, + Flags, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); + return_ACPI_STATUS (Status); + } + } + + /* + * We could put the returned object (Node) on the object stack for later, + * but for now, we will put it in the "op" object that the parser uses, + * so we can get it again at the end of this scope. + */ + Op->Common.Node = Node; + + /* + * If there is no object attached to the node, this node was just created + * and we need to create the field object. Otherwise, this was a lookup + * of an existing node and we don't want to create the field object again. + */ + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) + */ + + /* Create the buffer field object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER_FIELD); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Remember location in AML stream of the field unit opcode and operands -- + * since the buffer and index operands must be evaluated. + */ + SecondDesc = ObjDesc->Common.NextObject; + SecondDesc->Extra.AmlStart = Op->Named.Data; + SecondDesc->Extra.AmlLength = Op->Named.Length; + ObjDesc->BufferField.Node = Node; + + /* Attach constructed field descriptors to parent node */ + + Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_BUFFER_FIELD); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + +Cleanup: + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetFieldNames + * + * PARAMETERS: Info - CreateField info structure + * ` WalkState - Current method state + * Arg - First parser arg for the field name list + * + * RETURN: Status + * + * DESCRIPTION: Process all named fields in a field declaration. Names are + * entered into the namespace. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsGetFieldNames ( + ACPI_CREATE_FIELD_INFO *Info, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Arg) +{ + ACPI_STATUS Status; + UINT64 Position; + ACPI_PARSE_OBJECT *Child; + + + ACPI_FUNCTION_TRACE_PTR (DsGetFieldNames, Info); + + + /* First field starts at bit zero */ + + Info->FieldBitPosition = 0; + + /* Process all elements in the field list (of parse nodes) */ + + while (Arg) + { + /* + * Four types of field elements are handled: + * 1) Name - Enters a new named field into the namespace + * 2) Offset - specifies a bit offset + * 3) AccessAs - changes the access mode/attributes + * 4) Connection - Associate a resource template with the field + */ + switch (Arg->Common.AmlOpcode) + { + case AML_INT_RESERVEDFIELD_OP: + + Position = (UINT64) Info->FieldBitPosition + + (UINT64) Arg->Common.Value.Size; + + if (Position > ACPI_UINT32_MAX) + { + ACPI_ERROR ((AE_INFO, + "Bit offset within field too large (> 0xFFFFFFFF)")); + return_ACPI_STATUS (AE_SUPPORT); + } + + Info->FieldBitPosition = (UINT32) Position; + break; + + case AML_INT_ACCESSFIELD_OP: + case AML_INT_EXTACCESSFIELD_OP: + /* + * Get new AccessType, AccessAttribute, and AccessLength fields + * -- to be used for all field units that follow, until the + * end-of-field or another AccessAs keyword is encountered. + * NOTE. These three bytes are encoded in the integer value + * of the parseop for convenience. + * + * In FieldFlags, preserve the flag bits other than the + * ACCESS_TYPE bits. + */ + + /* AccessType (ByteAcc, WordAcc, etc.) */ + + Info->FieldFlags = (UINT8) + ((Info->FieldFlags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | + ((UINT8) ((UINT32) (Arg->Common.Value.Integer & 0x07)))); + + /* AccessAttribute (AttribQuick, AttribByte, etc.) */ + + Info->Attribute = (UINT8) ((Arg->Common.Value.Integer >> 8) & 0xFF); + + /* AccessLength (for serial/buffer protocols) */ + + Info->AccessLength = (UINT8) ((Arg->Common.Value.Integer >> 16) & 0xFF); + break; + + case AML_INT_CONNECTION_OP: + /* + * Clear any previous connection. New connection is used for all + * fields that follow, similar to AccessAs + */ + Info->ResourceBuffer = NULL; + Info->ConnectionNode = NULL; + + /* + * A Connection() is either an actual resource descriptor (buffer) + * or a named reference to a resource template + */ + Child = Arg->Common.Value.Arg; + if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP) + { + Info->ResourceBuffer = Child->Named.Data; + Info->ResourceLength = (UINT16) Child->Named.Value.Integer; + } + else + { + /* Lookup the Connection() namepath, it should already exist */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, + Child->Common.Value.Name, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &Info->ConnectionNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Child->Common.Value.Name, Status); + return_ACPI_STATUS (Status); + } + } + break; + + case AML_INT_NAMEDFIELD_OP: + + /* Lookup the name, it should already exist */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, + (char *) &Arg->Named.Name, Info->FieldType, + ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &Info->FieldNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status); + return_ACPI_STATUS (Status); + } + else + { + Arg->Common.Node = Info->FieldNode; + Info->FieldBitLength = Arg->Common.Value.Size; + + /* + * If there is no object attached to the node, this node was + * just created and we need to create the field object. + * Otherwise, this was a lookup of an existing node and we + * don't want to create the field object again. + */ + if (!AcpiNsGetAttachedObject (Info->FieldNode)) + { + Status = AcpiExPrepFieldValue (Info); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + + /* Keep track of bit position for the next field */ + + Position = (UINT64) Info->FieldBitPosition + + (UINT64) Arg->Common.Value.Size; + + if (Position > ACPI_UINT32_MAX) + { + ACPI_ERROR ((AE_INFO, + "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", + ACPI_CAST_PTR (char, &Info->FieldNode->Name))); + return_ACPI_STATUS (AE_SUPPORT); + } + + Info->FieldBitPosition += Info->FieldBitLength; + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Invalid opcode in field list: 0x%X", Arg->Common.AmlOpcode)); + return_ACPI_STATUS (AE_AML_BAD_OPCODE); + } + + Arg = Arg->Common.Next; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateField + * + * PARAMETERS: Op - Op containing the Field definition and args + * RegionNode - Object for the containing Operation Region + * ` WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Arg; + ACPI_CREATE_FIELD_INFO Info; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateField, Op); + + + /* First arg is the name of the parent OpRegion (must already exist) */ + + Arg = Op->Common.Value.Arg; + if (!RegionNode) + { + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name, + ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status); + return_ACPI_STATUS (Status); + } + } + + ACPI_MEMSET (&Info, 0, sizeof (ACPI_CREATE_FIELD_INFO)); + + /* Second arg is the field flags */ + + Arg = Arg->Common.Next; + Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; + Info.Attribute = 0; + + /* Each remaining arg is a Named Field */ + + Info.FieldType = ACPI_TYPE_LOCAL_REGION_FIELD; + Info.RegionNode = RegionNode; + + Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitFieldObjects + * + * PARAMETERS: Op - Op containing the Field definition and args + * ` WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: For each "Field Unit" name in the argument list that is + * part of the field declaration, enter the name into the + * namespace. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitFieldObjects ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Arg = NULL; + ACPI_NAMESPACE_NODE *Node; + UINT8 Type = 0; + UINT32 Flags; + + + ACPI_FUNCTION_TRACE_PTR (DsInitFieldObjects, Op); + + + /* Execute flag should always be set when this function is entered */ + + if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE)) + { + if (WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP) + { + /* BankField Op is deferred, just return OK */ + + return_ACPI_STATUS (AE_OK); + } + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* + * Get the FieldList argument for this opcode. This is the start of the + * list of field elements. + */ + switch (WalkState->Opcode) + { + case AML_FIELD_OP: + Arg = AcpiPsGetArg (Op, 2); + Type = ACPI_TYPE_LOCAL_REGION_FIELD; + break; + + case AML_BANK_FIELD_OP: + Arg = AcpiPsGetArg (Op, 4); + Type = ACPI_TYPE_LOCAL_BANK_FIELD; + break; + + case AML_INDEX_FIELD_OP: + Arg = AcpiPsGetArg (Op, 3); + Type = ACPI_TYPE_LOCAL_INDEX_FIELD; + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Creating new namespace node(s), should not already exist */ + + Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* + * Mark node(s) temporary if we are executing a normal control + * method. (Don't mark if this is a module-level code method) + */ + if (WalkState->MethodNode && + !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) + { + Flags |= ACPI_NS_TEMPORARY; + } + + /* + * Walk the list of entries in the FieldList + * Note: FieldList can be of zero length. In this case, Arg will be NULL. + */ + while (Arg) + { + /* + * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested + * in the field names in order to enter them into the namespace. + */ + if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) + { + Status = AcpiNsLookup (WalkState->ScopeInfo, + (char *) &Arg->Named.Name, Type, ACPI_IMODE_LOAD_PASS1, + Flags, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status); + if (Status != AE_ALREADY_EXISTS) + { + return_ACPI_STATUS (Status); + } + + /* Name already exists, just ignore this error */ + + Status = AE_OK; + } + + Arg->Common.Node = Node; + } + + /* Get the next field element in the list */ + + Arg = Arg->Common.Next; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateBankField + * + * PARAMETERS: Op - Op containing the Field definition and args + * RegionNode - Object for the containing Operation Region + * WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new bank field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateBankField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Arg; + ACPI_CREATE_FIELD_INFO Info; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateBankField, Op); + + + /* First arg is the name of the parent OpRegion (must already exist) */ + + Arg = Op->Common.Value.Arg; + if (!RegionNode) + { + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name, + ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status); + return_ACPI_STATUS (Status); + } + } + + /* Second arg is the Bank Register (Field) (must already exist) */ + + Arg = Arg->Common.Next; + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); + return_ACPI_STATUS (Status); + } + + /* + * Third arg is the BankValue + * This arg is a TermArg, not a constant + * It will be evaluated later, by AcpiDsEvalBankFieldOperands + */ + Arg = Arg->Common.Next; + + /* Fourth arg is the field flags */ + + Arg = Arg->Common.Next; + Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; + + /* Each remaining arg is a Named Field */ + + Info.FieldType = ACPI_TYPE_LOCAL_BANK_FIELD; + Info.RegionNode = RegionNode; + + /* + * Use Info.DataRegisterNode to store BankField Op + * It's safe because DataRegisterNode will never be used when create bank field + * We store AmlStart and AmlLength in the BankField Op for late evaluation + * Used in AcpiExPrepFieldValue(Info) + * + * TBD: Or, should we add a field in ACPI_CREATE_FIELD_INFO, like "void *ParentOp"? + */ + Info.DataRegisterNode = (ACPI_NAMESPACE_NODE*) Op; + + Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateIndexField + * + * PARAMETERS: Op - Op containing the Field definition and args + * RegionNode - Object for the containing Operation Region + * ` WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new index field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateIndexField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Arg; + ACPI_CREATE_FIELD_INFO Info; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateIndexField, Op); + + + /* First arg is the name of the Index register (must already exist) */ + + Arg = Op->Common.Value.Arg; + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); + return_ACPI_STATUS (Status); + } + + /* Second arg is the data register (must already exist) */ + + Arg = Arg->Common.Next; + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, WalkState, &Info.DataRegisterNode); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); + return_ACPI_STATUS (Status); + } + + /* Next arg is the field flags */ + + Arg = Arg->Common.Next; + Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; + + /* Each remaining arg is a Named Field */ + + Info.FieldType = ACPI_TYPE_LOCAL_INDEX_FIELD; + Info.RegionNode = RegionNode; + + Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/dispatcher/dsinit.c b/source/components/dispatcher/dsinit.c new file mode 100644 index 000000000000..1c7ad8849258 --- /dev/null +++ b/source/components/dispatcher/dsinit.c @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * Module Name: dsinit - Object initialization namespace walk + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSINIT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsinit") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsInitOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitOneObject + * + * PARAMETERS: ObjHandle - Node for the object + * Level - Current nesting level + * Context - Points to a init info struct + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Operation Regions + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsInitOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_OBJECT_TYPE Type; + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * We are only interested in NS nodes owned by the table that + * was just loaded + */ + if (Node->OwnerId != Info->OwnerId) + { + return (AE_OK); + } + + Info->ObjectCount++; + + /* And even then, we are only interested in a few object types */ + + Type = AcpiNsGetType (ObjHandle); + + switch (Type) + { + case ACPI_TYPE_REGION: + + Status = AcpiDsInitializeRegion (ObjHandle); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "During Region initialization %p [%4.4s]", + ObjHandle, AcpiUtGetNodeName (ObjHandle))); + } + + Info->OpRegionCount++; + break; + + + case ACPI_TYPE_METHOD: + + Info->MethodCount++; + break; + + + case ACPI_TYPE_DEVICE: + + Info->DeviceCount++; + break; + + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitializeObjects + * + * PARAMETERS: TableDesc - Descriptor for parent ACPI table + * StartNode - Root of subtree to be initialized. + * + * RETURN: Status + * + * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any + * necessary initialization on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitializeObjects ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode) +{ + ACPI_STATUS Status; + ACPI_INIT_WALK_INFO Info; + ACPI_TABLE_HEADER *Table; + ACPI_OWNER_ID OwnerId; + + + ACPI_FUNCTION_TRACE (DsInitializeObjects); + + + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "**** Starting initialization of namespace objects ****\n")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:")); + + /* Set all init info to zero */ + + ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + + Info.OwnerId = OwnerId; + Info.TableIndex = TableIndex; + + /* Walk entire namespace from the supplied root */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * We don't use AcpiWalkNamespace since we do not want to acquire + * the namespace reader lock. + */ + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, StartNode, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, AcpiDsInitOneObject, NULL, &Info, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace")); + } + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "\nTable [%4.4s](id %4.4X) - %u Objects with %u Devices %u Methods %u Regions\n", + Table->Signature, OwnerId, Info.ObjectCount, + Info.DeviceCount, Info.MethodCount, Info.OpRegionCount)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "%u Methods, %u Regions\n", Info.MethodCount, Info.OpRegionCount)); + + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/dispatcher/dsmethod.c b/source/components/dispatcher/dsmethod.c new file mode 100644 index 000000000000..670382ac9bfb --- /dev/null +++ b/source/components/dispatcher/dsmethod.c @@ -0,0 +1,726 @@ +/****************************************************************************** + * + * Module Name: dsmethod - Parser/Interpreter interface - control method parsing + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSMETHOD_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdisasm.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsmethod") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsCreateMethodMutex ( + ACPI_OPERAND_OBJECT *MethodDesc); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodError + * + * PARAMETERS: Status - Execution status + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Called on method error. Invoke the global exception handler if + * present, dump the method data if the disassembler is configured + * + * Note: Allows the exception handler to change the status code + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Ignore AE_OK and control exception codes */ + + if (ACPI_SUCCESS (Status) || + (Status & AE_CODE_CONTROL)) + { + return (Status); + } + + /* Invoke the global exception handler */ + + if (AcpiGbl_ExceptionHandler) + { + /* Exit the interpreter, allow handler to execute methods */ + + AcpiExExitInterpreter (); + + /* + * Handler can map the exception code to anything it wants, including + * AE_OK, in which case the executing method will not be aborted. + */ + Status = AcpiGbl_ExceptionHandler (Status, + WalkState->MethodNode ? + WalkState->MethodNode->Name.Integer : 0, + WalkState->Opcode, WalkState->AmlOffset, NULL); + AcpiExEnterInterpreter (); + } + + AcpiDsClearImplicitReturn (WalkState); + +#ifdef ACPI_DISASSEMBLER + if (ACPI_FAILURE (Status)) + { + /* Display method locals/args if disassembler is present */ + + AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op); + } +#endif + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateMethodMutex + * + * PARAMETERS: ObjDesc - The method object + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object for a serialized control method + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsCreateMethodMutex ( + ACPI_OPERAND_OBJECT *MethodDesc) +{ + ACPI_OPERAND_OBJECT *MutexDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (DsCreateMethodMutex); + + + /* Create the new mutex object */ + + MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); + if (!MutexDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Create the actual OS Mutex */ + + Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel; + MethodDesc->Method.Mutex = MutexDesc; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsBeginMethodExecution + * + * PARAMETERS: MethodNode - Node of the method + * ObjDesc - The method object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: Status + * + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * increments the thread count, and waits at the method semaphore + * for clearance to execute. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsBeginMethodExecution ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode); + + + if (!MethodNode) + { + return_ACPI_STATUS (AE_NULL_ENTRY); + } + + /* Prevent wraparound of thread count */ + + if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) + { + ACPI_ERROR ((AE_INFO, + "Method reached maximum reentrancy limit (255)")); + return_ACPI_STATUS (AE_AML_METHOD_LIMIT); + } + + /* + * If this method is serialized, we need to acquire the method mutex. + */ + if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) + { + /* + * Create a mutex for the method if it is defined to be Serialized + * and a mutex has not already been created. We defer the mutex creation + * until a method is actually executed, to minimize the object count + */ + if (!ObjDesc->Method.Mutex) + { + Status = AcpiDsCreateMethodMutex (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * The CurrentSyncLevel (per-thread) must be less than or equal to + * the sync level of the method. This mechanism provides some + * deadlock prevention + * + * Top-level method invocation has no walk state at this point + */ + if (WalkState && + (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel)) + { + ACPI_ERROR ((AE_INFO, + "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", + AcpiUtGetNodeName (MethodNode), + WalkState->Thread->CurrentSyncLevel)); + + return_ACPI_STATUS (AE_AML_MUTEX_ORDER); + } + + /* + * Obtain the method mutex if necessary. Do not acquire mutex for a + * recursive call. + */ + if (!WalkState || + !ObjDesc->Method.Mutex->Mutex.ThreadId || + (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId)) + { + /* + * Acquire the method mutex. This releases the interpreter if we + * block (and reacquires it before it returns) + */ + Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Update the mutex and walk info and save the original SyncLevel */ + + if (WalkState) + { + ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = + WalkState->Thread->CurrentSyncLevel; + + ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId; + WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel; + } + else + { + ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = + ObjDesc->Method.Mutex->Mutex.SyncLevel; + } + } + + /* Always increase acquisition depth */ + + ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++; + } + + /* + * Allocate an Owner ID for this method, only if this is the first thread + * to begin concurrent execution. We only need one OwnerId, even if the + * method is invoked recursively. + */ + if (!ObjDesc->Method.OwnerId) + { + Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + + /* + * Increment the method parse tree thread count since it has been + * reentered one more time (even if it is the same thread) + */ + ObjDesc->Method.ThreadCount++; + AcpiMethodCount++; + return_ACPI_STATUS (Status); + + +Cleanup: + /* On error, must release the method mutex (if present) */ + + if (ObjDesc->Method.Mutex) + { + AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex); + } + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCallControlMethod + * + * PARAMETERS: Thread - Info for this thread + * ThisWalkState - Current walk state + * Op - Current Op to be walked + * + * RETURN: Status + * + * DESCRIPTION: Transfer execution to a called control method + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCallControlMethod ( + ACPI_THREAD_STATE *Thread, + ACPI_WALK_STATE *ThisWalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *MethodNode; + ACPI_WALK_STATE *NextWalkState = NULL; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_EVALUATE_INFO *Info; + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n", + ThisWalkState->PrevOp, ThisWalkState)); + + /* + * Get the namespace entry for the control method we are about to call + */ + MethodNode = ThisWalkState->MethodCallNode; + if (!MethodNode) + { + return_ACPI_STATUS (AE_NULL_ENTRY); + } + + ObjDesc = AcpiNsGetAttachedObject (MethodNode); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Init for new method, possibly wait on method mutex */ + + Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, + ThisWalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Begin method parse/execution. Create a new walk state */ + + NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId, + NULL, ObjDesc, Thread); + if (!NextWalkState) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * The resolved arguments were put on the previous walk state's operand + * stack. Operands on the previous walk state stack always + * start at index 0. Also, null terminate the list of arguments + */ + ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL; + + /* + * Allocate and initialize the evaluation information block + * TBD: this is somewhat inefficient, should change interface to + * DsInitAmlWalk. For now, keeps this struct off the CPU stack + */ + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->Parameters = &ThisWalkState->Operands[0]; + + Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode, + ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, + Info, ACPI_IMODE_EXECUTE); + + ACPI_FREE (Info); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * Delete the operands on the previous walkstate operand stack + * (they were copied to new objects) + */ + for (i = 0; i < ObjDesc->Method.ParamCount; i++) + { + AcpiUtRemoveReference (ThisWalkState->Operands [i]); + ThisWalkState->Operands [i] = NULL; + } + + /* Clear the operand stack */ + + ThisWalkState->NumOperands = 0; + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", + MethodNode->Name.Ascii, NextWalkState)); + + /* Invoke an internal method if necessary */ + + if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) + { + Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState); + if (Status == AE_OK) + { + Status = AE_CTRL_TERMINATE; + } + } + + return_ACPI_STATUS (Status); + + +Cleanup: + + /* On error, we must terminate the method properly */ + + AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); + if (NextWalkState) + { + AcpiDsDeleteWalkState (NextWalkState); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsRestartControlMethod + * + * PARAMETERS: WalkState - State for preempted method (caller) + * ReturnDesc - Return value from the called method + * + * RETURN: Status + * + * DESCRIPTION: Restart a method that was preempted by another (nested) method + * invocation. Handle the return value (if any) from the callee. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsRestartControlMethod ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ReturnDesc) +{ + ACPI_STATUS Status; + int SameAsImplicitReturn; + + + ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState); + + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", + AcpiUtGetNodeName (WalkState->MethodNode), + WalkState->MethodCallOp, ReturnDesc)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", + WalkState->ReturnUsed, + WalkState->Results, WalkState)); + + /* Did the called method return a value? */ + + if (ReturnDesc) + { + /* Is the implicit return object the same as the return desc? */ + + SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc); + + /* Are we actually going to use the return value? */ + + if (WalkState->ReturnUsed) + { + /* Save the return value from the previous method */ + + Status = AcpiDsResultPush (ReturnDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + return_ACPI_STATUS (Status); + } + + /* + * Save as THIS method's return value in case it is returned + * immediately to yet another method + */ + WalkState->ReturnDesc = ReturnDesc; + } + + /* + * The following code is the optional support for the so-called + * "implicit return". Some AML code assumes that the last value of the + * method is "implicitly" returned to the caller, in the absence of an + * explicit return value. + * + * Just save the last result of the method as the return value. + * + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) || + SameAsImplicitReturn) + { + /* + * Delete the return value if it will not be used by the + * calling method or remove one reference if the explicit return + * is the same as the implicit return value. + */ + AcpiUtRemoveReference (ReturnDesc); + } + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsTerminateControlMethod + * + * PARAMETERS: MethodDesc - Method object + * WalkState - State associated with the method + * + * RETURN: None + * + * DESCRIPTION: Terminate a control method. Delete everything that the method + * created, delete all locals and arguments, and delete the parse + * tree if requested. + * + * MUTEX: Interpreter is locked + * + ******************************************************************************/ + +void +AcpiDsTerminateControlMethod ( + ACPI_OPERAND_OBJECT *MethodDesc, + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); + + + /* MethodDesc is required, WalkState is optional */ + + if (!MethodDesc) + { + return_VOID; + } + + if (WalkState) + { + /* Delete all arguments and locals */ + + AcpiDsMethodDataDeleteAll (WalkState); + + /* + * If method is serialized, release the mutex and restore the + * current sync level for this thread + */ + if (MethodDesc->Method.Mutex) + { + /* Acquisition Depth handles recursive calls */ + + MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; + if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) + { + WalkState->Thread->CurrentSyncLevel = + MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; + + AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex); + MethodDesc->Method.Mutex->Mutex.ThreadId = 0; + } + } + + /* + * Delete any namespace objects created anywhere within the + * namespace by the execution of this method. Unless: + * 1) This method is a module-level executable code method, in which + * case we want make the objects permanent. + * 2) There are other threads executing the method, in which case we + * will wait until the last thread has completed. + */ + if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) && + (MethodDesc->Method.ThreadCount == 1)) + { + /* Delete any direct children of (created by) this method */ + + AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode); + + /* + * Delete any objects that were created by this method + * elsewhere in the namespace (if any were created). + * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the + * deletion such that we don't have to perform an entire + * namespace walk for every control method execution. + */ + if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE) + { + AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); + MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE; + } + } + } + + /* Decrement the thread count on the method */ + + if (MethodDesc->Method.ThreadCount) + { + MethodDesc->Method.ThreadCount--; + } + else + { + ACPI_ERROR ((AE_INFO, + "Invalid zero thread count in method")); + } + + /* Are there any other threads currently executing this method? */ + + if (MethodDesc->Method.ThreadCount) + { + /* + * Additional threads. Do not release the OwnerId in this case, + * we immediately reuse it for the next thread executing this method + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "*** Completed execution of one thread, %u threads remaining\n", + MethodDesc->Method.ThreadCount)); + } + else + { + /* This is the only executing thread for this method */ + + /* + * Support to dynamically change a method from NotSerialized to + * Serialized if it appears that the method is incorrectly written and + * does not support multiple thread execution. The best example of this + * is if such a method creates namespace objects and blocks. A second + * thread will fail with an AE_ALREADY_EXISTS exception. + * + * This code is here because we must wait until the last thread exits + * before marking the method as serialized. + */ + if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING) + { + if (WalkState) + { + ACPI_INFO ((AE_INFO, + "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", + WalkState->MethodNode->Name.Ascii)); + } + + /* + * Method tried to create an object twice and was marked as + * "pending serialized". The probable cause is that the method + * cannot handle reentrancy. + * + * The method was created as NotSerialized, but it tried to create + * a named object and then blocked, causing the second thread + * entrance to begin and then fail. Workaround this problem by + * marking the method permanently as Serialized when the last + * thread exits here. + */ + MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING; + MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED; + MethodDesc->Method.SyncLevel = 0; + } + + /* No more threads, we can free the OwnerId */ + + if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)) + { + AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); + } + } + + return_VOID; +} + + diff --git a/source/components/dispatcher/dsmthdat.c b/source/components/dispatcher/dsmthdat.c new file mode 100644 index 000000000000..b4509e771021 --- /dev/null +++ b/source/components/dispatcher/dsmthdat.c @@ -0,0 +1,772 @@ +/******************************************************************************* + * + * Module Name: dsmthdat - control method arguments and local variables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSMTHDAT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsmthdat") + +/* Local prototypes */ + +static void +AcpiDsMethodDataDeleteValue ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +AcpiDsMethodDataSetValue ( + UINT8 Type, + UINT32 Index, + ACPI_OPERAND_OBJECT *Object, + ACPI_WALK_STATE *WalkState); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +ACPI_OBJECT_TYPE +AcpiDsMethodDataGetType ( + UINT16 Opcode, + UINT32 Index, + ACPI_WALK_STATE *WalkState); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataInit + * + * PARAMETERS: WalkState - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize the data structures that hold the method's arguments + * and locals. The data struct is an array of namespace nodes for + * each - this allows RefOf and DeRefOf to work properly for these + * special data types. + * + * NOTES: WalkState fields are initialized to zero by the + * ACPI_ALLOCATE_ZEROED(). + * + * A pseudo-Namespace Node is assigned to each argument and local + * so that RefOf() can return a pointer to the Node. + * + ******************************************************************************/ + +void +AcpiDsMethodDataInit ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE (DsMethodDataInit); + + + /* Init the method arguments */ + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + ACPI_MOVE_32_TO_32 (&WalkState->Arguments[i].Name, NAMEOF_ARG_NTE); + WalkState->Arguments[i].Name.Integer |= (i << 24); + WalkState->Arguments[i].DescriptorType = ACPI_DESC_TYPE_NAMED; + WalkState->Arguments[i].Type = ACPI_TYPE_ANY; + WalkState->Arguments[i].Flags = ANOBJ_METHOD_ARG; + } + + /* Init the method locals */ + + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) + { + ACPI_MOVE_32_TO_32 (&WalkState->LocalVariables[i].Name, NAMEOF_LOCAL_NTE); + + WalkState->LocalVariables[i].Name.Integer |= (i << 24); + WalkState->LocalVariables[i].DescriptorType = ACPI_DESC_TYPE_NAMED; + WalkState->LocalVariables[i].Type = ACPI_TYPE_ANY; + WalkState->LocalVariables[i].Flags = ANOBJ_METHOD_LOCAL; + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataDeleteAll + * + * PARAMETERS: WalkState - Current walk state object + * + * RETURN: None + * + * DESCRIPTION: Delete method locals and arguments. Arguments are only + * deleted if this method was called from another method. + * + ******************************************************************************/ + +void +AcpiDsMethodDataDeleteAll ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 Index; + + + ACPI_FUNCTION_TRACE (DsMethodDataDeleteAll); + + + /* Detach the locals */ + + for (Index = 0; Index < ACPI_METHOD_NUM_LOCALS; Index++) + { + if (WalkState->LocalVariables[Index].Object) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%u=%p\n", + Index, WalkState->LocalVariables[Index].Object)); + + /* Detach object (if present) and remove a reference */ + + AcpiNsDetachObject (&WalkState->LocalVariables[Index]); + } + } + + /* Detach the arguments */ + + for (Index = 0; Index < ACPI_METHOD_NUM_ARGS; Index++) + { + if (WalkState->Arguments[Index].Object) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%u=%p\n", + Index, WalkState->Arguments[Index].Object)); + + /* Detach object (if present) and remove a reference */ + + AcpiNsDetachObject (&WalkState->Arguments[Index]); + } + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataInitArgs + * + * PARAMETERS: *Params - Pointer to a parameter list for the method + * MaxParamCount - The arg count for this method + * WalkState - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize arguments for a method. The parameter list is a list + * of ACPI operand objects, either null terminated or whose length + * is defined by MaxParamCount. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsMethodDataInitArgs ( + ACPI_OPERAND_OBJECT **Params, + UINT32 MaxParamCount, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + UINT32 Index = 0; + + + ACPI_FUNCTION_TRACE_PTR (DsMethodDataInitArgs, Params); + + + if (!Params) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n")); + return_ACPI_STATUS (AE_OK); + } + + /* Copy passed parameters into the new method stack frame */ + + while ((Index < ACPI_METHOD_NUM_ARGS) && + (Index < MaxParamCount) && + Params[Index]) + { + /* + * A valid parameter. + * Store the argument in the method/walk descriptor. + * Do not copy the arg in order to implement call by reference + */ + Status = AcpiDsMethodDataSetValue (ACPI_REFCLASS_ARG, Index, + Params[Index], WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Index++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%u args passed to method\n", Index)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataGetNode + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg whose type to get + * WalkState - Current walk state object + * Node - Where the node is returned. + * + * RETURN: Status and node + * + * DESCRIPTION: Get the Node associated with a local or arg. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsMethodDataGetNode ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **Node) +{ + ACPI_FUNCTION_TRACE (DsMethodDataGetNode); + + + /* + * Method Locals and Arguments are supported + */ + switch (Type) + { + case ACPI_REFCLASS_LOCAL: + + if (Index > ACPI_METHOD_MAX_LOCAL) + { + ACPI_ERROR ((AE_INFO, + "Local index %u is invalid (max %u)", + Index, ACPI_METHOD_MAX_LOCAL)); + return_ACPI_STATUS (AE_AML_INVALID_INDEX); + } + + /* Return a pointer to the pseudo-node */ + + *Node = &WalkState->LocalVariables[Index]; + break; + + case ACPI_REFCLASS_ARG: + + if (Index > ACPI_METHOD_MAX_ARG) + { + ACPI_ERROR ((AE_INFO, + "Arg index %u is invalid (max %u)", + Index, ACPI_METHOD_MAX_ARG)); + return_ACPI_STATUS (AE_AML_INVALID_INDEX); + } + + /* Return a pointer to the pseudo-node */ + + *Node = &WalkState->Arguments[Index]; + break; + + default: + ACPI_ERROR ((AE_INFO, "Type %u is invalid", Type)); + return_ACPI_STATUS (AE_TYPE); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataSetValue + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg to get + * Object - Object to be inserted into the stack entry + * WalkState - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. + * Note: There is no "implicit conversion" for locals. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsMethodDataSetValue ( + UINT8 Type, + UINT32 Index, + ACPI_OPERAND_OBJECT *Object, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (DsMethodDataSetValue); + + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "NewObj %p Type %2.2X, Refs=%u [%s]\n", Object, + Type, Object->Common.ReferenceCount, + AcpiUtGetTypeName (Object->Common.Type))); + + /* Get the namespace node for the arg/local */ + + Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Increment ref count so object can't be deleted while installed. + * NOTE: We do not copy the object in order to preserve the call by + * reference semantics of ACPI Control Method invocation. + * (See ACPI Specification 2.0C) + */ + AcpiUtAddReference (Object); + + /* Install the object */ + + Node->Object = Object; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataGetValue + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which localVar or argument to get + * WalkState - Current walk state object + * DestDesc - Where Arg or Local value is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve value of selected Arg or Local for this method + * Used only in AcpiExResolveToValue(). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsMethodDataGetValue ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **DestDesc) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *Object; + + + ACPI_FUNCTION_TRACE (DsMethodDataGetValue); + + + /* Validate the object descriptor */ + + if (!DestDesc) + { + ACPI_ERROR ((AE_INFO, "Null object descriptor pointer")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the namespace node for the arg/local */ + + Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the object from the node */ + + Object = Node->Object; + + /* Examine the returned object, it must be valid. */ + + if (!Object) + { + /* + * Index points to uninitialized object. + * This means that either 1) The expected argument was + * not passed to the method, or 2) A local variable + * was referenced by the method (via the ASL) + * before it was initialized. Either case is an error. + */ + + /* If slack enabled, init the LocalX/ArgX to an Integer of value zero */ + + if (AcpiGbl_EnableInterpreterSlack) + { + Object = AcpiUtCreateIntegerObject ((UINT64) 0); + if (!Object) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Node->Object = Object; + } + + /* Otherwise, return the error */ + + else switch (Type) + { + case ACPI_REFCLASS_ARG: + + ACPI_ERROR ((AE_INFO, + "Uninitialized Arg[%u] at node %p", + Index, Node)); + + return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG); + + case ACPI_REFCLASS_LOCAL: + + /* + * No error message for this case, will be trapped again later to + * detect and ignore cases of Store(LocalX,LocalX) + */ + return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); + + default: + + ACPI_ERROR ((AE_INFO, "Not a Arg/Local opcode: 0x%X", Type)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + } + + /* + * The Index points to an initialized and valid object. + * Return an additional reference to the object + */ + *DestDesc = Object; + AcpiUtAddReference (Object); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataDeleteValue + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which localVar or argument to delete + * WalkState - Current walk state object + * + * RETURN: None + * + * DESCRIPTION: Delete the entry at Opcode:Index. Inserts + * a null into the stack slot after the object is deleted. + * + ******************************************************************************/ + +static void +AcpiDsMethodDataDeleteValue ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *Object; + + + ACPI_FUNCTION_TRACE (DsMethodDataDeleteValue); + + + /* Get the namespace node for the arg/local */ + + Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* Get the associated object */ + + Object = AcpiNsGetAttachedObject (Node); + + /* + * Undefine the Arg or Local by setting its descriptor + * pointer to NULL. Locals/Args can contain both + * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs + */ + Node->Object = NULL; + + if ((Object) && + (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_OPERAND)) + { + /* + * There is a valid object. + * Decrement the reference count by one to balance the + * increment when the object was stored. + */ + AcpiUtRemoveReference (Object); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsStoreObjectToLocal + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg to set + * ObjDesc - Value to be stored + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store a value in an Arg or Local. The ObjDesc is installed + * as the new value for the Arg or Local and the reference count + * for ObjDesc is incremented. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsStoreObjectToLocal ( + UINT8 Type, + UINT32 Index, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *CurrentObjDesc; + ACPI_OPERAND_OBJECT *NewObjDesc; + + + ACPI_FUNCTION_TRACE (DsStoreObjectToLocal); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n", + Type, Index, ObjDesc)); + + /* Parameter validation */ + + if (!ObjDesc) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the namespace node for the arg/local */ + + Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + CurrentObjDesc = AcpiNsGetAttachedObject (Node); + if (CurrentObjDesc == ObjDesc) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", + ObjDesc)); + return_ACPI_STATUS (Status); + } + + /* + * If the reference count on the object is more than one, we must + * take a copy of the object before we store. A reference count + * of exactly 1 means that the object was just created during the + * evaluation of an expression, and we can safely use it since it + * is not used anywhere else. + */ + NewObjDesc = ObjDesc; + if (ObjDesc->Common.ReferenceCount > 1) + { + Status = AcpiUtCopyIobjectToIobject (ObjDesc, &NewObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * If there is an object already in this slot, we either + * have to delete it, or if this is an argument and there + * is an object reference stored there, we have to do + * an indirect store! + */ + if (CurrentObjDesc) + { + /* + * Check for an indirect store if an argument + * contains an object reference (stored as an Node). + * We don't allow this automatic dereferencing for + * locals, since a store to a local should overwrite + * anything there, including an object reference. + * + * If both Arg0 and Local0 contain RefOf (Local4): + * + * Store (1, Arg0) - Causes indirect store to local4 + * Store (1, Local0) - Stores 1 in local0, overwriting + * the reference to local4 + * Store (1, DeRefof (Local0)) - Causes indirect store to local4 + * + * Weird, but true. + */ + if (Type == ACPI_REFCLASS_ARG) + { + /* + * If we have a valid reference object that came from RefOf(), + * do the indirect store + */ + if ((ACPI_GET_DESCRIPTOR_TYPE (CurrentObjDesc) == ACPI_DESC_TYPE_OPERAND) && + (CurrentObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + (CurrentObjDesc->Reference.Class == ACPI_REFCLASS_REFOF)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Arg (%p) is an ObjRef(Node), storing in node %p\n", + NewObjDesc, CurrentObjDesc)); + + /* + * Store this object to the Node (perform the indirect store) + * NOTE: No implicit conversion is performed, as per the ACPI + * specification rules on storing to Locals/Args. + */ + Status = AcpiExStoreObjectToNode (NewObjDesc, + CurrentObjDesc->Reference.Object, WalkState, + ACPI_NO_IMPLICIT_CONVERSION); + + /* Remove local reference if we copied the object above */ + + if (NewObjDesc != ObjDesc) + { + AcpiUtRemoveReference (NewObjDesc); + } + return_ACPI_STATUS (Status); + } + } + + /* Delete the existing object before storing the new one */ + + AcpiDsMethodDataDeleteValue (Type, Index, WalkState); + } + + /* + * Install the Obj descriptor (*NewObjDesc) into + * the descriptor for the Arg or Local. + * (increments the object reference count by one) + */ + Status = AcpiDsMethodDataSetValue (Type, Index, NewObjDesc, WalkState); + + /* Remove local reference if we copied the object above */ + + if (NewObjDesc != ObjDesc) + { + AcpiUtRemoveReference (NewObjDesc); + } + + return_ACPI_STATUS (Status); +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiDsMethodDataGetType + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which Local or Arg whose type to get + * WalkState - Current walk state object + * + * RETURN: Data type of current value of the selected Arg or Local + * + * DESCRIPTION: Get the type of the object stored in the Local or Arg + * + ******************************************************************************/ + +ACPI_OBJECT_TYPE +AcpiDsMethodDataGetType ( + UINT16 Opcode, + UINT32 Index, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *Object; + + + ACPI_FUNCTION_TRACE (DsMethodDataGetType); + + + /* Get the namespace node for the arg/local */ + + Status = AcpiDsMethodDataGetNode (Opcode, Index, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_VALUE ((ACPI_TYPE_NOT_FOUND)); + } + + /* Get the object */ + + Object = AcpiNsGetAttachedObject (Node); + if (!Object) + { + /* Uninitialized local/arg, return TYPE_ANY */ + + return_VALUE (ACPI_TYPE_ANY); + } + + /* Get the object type */ + + return_VALUE (Object->Type); +} +#endif + + diff --git a/source/components/dispatcher/dsobject.c b/source/components/dispatcher/dsobject.c new file mode 100644 index 000000000000..b3567766a2db --- /dev/null +++ b/source/components/dispatcher/dsobject.c @@ -0,0 +1,867 @@ +/****************************************************************************** + * + * Module Name: dsobject - Dispatcher object management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSOBJECT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsobject") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsBuildInternalObject ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT **ObjDescPtr); + + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: AcpiDsBuildInternalObject + * + * PARAMETERS: WalkState - Current walk state + * Op - Parser object to be translated + * ObjDescPtr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace object + * Simple objects are any objects other than a package object! + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsBuildInternalObject ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE Type; + + + ACPI_FUNCTION_TRACE (DsBuildInternalObject); + + + *ObjDescPtr = NULL; + if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) + { + /* + * This is a named object reference. If this name was + * previously looked up in the namespace, it was stored in this op. + * Otherwise, go ahead and look it up now + */ + if (!Op->Common.Node) + { + Status = AcpiNsLookup (WalkState->ScopeInfo, + Op->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node))); + if (ACPI_FAILURE (Status)) + { + /* Check if we are resolving a named reference within a package */ + + if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) && + + ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) + { + /* + * We didn't find the target and we are populating elements + * of a package - ignore if slack enabled. Some ASL code + * contains dangling invalid references in packages and + * expects that no exception will be issued. Leave the + * element as a null element. It cannot be used, but it + * can be overwritten by subsequent ASL code - this is + * typically the case. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Ignoring unresolved reference in package [%4.4s]\n", + WalkState->ScopeInfo->Scope.Node->Name.Ascii)); + + return_ACPI_STATUS (AE_OK); + } + else + { + ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status); + } + + return_ACPI_STATUS (Status); + } + } + + /* Special object resolution for elements of a package */ + + if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) + { + /* + * Attempt to resolve the node to a value before we insert it into + * the package. If this is a reference to a common data type, + * resolve it immediately. According to the ACPI spec, package + * elements can only be "data objects" or method references. + * Attempt to resolve to an Integer, Buffer, String or Package. + * If cannot, return the named reference (for things like Devices, + * Methods, etc.) Buffer Fields and Fields will resolve to simple + * objects (int/buf/str/pkg). + * + * NOTE: References to things like Devices, Methods, Mutexes, etc. + * will remain as named references. This behavior is not described + * in the ACPI spec, but it appears to be an oversight. + */ + ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node); + + Status = AcpiExResolveNodeToValue ( + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc), + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Special handling for Alias objects. We need to setup the type + * and the Op->Common.Node to point to the Alias target. Note, + * Alias has at most one level of indirection internally. + */ + Type = Op->Common.Node->Type; + if (Type == ACPI_TYPE_LOCAL_ALIAS) + { + Type = ObjDesc->Common.Type; + Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, + Op->Common.Node->Object); + } + + switch (Type) + { + /* + * For these types, we need the actual node, not the subobject. + * However, the subobject did not get an extra reference count above. + * + * TBD: should ExResolveNodeToValue be changed to fix this? + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + AcpiUtAddReference (Op->Common.Node->Object); + + /*lint -fallthrough */ + /* + * For these types, we need the actual node, not the subobject. + * The subobject got an extra reference count in ExResolveNodeToValue. + */ + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + /* We will create a reference object for these types below */ + break; + + default: + /* + * All other types - the node was resolved to an actual + * object, we are done. + */ + goto Exit; + } + } + } + + /* Create and init a new internal ACPI object */ + + ObjDesc = AcpiUtCreateInternalObject ( + (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, + &ObjDesc); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); + } + +Exit: + *ObjDescPtr = ObjDesc; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsBuildInternalBufferObj + * + * PARAMETERS: WalkState - Current walk state + * Op - Parser object to be translated + * BufferLength - Length of the buffer + * ObjDescPtr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsBuildInternalBufferObj ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 BufferLength, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_PARSE_OBJECT *Arg; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PARSE_OBJECT *ByteList; + UINT32 ByteListLength = 0; + + + ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj); + + + /* + * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". + * The buffer object already exists (from the NS node), otherwise it must + * be created. + */ + ObjDesc = *ObjDescPtr; + if (!ObjDesc) + { + /* Create a new buffer object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); + *ObjDescPtr = ObjDesc; + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + /* + * Second arg is the buffer data (optional) ByteList can be either + * individual bytes or a string initializer. In either case, a + * ByteList appears in the AML. + */ + Arg = Op->Common.Value.Arg; /* skip first arg */ + + ByteList = Arg->Named.Next; + if (ByteList) + { + if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP) + { + ACPI_ERROR ((AE_INFO, + "Expecting bytelist, found AML opcode 0x%X in op %p", + ByteList->Common.AmlOpcode, ByteList)); + + AcpiUtRemoveReference (ObjDesc); + return (AE_TYPE); + } + + ByteListLength = (UINT32) ByteList->Common.Value.Integer; + } + + /* + * The buffer length (number of bytes) will be the larger of: + * 1) The specified buffer length and + * 2) The length of the initializer byte list + */ + ObjDesc->Buffer.Length = BufferLength; + if (ByteListLength > BufferLength) + { + ObjDesc->Buffer.Length = ByteListLength; + } + + /* Allocate the buffer */ + + if (ObjDesc->Buffer.Length == 0) + { + ObjDesc->Buffer.Pointer = NULL; + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Buffer defined with zero length in AML, creating\n")); + } + else + { + ObjDesc->Buffer.Pointer = ACPI_ALLOCATE_ZEROED ( + ObjDesc->Buffer.Length); + if (!ObjDesc->Buffer.Pointer) + { + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize buffer from the ByteList (if present) */ + + if (ByteList) + { + ACPI_MEMCPY (ObjDesc->Buffer.Pointer, ByteList->Named.Data, + ByteListLength); + } + } + + ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; + Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsBuildInternalPackageObj + * + * PARAMETERS: WalkState - Current walk state + * Op - Parser object to be translated + * ElementCount - Number of elements in the package - this is + * the NumElements argument to Package() + * ObjDescPtr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + * NOTE: The number of elements in the package will be always be the NumElements + * count, regardless of the number of elements in the package list. If + * NumElements is smaller, only that many package list elements are used. + * if NumElements is larger, the Package object is padded out with + * objects of type Uninitialized (as per ACPI spec.) + * + * Even though the ASL compilers do not allow NumElements to be smaller + * than the Package list length (for the fixed length package opcode), some + * BIOS code modifies the AML on the fly to adjust the NumElements, and + * this code compensates for that. This also provides compatibility with + * other AML interpreters. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsBuildInternalPackageObj ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 ElementCount, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_PARSE_OBJECT *Arg; + ACPI_PARSE_OBJECT *Parent; + ACPI_OPERAND_OBJECT *ObjDesc = NULL; + ACPI_STATUS Status = AE_OK; + UINT32 i; + UINT16 Index; + UINT16 ReferenceCount; + + + ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); + + + /* Find the parent of a possibly nested package */ + + Parent = Op->Common.Parent; + while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) + { + Parent = Parent->Common.Parent; + } + + /* + * If we are evaluating a Named package object "Name (xxxx, Package)", + * the package object already exists, otherwise it must be created. + */ + ObjDesc = *ObjDescPtr; + if (!ObjDesc) + { + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); + *ObjDescPtr = ObjDesc; + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ObjDesc->Package.Node = Parent->Common.Node; + } + + /* + * Allocate the element array (array of pointers to the individual + * objects) based on the NumElements parameter. Add an extra pointer slot + * so that the list is always null terminated. + */ + ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); + + if (!ObjDesc->Package.Elements) + { + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ObjDesc->Package.Count = ElementCount; + + /* + * Initialize the elements of the package, up to the NumElements count. + * Package is automatically padded with uninitialized (NULL) elements + * if NumElements is greater than the package list length. Likewise, + * Package is truncated if NumElements is less than the list length. + */ + Arg = Op->Common.Value.Arg; + Arg = Arg->Common.Next; + for (i = 0; Arg && (i < ElementCount); i++) + { + if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) + { + if (Arg->Common.Node->Type == ACPI_TYPE_METHOD) + { + /* + * A method reference "looks" to the parser to be a method + * invocation, so we special case it here + */ + Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP; + Status = AcpiDsBuildInternalObject (WalkState, Arg, + &ObjDesc->Package.Elements[i]); + } + else + { + /* This package element is already built, just get it */ + + ObjDesc->Package.Elements[i] = + ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); + } + } + else + { + Status = AcpiDsBuildInternalObject (WalkState, Arg, + &ObjDesc->Package.Elements[i]); + } + + if (*ObjDescPtr) + { + /* Existing package, get existing reference count */ + + ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; + if (ReferenceCount > 1) + { + /* Make new element ref count match original ref count */ + + for (Index = 0; Index < (ReferenceCount - 1); Index++) + { + AcpiUtAddReference ((ObjDesc->Package.Elements[i])); + } + } + } + + Arg = Arg->Common.Next; + } + + /* Check for match between NumElements and actual length of PackageList */ + + if (Arg) + { + /* + * NumElements was exhausted, but there are remaining elements in the + * PackageList. Truncate the package to NumElements. + * + * Note: technically, this is an error, from ACPI spec: "It is an error + * for NumElements to be less than the number of elements in the + * PackageList". However, we just print a message and + * no exception is returned. This provides Windows compatibility. Some + * BIOSs will alter the NumElements on the fly, creating this type + * of ill-formed package object. + */ + while (Arg) + { + /* + * We must delete any package elements that were created earlier + * and are not going to be used because of the package truncation. + */ + if (Arg->Common.Node) + { + AcpiUtRemoveReference ( + ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node)); + Arg->Common.Node = NULL; + } + + /* Find out how many elements there really are */ + + i++; + Arg = Arg->Common.Next; + } + + ACPI_INFO ((AE_INFO, + "Actual Package length (%u) is larger than NumElements field (%u), truncated\n", + i, ElementCount)); + } + else if (i < ElementCount) + { + /* + * Arg list (elements) was exhausted, but we did not reach NumElements count. + * Note: this is not an error, the package is padded out with NULLs. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n", + i, ElementCount)); + } + + ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; + Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateNode + * + * PARAMETERS: WalkState - Current walk state + * Node - NS Node to be initialized + * Op - Parser object to be translated + * + * RETURN: Status + * + * DESCRIPTION: Create the object to be associated with a namespace node + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateNode ( + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *Node, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateNode, Op); + + + /* + * Because of the execution pass through the non-control-method + * parts of the table, we can arrive here twice. Only init + * the named object node the first time through + */ + if (AcpiNsGetAttachedObject (Node)) + { + return_ACPI_STATUS (AE_OK); + } + + if (!Op->Common.Value.Arg) + { + /* No arguments, there is nothing to do */ + + return_ACPI_STATUS (AE_OK); + } + + /* Build an internal object for the argument(s) */ + + Status = AcpiDsBuildInternalObject (WalkState, Op->Common.Value.Arg, + &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Re-type the object according to its argument */ + + Node->Type = ObjDesc->Common.Type; + + /* Attach obj to node */ + + Status = AcpiNsAttachObject (Node, ObjDesc, Node->Type); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + +#endif /* ACPI_NO_METHOD_EXECUTION */ + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitObjectFromOp + * + * PARAMETERS: WalkState - Current walk state + * Op - Parser op used to init the internal object + * Opcode - AML opcode associated with the object + * RetObjDesc - Namespace object to be initialized + * + * RETURN: Status + * + * DESCRIPTION: Initialize a namespace object from a parser Op and its + * associated arguments. The namespace object is a more compact + * representation of the Op and its arguments. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitObjectFromOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT16 Opcode, + ACPI_OPERAND_OBJECT **RetObjDesc) +{ + const ACPI_OPCODE_INFO *OpInfo; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (DsInitObjectFromOp); + + + ObjDesc = *RetObjDesc; + OpInfo = AcpiPsGetOpcodeInfo (Opcode); + if (OpInfo->Class == AML_CLASS_UNKNOWN) + { + /* Unknown opcode */ + + return_ACPI_STATUS (AE_TYPE); + } + + /* Perform per-object initialization */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + + /* + * Defer evaluation of Buffer TermArg operand + */ + ObjDesc->Buffer.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, + WalkState->Operands[0]); + ObjDesc->Buffer.AmlStart = Op->Named.Data; + ObjDesc->Buffer.AmlLength = Op->Named.Length; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Defer evaluation of Package TermArg operand + */ + ObjDesc->Package.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, + WalkState->Operands[0]); + ObjDesc->Package.AmlStart = Op->Named.Data; + ObjDesc->Package.AmlLength = Op->Named.Length; + break; + + + case ACPI_TYPE_INTEGER: + + switch (OpInfo->Type) + { + case AML_TYPE_CONSTANT: + /* + * Resolve AML Constants here - AND ONLY HERE! + * All constants are integers. + * We mark the integer with a flag that indicates that it started + * life as a constant -- so that stores to constants will perform + * as expected (noop). ZeroOp is used as a placeholder for optional + * target operands. + */ + ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT; + + switch (Opcode) + { + case AML_ZERO_OP: + + ObjDesc->Integer.Value = 0; + break; + + case AML_ONE_OP: + + ObjDesc->Integer.Value = 1; + break; + + case AML_ONES_OP: + + ObjDesc->Integer.Value = ACPI_UINT64_MAX; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + +#ifndef ACPI_NO_METHOD_EXECUTION + AcpiExTruncateFor32bitTable (ObjDesc); +#endif + break; + + case AML_REVISION_OP: + + ObjDesc->Integer.Value = ACPI_CA_VERSION; + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown constant opcode 0x%X", Opcode)); + Status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + case AML_TYPE_LITERAL: + + ObjDesc->Integer.Value = Op->Common.Value.Integer; +#ifndef ACPI_NO_METHOD_EXECUTION + AcpiExTruncateFor32bitTable (ObjDesc); +#endif + break; + + + default: + ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X", + OpInfo->Type)); + Status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + case ACPI_TYPE_STRING: + + ObjDesc->String.Pointer = Op->Common.Value.String; + ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Op->Common.Value.String); + + /* + * The string is contained in the ACPI table, don't ever try + * to delete it + */ + ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; + break; + + + case ACPI_TYPE_METHOD: + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (OpInfo->Type) + { + case AML_TYPE_LOCAL_VARIABLE: + + /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ + + ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_LOCAL_OP; + ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL; + +#ifndef ACPI_NO_METHOD_EXECUTION + Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL, + ObjDesc->Reference.Value, WalkState, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, + &ObjDesc->Reference.Object)); +#endif + break; + + + case AML_TYPE_METHOD_ARGUMENT: + + /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ + + ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_ARG_OP; + ObjDesc->Reference.Class = ACPI_REFCLASS_ARG; + +#ifndef ACPI_NO_METHOD_EXECUTION + Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG, + ObjDesc->Reference.Value, WalkState, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, + &ObjDesc->Reference.Object)); +#endif + break; + + default: /* Object name or Debug object */ + + switch (Op->Common.AmlOpcode) + { + case AML_INT_NAMEPATH_OP: + + /* Node was saved in Op */ + + ObjDesc->Reference.Node = Op->Common.Node; + ObjDesc->Reference.Object = Op->Common.Node->Object; + ObjDesc->Reference.Class = ACPI_REFCLASS_NAME; + break; + + case AML_DEBUG_OP: + + ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG; + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode)); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + break; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X", + ObjDesc->Common.Type)); + + Status = AE_AML_OPERAND_TYPE; + break; + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/dispatcher/dsopcode.c b/source/components/dispatcher/dsopcode.c new file mode 100644 index 000000000000..7569236f2ebe --- /dev/null +++ b/source/components/dispatcher/dsopcode.c @@ -0,0 +1,809 @@ +/****************************************************************************** + * + * Module Name: dsopcode - Dispatcher suport for regions and fields + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSOPCODE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" +#include "actables.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsopcode") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsInitBufferField ( + UINT16 AmlOpcode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *BufferDesc, + ACPI_OPERAND_OBJECT *OffsetDesc, + ACPI_OPERAND_OBJECT *LengthDesc, + ACPI_OPERAND_OBJECT *ResultDesc); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitializeRegion + * + * PARAMETERS: ObjHandle - Region namespace node + * + * RETURN: Status + * + * DESCRIPTION: Front end to EvInitializeRegion + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitializeRegion ( + ACPI_HANDLE ObjHandle) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ObjDesc = AcpiNsGetAttachedObject (ObjHandle); + + /* Namespace is NOT locked */ + + Status = AcpiEvInitializeRegion (ObjDesc, FALSE); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitBufferField + * + * PARAMETERS: AmlOpcode - CreateXxxField + * ObjDesc - BufferField object + * BufferDesc - Host Buffer + * OffsetDesc - Offset into buffer + * LengthDesc - Length of field (CREATE_FIELD_OP only) + * ResultDesc - Where to store the result + * + * RETURN: Status + * + * DESCRIPTION: Perform actual initialization of a buffer field + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsInitBufferField ( + UINT16 AmlOpcode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *BufferDesc, + ACPI_OPERAND_OBJECT *OffsetDesc, + ACPI_OPERAND_OBJECT *LengthDesc, + ACPI_OPERAND_OBJECT *ResultDesc) +{ + UINT32 Offset; + UINT32 BitOffset; + UINT32 BitCount; + UINT8 FieldFlags; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc); + + + /* Host object must be a Buffer */ + + if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER) + { + ACPI_ERROR ((AE_INFO, + "Target of Create Field is not a Buffer object - %s", + AcpiUtGetObjectTypeName (BufferDesc))); + + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + + /* + * The last parameter to all of these opcodes (ResultDesc) started + * out as a NameString, and should therefore now be a NS node + * after resolution in AcpiExResolveOperands(). + */ + if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED) + { + ACPI_ERROR ((AE_INFO, + "(%s) destination not a NS Node [%s]", + AcpiPsGetOpcodeName (AmlOpcode), + AcpiUtGetDescriptorName (ResultDesc))); + + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + + Offset = (UINT32) OffsetDesc->Integer.Value; + + /* + * Setup the Bit offsets and counts, according to the opcode + */ + switch (AmlOpcode) + { + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + FieldFlags = AML_FIELD_ACCESS_BYTE; + BitOffset = Offset; + BitCount = (UINT32) LengthDesc->Integer.Value; + + /* Must have a valid (>0) bit count */ + + if (BitCount == 0) + { + ACPI_ERROR ((AE_INFO, + "Attempt to CreateField of length zero")); + Status = AE_AML_OPERAND_VALUE; + goto Cleanup; + } + break; + + case AML_CREATE_BIT_FIELD_OP: + + /* Offset is in bits, Field is one bit */ + + BitOffset = Offset; + BitCount = 1; + FieldFlags = AML_FIELD_ACCESS_BYTE; + break; + + case AML_CREATE_BYTE_FIELD_OP: + + /* Offset is in bytes, field is one byte */ + + BitOffset = 8 * Offset; + BitCount = 8; + FieldFlags = AML_FIELD_ACCESS_BYTE; + break; + + case AML_CREATE_WORD_FIELD_OP: + + /* Offset is in bytes, field is one word */ + + BitOffset = 8 * Offset; + BitCount = 16; + FieldFlags = AML_FIELD_ACCESS_WORD; + break; + + case AML_CREATE_DWORD_FIELD_OP: + + /* Offset is in bytes, field is one dword */ + + BitOffset = 8 * Offset; + BitCount = 32; + FieldFlags = AML_FIELD_ACCESS_DWORD; + break; + + case AML_CREATE_QWORD_FIELD_OP: + + /* Offset is in bytes, field is one qword */ + + BitOffset = 8 * Offset; + BitCount = 64; + FieldFlags = AML_FIELD_ACCESS_QWORD; + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown field creation opcode 0x%02X", + AmlOpcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + /* Entire field must fit within the current length of the buffer */ + + if ((BitOffset + BitCount) > + (8 * (UINT32) BufferDesc->Buffer.Length)) + { + ACPI_ERROR ((AE_INFO, + "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", + AcpiUtGetNodeName (ResultDesc), + BitOffset + BitCount, + AcpiUtGetNodeName (BufferDesc->Buffer.Node), + 8 * (UINT32) BufferDesc->Buffer.Length)); + Status = AE_AML_BUFFER_LIMIT; + goto Cleanup; + } + + /* + * Initialize areas of the field object that are common to all fields + * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK), + * UPDATE_RULE = 0 (UPDATE_PRESERVE) + */ + Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0, + BitOffset, BitCount); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + ObjDesc->BufferField.BufferObj = BufferDesc; + + /* Reference count for BufferDesc inherits ObjDesc count */ + + BufferDesc->Common.ReferenceCount = (UINT16) + (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount); + + +Cleanup: + + /* Always delete the operands */ + + AcpiUtRemoveReference (OffsetDesc); + AcpiUtRemoveReference (BufferDesc); + + if (AmlOpcode == AML_CREATE_FIELD_OP) + { + AcpiUtRemoveReference (LengthDesc); + } + + /* On failure, delete the result descriptor */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ResultDesc); /* Result descriptor */ + } + else + { + /* Now the address and length are valid for this BufferField */ + + ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsEvalBufferFieldOperands + * + * PARAMETERS: WalkState - Current walk + * Op - A valid BufferField Op object + * + * RETURN: Status + * + * DESCRIPTION: Get BufferField Buffer and Index + * Called from AcpiDsExecEndOp during BufferField parse tree walk + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsEvalBufferFieldOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *NextOp; + + + ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op); + + + /* + * This is where we evaluate the address and length fields of the + * CreateXxxField declaration + */ + Node = Op->Common.Node; + + /* NextOp points to the op that holds the Buffer */ + + NextOp = Op->Common.Value.Arg; + + /* Evaluate/create the address and length operands */ + + Status = AcpiDsCreateOperands (WalkState, NextOp); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Resolve the operands */ + + Status = AcpiExResolveOperands (Op->Common.AmlOpcode, + ACPI_WALK_OPERANDS, WalkState); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "(%s) bad operand(s), status 0x%X", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status)); + + return_ACPI_STATUS (Status); + } + + /* Initialize the Buffer Field */ + + if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) + { + /* NOTE: Slightly different operands for this opcode */ + + Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, + WalkState->Operands[0], WalkState->Operands[1], + WalkState->Operands[2], WalkState->Operands[3]); + } + else + { + /* All other, CreateXxxField opcodes */ + + Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, + WalkState->Operands[0], WalkState->Operands[1], + NULL, WalkState->Operands[2]); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsEvalRegionOperands + * + * PARAMETERS: WalkState - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from AcpiDsExecEndOp during OpRegion parse tree walk + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsEvalRegionOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *OperandDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *NextOp; + + + ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op); + + + /* + * This is where we evaluate the address and length fields of the + * OpRegion declaration + */ + Node = Op->Common.Node; + + /* NextOp points to the op that holds the SpaceID */ + + NextOp = Op->Common.Value.Arg; + + /* NextOp points to address op */ + + NextOp = NextOp->Common.Next; + + /* Evaluate/create the address and length operands */ + + Status = AcpiDsCreateOperands (WalkState, NextOp); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Resolve the length and address operands to numbers */ + + Status = AcpiExResolveOperands (Op->Common.AmlOpcode, + ACPI_WALK_OPERANDS, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* + * Get the length operand and save it + * (at Top of stack) + */ + OperandDesc = WalkState->Operands[WalkState->NumOperands - 1]; + + ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value; + AcpiUtRemoveReference (OperandDesc); + + /* + * Get the address and save it + * (at top of stack - 1) + */ + OperandDesc = WalkState->Operands[WalkState->NumOperands - 2]; + + ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) + OperandDesc->Integer.Value; + AcpiUtRemoveReference (OperandDesc); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + ObjDesc, + ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), + ObjDesc->Region.Length)); + + /* Now the address and length are valid for this opregion */ + + ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsEvalTableRegionOperands + * + * PARAMETERS: WalkState - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length. + * Called from AcpiDsExecEndOp during DataTableRegion parse + * tree walk. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsEvalTableRegionOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT **Operand; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *NextOp; + UINT32 TableIndex; + ACPI_TABLE_HEADER *Table; + + + ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op); + + + /* + * This is where we evaluate the SignatureString and OemIDString + * and OemTableIDString of the DataTableRegion declaration + */ + Node = Op->Common.Node; + + /* NextOp points to SignatureString op */ + + NextOp = Op->Common.Value.Arg; + + /* + * Evaluate/create the SignatureString and OemIDString + * and OemTableIDString operands + */ + Status = AcpiDsCreateOperands (WalkState, NextOp); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Resolve the SignatureString and OemIDString + * and OemTableIDString operands + */ + Status = AcpiExResolveOperands (Op->Common.AmlOpcode, + ACPI_WALK_OPERANDS, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Operand = &WalkState->Operands[0]; + + /* Find the ACPI table */ + + Status = AcpiTbFindTable (Operand[0]->String.Pointer, + Operand[1]->String.Pointer, Operand[2]->String.Pointer, + &TableIndex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiUtRemoveReference (Operand[0]); + AcpiUtRemoveReference (Operand[1]); + AcpiUtRemoveReference (Operand[2]); + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) ACPI_TO_INTEGER (Table); + ObjDesc->Region.Length = Table->Length; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + ObjDesc, + ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), + ObjDesc->Region.Length)); + + /* Now the address and length are valid for this opregion */ + + ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsEvalDataObjectOperands + * + * PARAMETERS: WalkState - Current walk + * Op - A valid DataObject Op object + * ObjDesc - DataObject + * + * RETURN: Status + * + * DESCRIPTION: Get the operands and complete the following data object types: + * Buffer, Package. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsEvalDataObjectOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ArgDesc; + UINT32 Length; + + + ACPI_FUNCTION_TRACE (DsEvalDataObjectOperands); + + + /* The first operand (for all of these data objects) is the length */ + + /* + * Set proper index into operand stack for AcpiDsObjStackPush + * invoked inside AcpiDsCreateOperand. + */ + WalkState->OperandIndex = WalkState->NumOperands; + + Status = AcpiDsCreateOperand (WalkState, Op->Common.Value.Arg, 1); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiExResolveOperands (WalkState->Opcode, + &(WalkState->Operands [WalkState->NumOperands -1]), + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Extract length operand */ + + ArgDesc = WalkState->Operands [WalkState->NumOperands - 1]; + Length = (UINT32) ArgDesc->Integer.Value; + + /* Cleanup for length operand */ + + Status = AcpiDsObjStackPop (1, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiUtRemoveReference (ArgDesc); + + /* + * Create the actual data object + */ + switch (Op->Common.AmlOpcode) + { + case AML_BUFFER_OP: + + Status = AcpiDsBuildInternalBufferObj (WalkState, Op, Length, &ObjDesc); + break; + + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + Status = AcpiDsBuildInternalPackageObj (WalkState, Op, Length, &ObjDesc); + break; + + default: + return_ACPI_STATUS (AE_AML_BAD_OPCODE); + } + + if (ACPI_SUCCESS (Status)) + { + /* + * Return the object in the WalkState, unless the parent is a package - + * in this case, the return object will be stored in the parse tree + * for the package. + */ + if ((!Op->Common.Parent) || + ((Op->Common.Parent->Common.AmlOpcode != AML_PACKAGE_OP) && + (Op->Common.Parent->Common.AmlOpcode != AML_VAR_PACKAGE_OP) && + (Op->Common.Parent->Common.AmlOpcode != AML_NAME_OP))) + { + WalkState->ResultObj = ObjDesc; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsEvalBankFieldOperands + * + * PARAMETERS: WalkState - Current walk + * Op - A valid BankField Op object + * + * RETURN: Status + * + * DESCRIPTION: Get BankField BankValue + * Called from AcpiDsExecEndOp during BankField parse tree walk + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsEvalBankFieldOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *OperandDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *NextOp; + ACPI_PARSE_OBJECT *Arg; + + + ACPI_FUNCTION_TRACE_PTR (DsEvalBankFieldOperands, Op); + + + /* + * This is where we evaluate the BankValue field of the + * BankField declaration + */ + + /* NextOp points to the op that holds the Region */ + + NextOp = Op->Common.Value.Arg; + + /* NextOp points to the op that holds the Bank Register */ + + NextOp = NextOp->Common.Next; + + /* NextOp points to the op that holds the Bank Value */ + + NextOp = NextOp->Common.Next; + + /* + * Set proper index into operand stack for AcpiDsObjStackPush + * invoked inside AcpiDsCreateOperand. + * + * We use WalkState->Operands[0] to store the evaluated BankValue + */ + WalkState->OperandIndex = 0; + + Status = AcpiDsCreateOperand (WalkState, NextOp, 0); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiExResolveToValue (&WalkState->Operands[0], WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1); + /* + * Get the BankValue operand and save it + * (at Top of stack) + */ + OperandDesc = WalkState->Operands[0]; + + /* Arg points to the start Bank Field */ + + Arg = AcpiPsGetArg (Op, 4); + while (Arg) + { + /* Ignore OFFSET and ACCESSAS terms here */ + + if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) + { + Node = Arg->Common.Node; + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + ObjDesc->BankField.Value = (UINT32) OperandDesc->Integer.Value; + } + + /* Move to next field in the list */ + + Arg = Arg->Common.Next; + } + + AcpiUtRemoveReference (OperandDesc); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/dispatcher/dsutils.c b/source/components/dispatcher/dsutils.c new file mode 100644 index 000000000000..66431aad5316 --- /dev/null +++ b/source/components/dispatcher/dsutils.c @@ -0,0 +1,937 @@ +/******************************************************************************* + * + * Module Name: dsutils - Dispatcher utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSUTILS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsutils") + + +/******************************************************************************* + * + * FUNCTION: AcpiDsClearImplicitReturn + * + * PARAMETERS: WalkState - Current State + * + * RETURN: None. + * + * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * to delete "stale" return values (if enabled, the return value + * from every operator is saved at least momentarily, in case the + * parent method exits.) + * + ******************************************************************************/ + +void +AcpiDsClearImplicitReturn ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_FUNCTION_NAME (DsClearImplicitReturn); + + + /* + * Slack must be enabled for this feature + */ + if (!AcpiGbl_EnableInterpreterSlack) + { + return; + } + + if (WalkState->ImplicitReturnObj) + { + /* + * Delete any "stale" implicit return. However, in + * complex statements, the implicit return value can be + * bubbled up several levels. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Removing reference on stale implicit return obj %p\n", + WalkState->ImplicitReturnObj)); + + AcpiUtRemoveReference (WalkState->ImplicitReturnObj); + WalkState->ImplicitReturnObj = NULL; + } +} + + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: AcpiDsDoImplicitReturn + * + * PARAMETERS: ReturnDesc - The return value + * WalkState - Current State + * AddReference - True if a reference should be added to the + * return object + * + * RETURN: TRUE if implicit return enabled, FALSE otherwise + * + * DESCRIPTION: Implements the optional "implicit return". We save the result + * of every ASL operator and control method invocation in case the + * parent method exit. Before storing a new return value, we + * delete the previous return value. + * + ******************************************************************************/ + +BOOLEAN +AcpiDsDoImplicitReturn ( + ACPI_OPERAND_OBJECT *ReturnDesc, + ACPI_WALK_STATE *WalkState, + BOOLEAN AddReference) +{ + ACPI_FUNCTION_NAME (DsDoImplicitReturn); + + + /* + * Slack must be enabled for this feature, and we must + * have a valid return object + */ + if ((!AcpiGbl_EnableInterpreterSlack) || + (!ReturnDesc)) + { + return (FALSE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result %p will be implicitly returned; Prev=%p\n", + ReturnDesc, + WalkState->ImplicitReturnObj)); + + /* + * Delete any "stale" implicit return value first. However, in + * complex statements, the implicit return value can be + * bubbled up several levels, so we don't clear the value if it + * is the same as the ReturnDesc. + */ + if (WalkState->ImplicitReturnObj) + { + if (WalkState->ImplicitReturnObj == ReturnDesc) + { + return (TRUE); + } + AcpiDsClearImplicitReturn (WalkState); + } + + /* Save the implicit return value, add a reference if requested */ + + WalkState->ImplicitReturnObj = ReturnDesc; + if (AddReference) + { + AcpiUtAddReference (ReturnDesc); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsIsResultUsed + * + * PARAMETERS: Op - Current Op + * WalkState - Current State + * + * RETURN: TRUE if result is used, FALSE otherwise + * + * DESCRIPTION: Check if a result object will be used by the parent + * + ******************************************************************************/ + +BOOLEAN +AcpiDsIsResultUsed ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + const ACPI_OPCODE_INFO *ParentInfo; + + ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op); + + + /* Must have both an Op and a Result Object */ + + if (!Op) + { + ACPI_ERROR ((AE_INFO, "Null Op")); + return_UINT8 (TRUE); + } + + /* + * We know that this operator is not a + * Return() operator (would not come here.) The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE); + + /* + * Now determine if the parent will use the result + * + * If there is no parent, or the parent is a ScopeOp, we are executing + * at the method level. An executing method typically has no parent, + * since each method is parsed separately. A method invoked externally + * via ExecuteControlMethod has a ScopeOp as the parent. + */ + if ((!Op->Common.Parent) || + (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) + { + /* No parent, the return value cannot possibly be used */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "At Method level, result of [%s] not used\n", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); + return_UINT8 (FALSE); + } + + /* Get info on the parent. The RootOp is AML_SCOPE */ + + ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); + if (ParentInfo->Class == AML_CLASS_UNKNOWN) + { + ACPI_ERROR ((AE_INFO, + "Unknown parent opcode Op=%p", Op)); + return_UINT8 (FALSE); + } + + /* + * Decide what to do with the result based on the parent. If + * the parent opcode will not use the result, delete the object. + * Otherwise leave it as is, it will be deleted when it is used + * as an operand later. + */ + switch (ParentInfo->Class) + { + case AML_CLASS_CONTROL: + + switch (Op->Common.Parent->Common.AmlOpcode) + { + case AML_RETURN_OP: + + /* Never delete the return value associated with a return opcode */ + + goto ResultUsed; + + case AML_IF_OP: + case AML_WHILE_OP: + + /* + * If we are executing the predicate AND this is the predicate op, + * we will use the return value + */ + if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && + (WalkState->ControlState->Control.PredicateOp == Op)) + { + goto ResultUsed; + } + break; + + default: + /* Ignore other control opcodes */ + break; + } + + /* The general control opcode returns no result */ + + goto ResultNotUsed; + + + case AML_CLASS_CREATE: + + /* + * These opcodes allow TermArg(s) as operands and therefore + * the operands can be method calls. The result is used. + */ + goto ResultUsed; + + + case AML_CLASS_NAMED_OBJECT: + + if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) + { + /* + * These opcodes allow TermArg(s) as operands and therefore + * the operands can be method calls. The result is used. + */ + goto ResultUsed; + } + + goto ResultNotUsed; + + + default: + + /* + * In all other cases. the parent will actually use the return + * object, so keep it. + */ + goto ResultUsed; + } + + +ResultUsed: + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result of [%s] used by Parent [%s] Op=%p\n", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), + AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); + + return_UINT8 (TRUE); + + +ResultNotUsed: + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result of [%s] not used by Parent [%s] Op=%p\n", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), + AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); + + return_UINT8 (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsDeleteResultIfNotUsed + * + * PARAMETERS: Op - Current parse Op + * ResultObj - Result of the operation + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * result descriptor, check if the parent opcode will actually use + * this result. If not, delete the result now so that it will + * not become orphaned. + * + ******************************************************************************/ + +void +AcpiDsDeleteResultIfNotUsed ( + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT *ResultObj, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj); + + + if (!Op) + { + ACPI_ERROR ((AE_INFO, "Null Op")); + return_VOID; + } + + if (!ResultObj) + { + return_VOID; + } + + if (!AcpiDsIsResultUsed (Op, WalkState)) + { + /* Must pop the result stack (ObjDesc should be equal to ResultObj) */ + + Status = AcpiDsResultPop (&ObjDesc, WalkState); + if (ACPI_SUCCESS (Status)) + { + AcpiUtRemoveReference (ResultObj); + } + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResolveOperands + * + * PARAMETERS: WalkState - Current walk state with operands on stack + * + * RETURN: Status + * + * DESCRIPTION: Resolve all operands to their values. Used to prepare + * arguments to a control method invocation (a call from one + * method to another.) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsResolveOperands ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState); + + + /* + * Attempt to resolve each of the valid operands + * Method arguments are passed by reference, not by value. This means + * that the actual objects are passed, not copies of the objects. + */ + for (i = 0; i < WalkState->NumOperands; i++) + { + Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState); + if (ACPI_FAILURE (Status)) + { + break; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsClearOperands + * + * PARAMETERS: WalkState - Current walk state with operands on stack + * + * RETURN: None + * + * DESCRIPTION: Clear all operands on the current walk state operand stack. + * + ******************************************************************************/ + +void +AcpiDsClearOperands ( + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState); + + + /* Remove a reference on each operand on the stack */ + + for (i = 0; i < WalkState->NumOperands; i++) + { + /* + * Remove a reference to all operands, including both + * "Arguments" and "Targets". + */ + AcpiUtRemoveReference (WalkState->Operands[i]); + WalkState->Operands[i] = NULL; + } + + WalkState->NumOperands = 0; + return_VOID; +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateOperand + * + * PARAMETERS: WalkState - Current walk state + * Arg - Parse object for the argument + * ArgIndex - Which argument (zero based) + * + * RETURN: Status + * + * DESCRIPTION: Translate a parse tree object that is an argument to an AML + * opcode to the equivalent interpreter object. This may include + * looking up a name or entering a new name into the internal + * namespace. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateOperand ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Arg, + UINT32 ArgIndex) +{ + ACPI_STATUS Status = AE_OK; + char *NameString; + UINT32 NameLength; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PARSE_OBJECT *ParentOp; + UINT16 Opcode; + ACPI_INTERPRETER_MODE InterpreterMode; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); + + + /* A valid name must be looked up in the namespace */ + + if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + (Arg->Common.Value.String) && + !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); + + /* Get the entire name string from the AML stream */ + + Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, + &NameString, &NameLength); + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* All prefixes have been handled, and the name is in NameString */ + + /* + * Special handling for BufferField declarations. This is a deferred + * opcode that unfortunately defines the field name as the last + * parameter instead of the first. We get here when we are performing + * the deferred execution, so the actual name of the field is already + * in the namespace. We don't want to attempt to look it up again + * because we may be executing in a different scope than where the + * actual opcode exists. + */ + if ((WalkState->DeferredNode) && + (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && + (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) + { + ObjDesc = ACPI_CAST_PTR ( + ACPI_OPERAND_OBJECT, WalkState->DeferredNode); + Status = AE_OK; + } + else /* All other opcodes */ + { + /* + * Differentiate between a namespace "create" operation + * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. + * IMODE_EXECUTE) in order to support the creation of + * namespace objects during the execution of control methods. + */ + ParentOp = Arg->Common.Parent; + OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); + if ((OpInfo->Flags & AML_NSNODE) && + (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && + (ParentOp->Common.AmlOpcode != AML_REGION_OP) && + (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) + { + /* Enter name into namespace if not found */ + + InterpreterMode = ACPI_IMODE_LOAD_PASS2; + } + else + { + /* Return a failure if name not found */ + + InterpreterMode = ACPI_IMODE_EXECUTE; + } + + Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, + ACPI_TYPE_ANY, InterpreterMode, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + WalkState, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); + /* + * The only case where we pass through (ignore) a NOT_FOUND + * error is for the CondRefOf opcode. + */ + if (Status == AE_NOT_FOUND) + { + if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) + { + /* + * For the Conditional Reference op, it's OK if + * the name is not found; We just need a way to + * indicate this to the interpreter, set the + * object to the root + */ + ObjDesc = ACPI_CAST_PTR ( + ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); + Status = AE_OK; + } + else + { + /* + * We just plain didn't find it -- which is a + * very serious error at this point + */ + Status = AE_AML_NAME_NOT_FOUND; + } + } + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (NameString, Status); + } + } + + /* Free the namestring created above */ + + ACPI_FREE (NameString); + + /* Check status from the lookup */ + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Put the resulting object onto the current object stack */ + + Status = AcpiDsObjStackPush (ObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); + } + else + { + /* Check for null name case */ + + if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) + { + /* + * If the name is null, this means that this is an + * optional result parameter that was not specified + * in the original ASL. Create a Zero Constant for a + * placeholder. (Store to a constant is a Noop.) + */ + Opcode = AML_ZERO_OP; /* Has no arguments! */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Null namepath: Arg=%p\n", Arg)); + } + else + { + Opcode = Arg->Common.AmlOpcode; + } + + /* Get the object type of the argument */ + + OpInfo = AcpiPsGetOpcodeInfo (Opcode); + if (OpInfo->ObjectType == ACPI_TYPE_INVALID) + { + return_ACPI_STATUS (AE_NOT_IMPLEMENTED); + } + + if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Argument previously created, already stacked\n")); + + ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( + WalkState->Operands [WalkState->NumOperands - 1], WalkState)); + + /* + * Use value that was already previously returned + * by the evaluation of this argument + */ + Status = AcpiDsResultPop (&ObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + /* + * Only error is underflow, and this indicates + * a missing or null operand! + */ + ACPI_EXCEPTION ((AE_INFO, Status, + "Missing or null operand")); + return_ACPI_STATUS (Status); + } + } + else + { + /* Create an ACPI_INTERNAL_OBJECT for the argument */ + + ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize the new object */ + + Status = AcpiDsInitObjectFromOp ( + WalkState, Arg, Opcode, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (Status); + } + } + + /* Put the operand object on the object stack */ + + Status = AcpiDsObjStackPush (ObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateOperands + * + * PARAMETERS: WalkState - Current state + * FirstArg - First argument of a parser argument tree + * + * RETURN: Status + * + * DESCRIPTION: Convert an operator's arguments from a parse tree format to + * namespace objects and place those argument object on the object + * stack in preparation for evaluation by the interpreter. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsCreateOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *FirstArg) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Arg; + ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; + UINT32 ArgCount = 0; + UINT32 Index = WalkState->NumOperands; + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg); + + + /* Get all arguments in the list */ + + Arg = FirstArg; + while (Arg) + { + if (Index >= ACPI_OBJ_NUM_OPERANDS) + { + return_ACPI_STATUS (AE_BAD_DATA); + } + + Arguments[Index] = Arg; + WalkState->Operands [Index] = NULL; + + /* Move on to next argument, if any */ + + Arg = Arg->Common.Next; + ArgCount++; + Index++; + } + + Index--; + + /* It is the appropriate order to get objects from the Result stack */ + + for (i = 0; i < ArgCount; i++) + { + Arg = Arguments[Index]; + + /* Force the filling of the operand stack in inverse order */ + + WalkState->OperandIndex = (UINT8) Index; + + Status = AcpiDsCreateOperand (WalkState, Arg, Index); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Index--; + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n", + Index, Arg, FirstArg)); + } + + return_ACPI_STATUS (Status); + + +Cleanup: + /* + * We must undo everything done above; meaning that we must + * pop everything off of the operand stack and delete those + * objects + */ + AcpiDsObjStackPopAndDelete (ArgCount, WalkState); + + ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); + return_ACPI_STATUS (Status); +} + + +/***************************************************************************** + * + * FUNCTION: AcpiDsEvaluateNamePath + * + * PARAMETERS: WalkState - Current state of the parse tree walk, + * the opcode of current operation should be + * AML_INT_NAMEPATH_OP + * + * RETURN: Status + * + * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent + * interpreter object, convert it to value, if needed, duplicate + * it, if needed, and push it onto the current result stack. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiDsEvaluateNamePath ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Op = WalkState->Op; + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *NewObjDesc; + UINT8 Type; + + + ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState); + + + if (!Op->Common.Parent) + { + /* This happens after certain exception processing */ + + goto Exit; + } + + if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP)) + { + /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */ + + goto Exit; + } + + Status = AcpiDsCreateOperand (WalkState, Op, 0); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + if (Op->Common.Flags & ACPI_PARSEOP_TARGET) + { + NewObjDesc = *Operand; + goto PushResult; + } + + Type = (*Operand)->Common.Type; + + Status = AcpiExResolveToValue (Operand, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + if (Type == ACPI_TYPE_INTEGER) + { + /* It was incremented by AcpiExResolveToValue */ + + AcpiUtRemoveReference (*Operand); + + Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + } + else + { + /* + * The object either was anew created or is + * a Namespace node - don't decrement it. + */ + NewObjDesc = *Operand; + } + + /* Cleanup for name-path operand */ + + Status = AcpiDsObjStackPop (1, WalkState); + if (ACPI_FAILURE (Status)) + { + WalkState->ResultObj = NewObjDesc; + goto Exit; + } + +PushResult: + + WalkState->ResultObj = NewObjDesc; + + Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); + if (ACPI_SUCCESS (Status)) + { + /* Force to take it from stack */ + + Op->Common.Flags |= ACPI_PARSEOP_IN_STACK; + } + +Exit: + + return_ACPI_STATUS (Status); +} diff --git a/source/components/dispatcher/dswexec.c b/source/components/dispatcher/dswexec.c new file mode 100644 index 000000000000..5732855bbeee --- /dev/null +++ b/source/components/dispatcher/dswexec.c @@ -0,0 +1,797 @@ +/****************************************************************************** + * + * Module Name: dswexec - Dispatcher method execution callbacks; + * dispatch to interpreter. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSWEXEC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswexec") + +/* + * Dispatch table for opcode classes + */ +static ACPI_EXECUTE_OP AcpiGbl_OpTypeDispatch [] = +{ + AcpiExOpcode_0A_0T_1R, + AcpiExOpcode_1A_0T_0R, + AcpiExOpcode_1A_0T_1R, + AcpiExOpcode_1A_1T_0R, + AcpiExOpcode_1A_1T_1R, + AcpiExOpcode_2A_0T_0R, + AcpiExOpcode_2A_0T_1R, + AcpiExOpcode_2A_1T_1R, + AcpiExOpcode_2A_2T_1R, + AcpiExOpcode_3A_0T_0R, + AcpiExOpcode_3A_1T_1R, + AcpiExOpcode_6A_0T_1R +}; + + +/***************************************************************************** + * + * FUNCTION: AcpiDsGetPredicateValue + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * ResultObj - if non-zero, pop result from result stack + * + * RETURN: Status + * + * DESCRIPTION: Get the result of a predicate evaluation + * + ****************************************************************************/ + +ACPI_STATUS +AcpiDsGetPredicateValue ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ResultObj) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *LocalObjDesc = NULL; + + + ACPI_FUNCTION_TRACE_PTR (DsGetPredicateValue, WalkState); + + + WalkState->ControlState->Common.State = 0; + + if (ResultObj) + { + Status = AcpiDsResultPop (&ObjDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not get result from predicate evaluation")); + + return_ACPI_STATUS (Status); + } + } + else + { + Status = AcpiDsCreateOperand (WalkState, WalkState->Op, 0); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ObjDesc = WalkState->Operands [0]; + } + + if (!ObjDesc) + { + ACPI_ERROR ((AE_INFO, + "No predicate ObjDesc=%p State=%p", + ObjDesc, WalkState)); + + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + /* + * Result of predicate evaluation must be an Integer + * object. Implicitly convert the argument if necessary. + */ + Status = AcpiExConvertToInteger (ObjDesc, &LocalObjDesc, 16); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + if (LocalObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, + "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X", + ObjDesc, WalkState, ObjDesc->Common.Type)); + + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + + /* Truncate the predicate to 32-bits if necessary */ + + AcpiExTruncateFor32bitTable (LocalObjDesc); + + /* + * Save the result of the predicate evaluation on + * the control stack + */ + if (LocalObjDesc->Integer.Value) + { + WalkState->ControlState->Common.Value = TRUE; + } + else + { + /* + * Predicate is FALSE, we will just toss the + * rest of the package + */ + WalkState->ControlState->Common.Value = FALSE; + Status = AE_CTRL_FALSE; + } + + /* Predicate can be used for an implicit return value */ + + (void) AcpiDsDoImplicitReturn (LocalObjDesc, WalkState, TRUE); + + +Cleanup: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", + WalkState->ControlState->Common.Value, WalkState->Op)); + + /* Break to debugger to display result */ + + ACPI_DEBUGGER_EXEC (AcpiDbDisplayResultObject (LocalObjDesc, WalkState)); + + /* + * Delete the predicate result object (we know that + * we don't need it anymore) + */ + if (LocalObjDesc != ObjDesc) + { + AcpiUtRemoveReference (LocalObjDesc); + } + AcpiUtRemoveReference (ObjDesc); + + WalkState->ControlState->Common.State = ACPI_CONTROL_NORMAL; + return_ACPI_STATUS (Status); +} + + +/***************************************************************************** + * + * FUNCTION: AcpiDsExecBeginOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * OutOp - Where to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the execution of control + * methods. This is where most operators and operands are + * dispatched to the interpreter. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiDsExecBeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_STATUS Status = AE_OK; + UINT32 OpcodeClass; + + + ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState); + + + Op = WalkState->Op; + if (!Op) + { + Status = AcpiDsLoad2BeginOp (WalkState, OutOp); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + Op = *OutOp; + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + + if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "(%s) Popping scope for Op %p\n", + AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op)); + + Status = AcpiDsScopeStackPop (WalkState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + } + } + + if (Op == WalkState->Origin) + { + if (OutOp) + { + *OutOp = Op; + } + + return_ACPI_STATUS (AE_OK); + } + + /* + * If the previous opcode was a conditional, this opcode + * must be the beginning of the associated predicate. + * Save this knowledge in the current scope descriptor + */ + if ((WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n", + Op, WalkState)); + + WalkState->ControlState->Common.State = ACPI_CONTROL_PREDICATE_EXECUTING; + + /* Save start of predicate */ + + WalkState->ControlState->Control.PredicateOp = Op; + } + + + OpcodeClass = WalkState->OpInfo->Class; + + /* We want to send namepaths to the load code */ + + if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) + { + OpcodeClass = AML_CLASS_NAMED_OBJECT; + } + + /* + * Handle the opcode based upon the opcode type + */ + switch (OpcodeClass) + { + case AML_CLASS_CONTROL: + + Status = AcpiDsExecBeginControlOp (WalkState, Op); + break; + + + case AML_CLASS_NAMED_OBJECT: + + if (WalkState->WalkType & ACPI_WALK_METHOD) + { + /* + * Found a named object declaration during method execution; + * we must enter this object into the namespace. The created + * object is temporary and will be deleted upon completion of + * the execution of this method. + * + * Note 10/2010: Except for the Scope() op. This opcode does + * not actually create a new object, it refers to an existing + * object. However, for Scope(), we want to indeed open a + * new scope. + */ + if (Op->Common.AmlOpcode != AML_SCOPE_OP) + { + Status = AcpiDsLoad2BeginOp (WalkState, NULL); + } + else + { + Status = AcpiDsScopeStackPush (Op->Named.Node, + Op->Named.Node->Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + break; + + + case AML_CLASS_EXECUTE: + case AML_CLASS_CREATE: + + break; + + + default: + break; + } + + /* Nothing to do here during method execution */ + + return_ACPI_STATUS (Status); + + +ErrorExit: + Status = AcpiDsMethodError (Status, WalkState); + return_ACPI_STATUS (Status); +} + + +/***************************************************************************** + * + * FUNCTION: AcpiDsExecEndOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the execution of control + * methods. The only thing we really need to do here is to + * notice the beginning of IF, ELSE, and WHILE blocks. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiDsExecEndOp ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_STATUS Status = AE_OK; + UINT32 OpType; + UINT32 OpClass; + ACPI_PARSE_OBJECT *NextOp; + ACPI_PARSE_OBJECT *FirstArg; + + + ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState); + + + Op = WalkState->Op; + OpType = WalkState->OpInfo->Type; + OpClass = WalkState->OpInfo->Class; + + if (OpClass == AML_CLASS_UNKNOWN) + { + ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode)); + return_ACPI_STATUS (AE_NOT_IMPLEMENTED); + } + + FirstArg = Op->Common.Value.Arg; + + /* Init the walk state */ + + WalkState->NumOperands = 0; + WalkState->OperandIndex = 0; + WalkState->ReturnDesc = NULL; + WalkState->ResultObj = NULL; + + /* Call debugger for single step support (DEBUG build only) */ + + ACPI_DEBUGGER_EXEC (Status = AcpiDbSingleStep (WalkState, Op, OpClass)); + ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (Status)) {return_ACPI_STATUS (Status);}); + + /* Decode the Opcode Class */ + + switch (OpClass) + { + case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ + + if (WalkState->Opcode == AML_INT_NAMEPATH_OP) + { + Status = AcpiDsEvaluateNamePath (WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + break; + + + case AML_CLASS_EXECUTE: /* Most operators with arguments */ + + /* Build resolved operand stack */ + + Status = AcpiDsCreateOperands (WalkState, FirstArg); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * All opcodes require operand resolution, with the only exceptions + * being the ObjectType and SizeOf operators. + */ + if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE)) + { + /* Resolve all operands */ + + Status = AcpiExResolveOperands (WalkState->Opcode, + &(WalkState->Operands [WalkState->NumOperands -1]), + WalkState); + } + + if (ACPI_SUCCESS (Status)) + { + /* + * Dispatch the request to the appropriate interpreter handler + * routine. There is one routine per opcode "type" based upon the + * number of opcode arguments and return type. + */ + Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState); + } + else + { + /* + * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the + * Local is uninitialized. + */ + if ((Status == AE_AML_UNINITIALIZED_LOCAL) && + (WalkState->Opcode == AML_STORE_OP) && + (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + (WalkState->Operands[0]->Reference.Class == + WalkState->Operands[1]->Reference.Class) && + (WalkState->Operands[0]->Reference.Value == + WalkState->Operands[1]->Reference.Value)) + { + Status = AE_OK; + } + else + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While resolving operands for [%s]", + AcpiPsGetOpcodeName (WalkState->Opcode))); + } + } + + /* Always delete the argument objects and clear the operand stack */ + + AcpiDsClearOperands (WalkState); + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (ACPI_SUCCESS (Status) && + WalkState->ResultObj) + { + Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); + } + break; + + + default: + + switch (OpType) + { + case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ + + /* 1 Operand, 0 ExternalResult, 0 InternalResult */ + + Status = AcpiDsExecEndControlOp (WalkState, Op); + + break; + + + case AML_TYPE_METHOD_CALL: + + /* + * If the method is referenced from within a package + * declaration, it is not a invocation of the method, just + * a reference to it. + */ + if ((Op->Asl.Parent) && + ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) || + (Op->Asl.Parent->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Method Reference in a Package, Op=%p\n", Op)); + + Op->Common.Node = (ACPI_NAMESPACE_NODE *) Op->Asl.Value.Arg->Asl.Node; + AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object); + return_ACPI_STATUS (AE_OK); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", Op)); + + /* + * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains + * the method Node pointer + */ + /* NextOp points to the op that holds the method name */ + + NextOp = FirstArg; + + /* NextOp points to first argument op */ + + NextOp = NextOp->Common.Next; + + /* + * Get the method's arguments and put them on the operand stack + */ + Status = AcpiDsCreateOperands (WalkState, NextOp); + if (ACPI_FAILURE (Status)) + { + break; + } + + /* + * Since the operands will be passed to another control method, + * we must resolve all local references here (Local variables, + * arguments to *this* method, etc.) + */ + Status = AcpiDsResolveOperands (WalkState); + if (ACPI_FAILURE (Status)) + { + /* On error, clear all resolved operands */ + + AcpiDsClearOperands (WalkState); + break; + } + + /* + * Tell the walk loop to preempt this running method and + * execute the new method + */ + Status = AE_CTRL_TRANSFER; + + /* + * Return now; we don't want to disturb anything, + * especially the operand count! + */ + return_ACPI_STATUS (Status); + + + case AML_TYPE_CREATE_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing CreateField Buffer/Index Op=%p\n", Op)); + + Status = AcpiDsLoad2EndOp (WalkState); + if (ACPI_FAILURE (Status)) + { + break; + } + + Status = AcpiDsEvalBufferFieldOperands (WalkState, Op); + break; + + + case AML_TYPE_CREATE_OBJECT: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing CreateObject (Buffer/Package) Op=%p\n", Op)); + + switch (Op->Common.Parent->Common.AmlOpcode) + { + case AML_NAME_OP: + + /* + * Put the Node on the object stack (Contains the ACPI Name + * of this object) + */ + WalkState->Operands[0] = (void *) Op->Common.Parent->Common.Node; + WalkState->NumOperands = 1; + + Status = AcpiDsCreateNode (WalkState, + Op->Common.Parent->Common.Node, + Op->Common.Parent); + if (ACPI_FAILURE (Status)) + { + break; + } + + /* Fall through */ + /*lint -fallthrough */ + + case AML_INT_EVAL_SUBTREE_OP: + + Status = AcpiDsEvalDataObjectOperands (WalkState, Op, + AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node)); + break; + + default: + + Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL); + break; + } + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (WalkState->ResultObj) + { + Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); + } + break; + + + case AML_TYPE_NAMED_FIELD: + case AML_TYPE_NAMED_COMPLEX: + case AML_TYPE_NAMED_SIMPLE: + case AML_TYPE_NAMED_NO_OBJ: + + Status = AcpiDsLoad2EndOp (WalkState); + if (ACPI_FAILURE (Status)) + { + break; + } + + if (Op->Common.AmlOpcode == AML_REGION_OP) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing OpRegion Address/Length Op=%p\n", Op)); + + Status = AcpiDsEvalRegionOperands (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + break; + } + } + else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing DataTableRegion Strings Op=%p\n", Op)); + + Status = AcpiDsEvalTableRegionOperands (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + break; + } + } + else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing BankField Op=%p\n", Op)); + + Status = AcpiDsEvalBankFieldOperands (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + break; + } + } + break; + + + case AML_TYPE_UNDEFINED: + + ACPI_ERROR ((AE_INFO, + "Undefined opcode type Op=%p", Op)); + return_ACPI_STATUS (AE_NOT_IMPLEMENTED); + + + case AML_TYPE_BOGUS: + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Internal opcode=%X type Op=%p\n", + WalkState->Opcode, Op)); + break; + + + default: + + ACPI_ERROR ((AE_INFO, + "Unimplemented opcode, class=0x%X type=0x%X Opcode=-0x%X Op=%p", + OpClass, OpType, Op->Common.AmlOpcode, Op)); + + Status = AE_NOT_IMPLEMENTED; + break; + } + } + + /* + * ACPI 2.0 support for 64-bit integers: Truncate numeric + * result value if we are executing from a 32-bit ACPI table + */ + AcpiExTruncateFor32bitTable (WalkState->ResultObj); + + /* + * Check if we just completed the evaluation of a + * conditional predicate + */ + if ((ACPI_SUCCESS (Status)) && + (WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_PREDICATE_EXECUTING) && + (WalkState->ControlState->Control.PredicateOp == Op)) + { + Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj); + WalkState->ResultObj = NULL; + } + + +Cleanup: + + if (WalkState->ResultObj) + { + /* Break to debugger to display result */ + + ACPI_DEBUGGER_EXEC (AcpiDbDisplayResultObject (WalkState->ResultObj, + WalkState)); + + /* + * Delete the result op if and only if: + * Parent will not use the result -- such as any + * non-nested type2 op in a method (parent will be method) + */ + AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState); + } + +#ifdef _UNDER_DEVELOPMENT + + if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd) + { + AcpiDbMethodEnd (WalkState); + } +#endif + + /* Invoke exception handler on error */ + + if (ACPI_FAILURE (Status)) + { + Status = AcpiDsMethodError (Status, WalkState); + } + + /* Always clear the object stack */ + + WalkState->NumOperands = 0; + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/dispatcher/dswload.c b/source/components/dispatcher/dswload.c new file mode 100644 index 000000000000..d40f911f417c --- /dev/null +++ b/source/components/dispatcher/dswload.c @@ -0,0 +1,551 @@ +/****************************************************************************** + * + * Module Name: dswload - Dispatcher first pass namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSWLOAD_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" + +#ifdef ACPI_ASL_COMPILER +#include "acdisasm.h" +#endif + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswload") + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitCallbacks + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * PassNumber - 1, 2, or 3 + * + * RETURN: Status + * + * DESCRIPTION: Init walk state callbacks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitCallbacks ( + ACPI_WALK_STATE *WalkState, + UINT32 PassNumber) +{ + + switch (PassNumber) + { + case 1: + WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsLoad1BeginOp; + WalkState->AscendingCallback = AcpiDsLoad1EndOp; + break; + + case 2: + WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsLoad2BeginOp; + WalkState->AscendingCallback = AcpiDsLoad2EndOp; + break; + + case 3: +#ifndef ACPI_NO_METHOD_EXECUTION + WalkState->ParseFlags |= ACPI_PARSE_EXECUTE | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsExecBeginOp; + WalkState->AscendingCallback = AcpiDsExecEndOp; +#endif + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsLoad1BeginOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * OutOp - Where to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsLoad1BeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE ObjectType; + char *Path; + UINT32 Flags; + + + ACPI_FUNCTION_TRACE (DsLoad1BeginOp); + + + Op = WalkState->Op; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); + + /* We are only interested in opcodes that have an associated name */ + + if (Op) + { + if (!(WalkState->OpInfo->Flags & AML_NAMED)) + { + *OutOp = Op; + return_ACPI_STATUS (AE_OK); + } + + /* Check if this object has already been installed in the namespace */ + + if (Op->Common.Node) + { + *OutOp = Op; + return_ACPI_STATUS (AE_OK); + } + } + + Path = AcpiPsGetNextNamestring (&WalkState->ParserState); + + /* Map the raw opcode into an internal object type */ + + ObjectType = WalkState->OpInfo->ObjectType; + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "State=%p Op=%p [%s]\n", WalkState, Op, AcpiUtGetTypeName (ObjectType))); + + switch (WalkState->Opcode) + { + case AML_SCOPE_OP: + + /* + * The target name of the Scope() operator must exist at this point so + * that we can actually open the scope to enter new names underneath it. + * Allow search-to-root for single namesegs. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); +#ifdef ACPI_ASL_COMPILER + if (Status == AE_NOT_FOUND) + { + /* + * Table disassembly: + * Target of Scope() not found. Generate an External for it, and + * insert the name into the namespace. + */ + AcpiDmAddToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0); + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, + WalkState, &Node); + } +#endif + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Path, Status); + return_ACPI_STATUS (Status); + } + + /* + * Check to make sure that the target is + * one of the opcodes that actually opens a scope + */ + switch (Node->Type) + { + case ACPI_TYPE_ANY: + case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. + * This enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + * + * Note: silently change the type here. On the second pass, + * we will report a warning + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); + + Node->Type = ACPI_TYPE_ANY; + WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; + break; + + default: + + /* All other types are an error */ + + ACPI_ERROR ((AE_INFO, + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", + AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + break; + + + default: + /* + * For all other named opcodes, we will enter the name into + * the namespace. + * + * Setup the search flags. + * Since we are entering a name into the namespace, we do not want to + * enable the search-to-root upsearch. + * + * There are only two conditions where it is acceptable that the name + * already exists: + * 1) the Scope() operator can reopen a scoping object that was + * previously defined (Scope, Method, Device, etc.) + * 2) Whenever we are parsing a deferred opcode (OpRegion, Buffer, + * BufferField, or Package), the name of the object is already + * in the namespace. + */ + if (WalkState->DeferredNode) + { + /* This name is already in the namespace, get the node */ + + Node = WalkState->DeferredNode; + Status = AE_OK; + break; + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (WalkState->MethodNode) + { + Node = NULL; + Status = AE_OK; + break; + } + + Flags = ACPI_NS_NO_UPSEARCH; + if ((WalkState->Opcode != AML_SCOPE_OP) && + (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP))) + { + Flags |= ACPI_NS_ERROR_IF_FOUND; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", + AcpiUtGetTypeName (ObjectType))); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "[%s] Both Find or Create allowed\n", + AcpiUtGetTypeName (ObjectType))); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, + ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_ALREADY_EXISTS) + { + /* The name already exists in this scope */ + + if (Node->Flags & ANOBJ_IS_EXTERNAL) + { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + Node->Flags &= ~ANOBJ_IS_EXTERNAL; + Node->Type = (UINT8) ObjectType; + + /* Just retyped a node, probably will need to open a scope */ + + if (AcpiNsOpensScope (ObjectType)) + { + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + Status = AE_OK; + } + } + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Path, Status); + return_ACPI_STATUS (Status); + } + } + break; + } + + /* Common exit */ + + if (!Op) + { + /* Create a new op */ + + Op = AcpiPsAllocOp (WalkState->Opcode); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + /* Initialize the op */ + +#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) + Op->Named.Path = ACPI_CAST_PTR (UINT8, Path); +#endif + + if (Node) + { + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + Op->Common.Node = Node; + Op->Named.Name = Node->Name.Integer; + } + + AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op); + *OutOp = Op; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsLoad1EndOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsLoad1EndOp ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_OBJECT_TYPE ObjectType; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (DsLoad1EndOp); + + + Op = WalkState->Op; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); + + /* We are only interested in opcodes that have an associated name */ + + if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_FIELD))) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the object type to determine if we should pop the scope */ + + ObjectType = WalkState->OpInfo->ObjectType; + +#ifndef ACPI_NO_METHOD_EXECUTION + if (WalkState->OpInfo->Flags & AML_FIELD) + { + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!WalkState->MethodNode) + { + if (WalkState->Opcode == AML_FIELD_OP || + WalkState->Opcode == AML_BANK_FIELD_OP || + WalkState->Opcode == AML_INDEX_FIELD_OP) + { + Status = AcpiDsInitFieldObjects (Op, WalkState); + } + } + return_ACPI_STATUS (Status); + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!WalkState->MethodNode) + { + if (Op->Common.AmlOpcode == AML_REGION_OP) + { + Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, + (ACPI_ADR_SPACE_TYPE) ((Op->Common.Value.Arg)->Common.Value.Integer), + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) + { + Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, + ACPI_ADR_SPACE_DATA_TABLE, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } +#endif + + if (Op->Common.AmlOpcode == AML_NAME_OP) + { + /* For Name opcode, get the object type from the argument */ + + if (Op->Common.Value.Arg) + { + ObjectType = (AcpiPsGetOpcodeInfo ( + (Op->Common.Value.Arg)->Common.AmlOpcode))->ObjectType; + + /* Set node type if we have a namespace node */ + + if (Op->Common.Node) + { + Op->Common.Node->Type = (UINT8) ObjectType; + } + } + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!WalkState->MethodNode) + { + if (Op->Common.AmlOpcode == AML_METHOD_OP) + { + /* + * MethodOp PkgLength NameString MethodFlags TermList + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", + WalkState, Op, Op->Named.Node)); + + if (!AcpiNsGetAttachedObject (Op->Named.Node)) + { + WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node); + WalkState->NumOperands = 1; + + Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiExCreateMethod (Op->Named.Data, + Op->Named.Length, WalkState); + } + + WalkState->Operands[0] = NULL; + WalkState->NumOperands = 0; + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + } + + /* Pop the scope stack (only if loading a table) */ + + if (!WalkState->MethodNode && + AcpiNsOpensScope (ObjectType)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", + AcpiUtGetTypeName (ObjectType), Op)); + + Status = AcpiDsScopeStackPop (WalkState); + } + + return_ACPI_STATUS (Status); +} diff --git a/source/components/dispatcher/dswload2.c b/source/components/dispatcher/dswload2.c new file mode 100644 index 000000000000..27e317620911 --- /dev/null +++ b/source/components/dispatcher/dswload2.c @@ -0,0 +1,747 @@ +/****************************************************************************** + * + * Module Name: dswload2 - Dispatcher second pass namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSWLOAD2_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswload2") + + +/******************************************************************************* + * + * FUNCTION: AcpiDsLoad2BeginOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * OutOp - Wher to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsLoad2BeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE ObjectType; + char *BufferPtr; + UINT32 Flags; + + + ACPI_FUNCTION_TRACE (DsLoad2BeginOp); + + + Op = WalkState->Op; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); + + if (Op) + { + if ((WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) + { + /* We are executing a while loop outside of a method */ + + Status = AcpiDsExecBeginOp (WalkState, OutOp); + return_ACPI_STATUS (Status); + } + + /* We only care about Namespace opcodes here */ + + if ((!(WalkState->OpInfo->Flags & AML_NSOPCODE) && + (WalkState->Opcode != AML_INT_NAMEPATH_OP)) || + (!(WalkState->OpInfo->Flags & AML_NAMED))) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get the name we are going to enter or lookup in the namespace */ + + if (WalkState->Opcode == AML_INT_NAMEPATH_OP) + { + /* For Namepath op, get the path string */ + + BufferPtr = Op->Common.Value.String; + if (!BufferPtr) + { + /* No name, just exit */ + + return_ACPI_STATUS (AE_OK); + } + } + else + { + /* Get name from the op */ + + BufferPtr = ACPI_CAST_PTR (char, &Op->Named.Name); + } + } + else + { + /* Get the namestring from the raw AML */ + + BufferPtr = AcpiPsGetNextNamestring (&WalkState->ParserState); + } + + /* Map the opcode into an internal object type */ + + ObjectType = WalkState->OpInfo->ObjectType; + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "State=%p Op=%p Type=%X\n", WalkState, Op, ObjectType)); + + switch (WalkState->Opcode) + { + case AML_FIELD_OP: + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + + Node = NULL; + Status = AE_OK; + break; + + case AML_INT_NAMEPATH_OP: + /* + * The NamePath is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + WalkState, &(Node)); + break; + + case AML_SCOPE_OP: + + /* Special case for Scope(\) -> refers to the Root node */ + + if (Op && (Op->Named.Node == AcpiGbl_RootNode)) + { + Node = Op->Named.Node; + + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + else + { + /* + * The Path is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + WalkState, &(Node)); + if (ACPI_FAILURE (Status)) + { +#ifdef ACPI_ASL_COMPILER + if (Status == AE_NOT_FOUND) + { + Status = AE_OK; + } + else + { + ACPI_ERROR_NAMESPACE (BufferPtr, Status); + } +#else + ACPI_ERROR_NAMESPACE (BufferPtr, Status); +#endif + return_ACPI_STATUS (Status); + } + } + + /* + * We must check to make sure that the target is + * one of the opcodes that actually opens a scope + */ + switch (Node->Type) + { + case ACPI_TYPE_ANY: + case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. + * This enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + */ + ACPI_WARNING ((AE_INFO, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); + + Node->Type = ACPI_TYPE_ANY; + WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; + break; + + default: + + /* All other types are an error */ + + ACPI_ERROR ((AE_INFO, + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", + AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); + + return (AE_AML_OPERAND_TYPE); + } + break; + + default: + + /* All other opcodes */ + + if (Op && Op->Common.Node) + { + /* This op/node was previously entered into the namespace */ + + Node = Op->Common.Node; + + if (AcpiNsOpensScope (ObjectType)) + { + Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + return_ACPI_STATUS (AE_OK); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + * + * Note: Name may already exist if we are executing a deferred opcode. + */ + if (WalkState->DeferredNode) + { + /* This name is already in the namespace, get the node */ + + Node = WalkState->DeferredNode; + Status = AE_OK; + break; + } + + Flags = ACPI_NS_NO_UPSEARCH; + if (WalkState->PassNumber == ACPI_IMODE_EXECUTE) + { + /* Execution mode, node cannot already exist, node is temporary */ + + Flags |= ACPI_NS_ERROR_IF_FOUND; + + if (!(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) + { + Flags |= ACPI_NS_TEMPORARY; + } + } + + /* Add new entry or lookup existing entry */ + + Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType, + ACPI_IMODE_LOAD_PASS2, Flags, WalkState, &Node); + + if (ACPI_SUCCESS (Status) && (Flags & ACPI_NS_TEMPORARY)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "***New Node [%4.4s] %p is temporary\n", + AcpiUtGetNodeName (Node), Node)); + } + break; + } + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (BufferPtr, Status); + return_ACPI_STATUS (Status); + } + + if (!Op) + { + /* Create a new op */ + + Op = AcpiPsAllocOp (WalkState->Opcode); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize the new op */ + + if (Node) + { + Op->Named.Name = Node->Name.Integer; + } + *OutOp = Op; + } + + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + Op->Common.Node = Node; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsLoad2EndOp + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsLoad2EndOp ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_PARSE_OBJECT *Op; + ACPI_STATUS Status = AE_OK; + ACPI_OBJECT_TYPE ObjectType; + ACPI_NAMESPACE_NODE *Node; + ACPI_PARSE_OBJECT *Arg; + ACPI_NAMESPACE_NODE *NewNode; +#ifndef ACPI_NO_METHOD_EXECUTION + UINT32 i; + UINT8 RegionSpace; +#endif + + + ACPI_FUNCTION_TRACE (DsLoad2EndOp); + + Op = WalkState->Op; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", + WalkState->OpInfo->Name, Op, WalkState)); + + /* Check if opcode had an associated namespace object */ + + if (!(WalkState->OpInfo->Flags & AML_NSOBJECT)) + { + return_ACPI_STATUS (AE_OK); + } + + if (Op->Common.AmlOpcode == AML_SCOPE_OP) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Ending scope Op=%p State=%p\n", Op, WalkState)); + } + + ObjectType = WalkState->OpInfo->ObjectType; + + /* + * Get the Node/name from the earlier lookup + * (It was saved in the *op structure) + */ + Node = Op->Common.Node; + + /* + * Put the Node on the object stack (Contains the ACPI Name of + * this object) + */ + WalkState->Operands[0] = (void *) Node; + WalkState->NumOperands = 1; + + /* Pop the scope stack */ + + if (AcpiNsOpensScope (ObjectType) && + (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", + AcpiUtGetTypeName (ObjectType), Op)); + + Status = AcpiDsScopeStackPop (WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + + /* + * Named operations are as follows: + * + * AML_ALIAS + * AML_BANKFIELD + * AML_CREATEBITFIELD + * AML_CREATEBYTEFIELD + * AML_CREATEDWORDFIELD + * AML_CREATEFIELD + * AML_CREATEQWORDFIELD + * AML_CREATEWORDFIELD + * AML_DATA_REGION + * AML_DEVICE + * AML_EVENT + * AML_FIELD + * AML_INDEXFIELD + * AML_METHOD + * AML_METHODCALL + * AML_MUTEX + * AML_NAME + * AML_NAMEDFIELD + * AML_OPREGION + * AML_POWERRES + * AML_PROCESSOR + * AML_SCOPE + * AML_THERMALZONE + */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), WalkState, Op, Node)); + + /* Decode the opcode */ + + Arg = Op->Common.Value.Arg; + + switch (WalkState->OpInfo->Type) + { +#ifndef ACPI_NO_METHOD_EXECUTION + + case AML_TYPE_CREATE_FIELD: + /* + * Create the field object, but the field buffer and index must + * be evaluated later during the execution phase + */ + Status = AcpiDsCreateBufferField (Op, WalkState); + break; + + + case AML_TYPE_NAMED_FIELD: + /* + * If we are executing a method, initialize the field + */ + if (WalkState->MethodNode) + { + Status = AcpiDsInitFieldObjects (Op, WalkState); + } + + switch (Op->Common.AmlOpcode) + { + case AML_INDEX_FIELD_OP: + + Status = AcpiDsCreateIndexField (Op, (ACPI_HANDLE) Arg->Common.Node, + WalkState); + break; + + case AML_BANK_FIELD_OP: + + Status = AcpiDsCreateBankField (Op, Arg->Common.Node, WalkState); + break; + + case AML_FIELD_OP: + + Status = AcpiDsCreateField (Op, Arg->Common.Node, WalkState); + break; + + default: + /* All NAMED_FIELD opcodes must be handled above */ + break; + } + break; + + + case AML_TYPE_NAMED_SIMPLE: + + Status = AcpiDsCreateOperands (WalkState, Arg); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + switch (Op->Common.AmlOpcode) + { + case AML_PROCESSOR_OP: + + Status = AcpiExCreateProcessor (WalkState); + break; + + case AML_POWER_RES_OP: + + Status = AcpiExCreatePowerResource (WalkState); + break; + + case AML_MUTEX_OP: + + Status = AcpiExCreateMutex (WalkState); + break; + + case AML_EVENT_OP: + + Status = AcpiExCreateEvent (WalkState); + break; + + + case AML_ALIAS_OP: + + Status = AcpiExCreateAlias (WalkState); + break; + + default: + /* Unknown opcode */ + + Status = AE_OK; + goto Cleanup; + } + + /* Delete operands */ + + for (i = 1; i < WalkState->NumOperands; i++) + { + AcpiUtRemoveReference (WalkState->Operands[i]); + WalkState->Operands[i] = NULL; + } + + break; +#endif /* ACPI_NO_METHOD_EXECUTION */ + + case AML_TYPE_NAMED_COMPLEX: + + switch (Op->Common.AmlOpcode) + { +#ifndef ACPI_NO_METHOD_EXECUTION + case AML_REGION_OP: + case AML_DATA_REGION_OP: + + if (Op->Common.AmlOpcode == AML_REGION_OP) + { + RegionSpace = (ACPI_ADR_SPACE_TYPE) + ((Op->Common.Value.Arg)->Common.Value.Integer); + } + else + { + RegionSpace = ACPI_ADR_SPACE_DATA_TABLE; + } + + /* + * The OpRegion is not fully parsed at this time. The only valid + * argument is the SpaceId. (We must save the address of the + * AML of the address and length operands) + * + * If we have a valid region, initialize it. The namespace is + * unlocked at this point. + * + * Need to unlock interpreter if it is locked (if we are running + * a control method), in order to allow _REG methods to be run + * during AcpiEvInitializeRegion. + */ + if (WalkState->MethodNode) + { + /* + * Executing a method: initialize the region and unlock + * the interpreter + */ + Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, + RegionSpace, WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + AcpiExExitInterpreter (); + } + + Status = AcpiEvInitializeRegion (AcpiNsGetAttachedObject (Node), + FALSE); + if (WalkState->MethodNode) + { + AcpiExEnterInterpreter (); + } + + if (ACPI_FAILURE (Status)) + { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == Status) + { + Status = AE_OK; + } + } + break; + + + case AML_NAME_OP: + + Status = AcpiDsCreateNode (WalkState, Node, Op); + break; + + + case AML_METHOD_OP: + /* + * MethodOp PkgLength NameString MethodFlags TermList + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", + WalkState, Op, Op->Named.Node)); + + if (!AcpiNsGetAttachedObject (Op->Named.Node)) + { + WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node); + WalkState->NumOperands = 1; + + Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiExCreateMethod (Op->Named.Data, + Op->Named.Length, WalkState); + } + WalkState->Operands[0] = NULL; + WalkState->NumOperands = 0; + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + break; + +#endif /* ACPI_NO_METHOD_EXECUTION */ + + default: + /* All NAMED_COMPLEX opcodes must be handled above */ + break; + } + break; + + + case AML_CLASS_INTERNAL: + + /* case AML_INT_NAMEPATH_OP: */ + break; + + + case AML_CLASS_METHOD_CALL: + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", + WalkState, Op, Node)); + + /* + * Lookup the method name and save the Node + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, + ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + WalkState, &(NewNode)); + if (ACPI_SUCCESS (Status)) + { + /* + * Make sure that what we found is indeed a method + * We didn't search for a method on purpose, to see if the name + * would resolve + */ + if (NewNode->Type != ACPI_TYPE_METHOD) + { + Status = AE_AML_OPERAND_TYPE; + } + + /* We could put the returned object (Node) on the object stack for + * later, but for now, we will put it in the "op" object that the + * parser uses, so we can get it again at the end of this scope + */ + Op->Common.Node = NewNode; + } + else + { + ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); + } + break; + + + default: + break; + } + +Cleanup: + + /* Remove the Node pushed at the very beginning */ + + WalkState->Operands[0] = NULL; + WalkState->NumOperands = 0; + return_ACPI_STATUS (Status); +} + diff --git a/source/components/dispatcher/dswscope.c b/source/components/dispatcher/dswscope.c new file mode 100644 index 000000000000..a59fdc9dca5c --- /dev/null +++ b/source/components/dispatcher/dswscope.c @@ -0,0 +1,239 @@ +/****************************************************************************** + * + * Module Name: dswscope - Scope stack manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __DSWSCOPE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswscope") + + +/**************************************************************************** + * + * FUNCTION: AcpiDsScopeStackClear + * + * PARAMETERS: WalkState - Current state + * + * RETURN: None + * + * DESCRIPTION: Pop (and free) everything on the scope stack except the + * root scope object (which remains at the stack top.) + * + ***************************************************************************/ + +void +AcpiDsScopeStackClear ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *ScopeInfo; + + ACPI_FUNCTION_NAME (DsScopeStackClear); + + + while (WalkState->ScopeInfo) + { + /* Pop a scope off the stack */ + + ScopeInfo = WalkState->ScopeInfo; + WalkState->ScopeInfo = ScopeInfo->Scope.Next; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Popped object type (%s)\n", + AcpiUtGetTypeName (ScopeInfo->Common.Value))); + AcpiUtDeleteGenericState (ScopeInfo); + } +} + + +/**************************************************************************** + * + * FUNCTION: AcpiDsScopeStackPush + * + * PARAMETERS: Node - Name to be made current + * Type - Type of frame being pushed + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Push the current scope on the scope stack, and make the + * passed Node current. + * + ***************************************************************************/ + +ACPI_STATUS +AcpiDsScopeStackPush ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type, + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *ScopeInfo; + ACPI_GENERIC_STATE *OldScopeInfo; + + + ACPI_FUNCTION_TRACE (DsScopeStackPush); + + + if (!Node) + { + /* Invalid scope */ + + ACPI_ERROR ((AE_INFO, "Null scope parameter")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Make sure object type is valid */ + + if (!AcpiUtValidObjectType (Type)) + { + ACPI_WARNING ((AE_INFO, + "Invalid object type: 0x%X", Type)); + } + + /* Allocate a new scope object */ + + ScopeInfo = AcpiUtCreateGenericState (); + if (!ScopeInfo) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Init new scope object */ + + ScopeInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_WSCOPE; + ScopeInfo->Scope.Node = Node; + ScopeInfo->Common.Value = (UINT16) Type; + + WalkState->ScopeDepth++; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[%.2d] Pushed scope ", (UINT32) WalkState->ScopeDepth)); + + OldScopeInfo = WalkState->ScopeInfo; + if (OldScopeInfo) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + "[%4.4s] (%s)", + AcpiUtGetNodeName (OldScopeInfo->Scope.Node), + AcpiUtGetTypeName (OldScopeInfo->Common.Value))); + } + else + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + "[\\___] (%s)", "ROOT")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + ", New scope -> [%4.4s] (%s)\n", + AcpiUtGetNodeName (ScopeInfo->Scope.Node), + AcpiUtGetTypeName (ScopeInfo->Common.Value))); + + /* Push new scope object onto stack */ + + AcpiUtPushGenericState (&WalkState->ScopeInfo, ScopeInfo); + return_ACPI_STATUS (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: AcpiDsScopeStackPop + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Pop the scope stack once. + * + ***************************************************************************/ + +ACPI_STATUS +AcpiDsScopeStackPop ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *ScopeInfo; + ACPI_GENERIC_STATE *NewScopeInfo; + + + ACPI_FUNCTION_TRACE (DsScopeStackPop); + + + /* + * Pop scope info object off the stack. + */ + ScopeInfo = AcpiUtPopGenericState (&WalkState->ScopeInfo); + if (!ScopeInfo) + { + return_ACPI_STATUS (AE_STACK_UNDERFLOW); + } + + WalkState->ScopeDepth--; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", + (UINT32) WalkState->ScopeDepth, + AcpiUtGetNodeName (ScopeInfo->Scope.Node), + AcpiUtGetTypeName (ScopeInfo->Common.Value))); + + NewScopeInfo = WalkState->ScopeInfo; + if (NewScopeInfo) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + "[%4.4s] (%s)\n", + AcpiUtGetNodeName (NewScopeInfo->Scope.Node), + AcpiUtGetTypeName (NewScopeInfo->Common.Value))); + } + else + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + "[\\___] (ROOT)\n")); + } + + AcpiUtDeleteGenericState (ScopeInfo); + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/dispatcher/dswstate.c b/source/components/dispatcher/dswstate.c new file mode 100644 index 000000000000..dd11a1813029 --- /dev/null +++ b/source/components/dispatcher/dswstate.c @@ -0,0 +1,846 @@ +/****************************************************************************** + * + * Module Name: dswstate - Dispatcher parse tree walk management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __DSWSTATE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswstate") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsResultStackPush ( + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +AcpiDsResultStackPop ( + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResultPop + * + * PARAMETERS: Object - Where to return the popped object + * WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the top of this walk's result stack + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsResultPop ( + ACPI_OPERAND_OBJECT **Object, + ACPI_WALK_STATE *WalkState) +{ + UINT32 Index; + ACPI_GENERIC_STATE *State; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (DsResultPop); + + + State = WalkState->Results; + + /* Incorrect state of result stack */ + + if (State && !WalkState->ResultCount) + { + ACPI_ERROR ((AE_INFO, "No results on result stack")); + return (AE_AML_INTERNAL); + } + + if (!State && WalkState->ResultCount) + { + ACPI_ERROR ((AE_INFO, "No result state for result stack")); + return (AE_AML_INTERNAL); + } + + /* Empty result stack */ + + if (!State) + { + ACPI_ERROR ((AE_INFO, "Result stack is empty! State=%p", WalkState)); + return (AE_AML_NO_RETURN_VALUE); + } + + /* Return object of the top element and clean that top element result stack */ + + WalkState->ResultCount--; + Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; + + *Object = State->Results.ObjDesc [Index]; + if (!*Object) + { + ACPI_ERROR ((AE_INFO, "No result objects on result stack, State=%p", + WalkState)); + return (AE_AML_NO_RETURN_VALUE); + } + + State->Results.ObjDesc [Index] = NULL; + if (Index == 0) + { + Status = AcpiDsResultStackPop (WalkState); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Obj=%p [%s] Index=%X State=%p Num=%X\n", *Object, + AcpiUtGetObjectTypeName (*Object), + Index, WalkState, WalkState->ResultCount)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResultPush + * + * PARAMETERS: Object - Where to return the popped object + * WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto the current result stack + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsResultPush ( + ACPI_OPERAND_OBJECT *Object, + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *State; + ACPI_STATUS Status; + UINT32 Index; + + + ACPI_FUNCTION_NAME (DsResultPush); + + + if (WalkState->ResultCount > WalkState->ResultSize) + { + ACPI_ERROR ((AE_INFO, "Result stack is full")); + return (AE_AML_INTERNAL); + } + else if (WalkState->ResultCount == WalkState->ResultSize) + { + /* Extend the result stack */ + + Status = AcpiDsResultStackPush (WalkState); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Failed to extend the result stack")); + return (Status); + } + } + + if (!(WalkState->ResultCount < WalkState->ResultSize)) + { + ACPI_ERROR ((AE_INFO, "No free elements in result stack")); + return (AE_AML_INTERNAL); + } + + State = WalkState->Results; + if (!State) + { + ACPI_ERROR ((AE_INFO, "No result stack frame during push")); + return (AE_AML_INTERNAL); + } + + if (!Object) + { + ACPI_ERROR ((AE_INFO, + "Null Object! Obj=%p State=%p Num=%u", + Object, WalkState, WalkState->ResultCount)); + return (AE_BAD_PARAMETER); + } + + /* Assign the address of object to the top free element of result stack */ + + Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; + State->Results.ObjDesc [Index] = Object; + WalkState->ResultCount++; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", + Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object), + WalkState, WalkState->ResultCount, WalkState->CurrentResult)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResultStackPush + * + * PARAMETERS: WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto the WalkState result stack + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsResultStackPush ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_NAME (DsResultStackPush); + + + /* Check for stack overflow */ + + if (((UINT32) WalkState->ResultSize + ACPI_RESULTS_FRAME_OBJ_NUM) > + ACPI_RESULTS_OBJ_NUM_MAX) + { + ACPI_ERROR ((AE_INFO, "Result stack overflow: State=%p Num=%u", + WalkState, WalkState->ResultSize)); + return (AE_STACK_OVERFLOW); + } + + State = AcpiUtCreateGenericState (); + if (!State) + { + return (AE_NO_MEMORY); + } + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_RESULT; + AcpiUtPushGenericState (&WalkState->Results, State); + + /* Increase the length of the result stack by the length of frame */ + + WalkState->ResultSize += ACPI_RESULTS_FRAME_OBJ_NUM; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n", + State, WalkState)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResultStackPop + * + * PARAMETERS: WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off of the WalkState result stack + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsResultStackPop ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_NAME (DsResultStackPop); + + + /* Check for stack underflow */ + + if (WalkState->Results == NULL) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Result stack underflow - State=%p\n", + WalkState)); + return (AE_AML_NO_OPERAND); + } + + if (WalkState->ResultSize < ACPI_RESULTS_FRAME_OBJ_NUM) + { + ACPI_ERROR ((AE_INFO, "Insufficient result stack size")); + return (AE_AML_INTERNAL); + } + + State = AcpiUtPopGenericState (&WalkState->Results); + AcpiUtDeleteGenericState (State); + + /* Decrease the length of result stack by the length of frame */ + + WalkState->ResultSize -= ACPI_RESULTS_FRAME_OBJ_NUM; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Result=%p RemainingResults=%X State=%p\n", + State, WalkState->ResultCount, WalkState)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsObjStackPush + * + * PARAMETERS: Object - Object to push + * WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's object/operand stack + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsObjStackPush ( + void *Object, + ACPI_WALK_STATE *WalkState) +{ + ACPI_FUNCTION_NAME (DsObjStackPush); + + + /* Check for stack overflow */ + + if (WalkState->NumOperands >= ACPI_OBJ_NUM_OPERANDS) + { + ACPI_ERROR ((AE_INFO, + "Object stack overflow! Obj=%p State=%p #Ops=%u", + Object, WalkState, WalkState->NumOperands)); + return (AE_STACK_OVERFLOW); + } + + /* Put the object onto the stack */ + + WalkState->Operands [WalkState->OperandIndex] = Object; + WalkState->NumOperands++; + + /* For the usual order of filling the operand stack */ + + WalkState->OperandIndex++; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", + Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object), + WalkState, WalkState->NumOperands)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsObjStackPop + * + * PARAMETERS: PopCount - Number of objects/entries to pop + * WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsObjStackPop ( + UINT32 PopCount, + ACPI_WALK_STATE *WalkState) +{ + UINT32 i; + + + ACPI_FUNCTION_NAME (DsObjStackPop); + + + for (i = 0; i < PopCount; i++) + { + /* Check for stack underflow */ + + if (WalkState->NumOperands == 0) + { + ACPI_ERROR ((AE_INFO, + "Object stack underflow! Count=%X State=%p #Ops=%u", + PopCount, WalkState, WalkState->NumOperands)); + return (AE_STACK_UNDERFLOW); + } + + /* Just set the stack entry to null */ + + WalkState->NumOperands--; + WalkState->Operands [WalkState->NumOperands] = NULL; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n", + PopCount, WalkState, WalkState->NumOperands)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsObjStackPopAndDelete + * + * PARAMETERS: PopCount - Number of objects/entries to pop + * WalkState - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack and delete each object that is + * popped off. + * + ******************************************************************************/ + +void +AcpiDsObjStackPopAndDelete ( + UINT32 PopCount, + ACPI_WALK_STATE *WalkState) +{ + INT32 i; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_NAME (DsObjStackPopAndDelete); + + + if (PopCount == 0) + { + return; + } + + for (i = (INT32) PopCount - 1; i >= 0; i--) + { + if (WalkState->NumOperands == 0) + { + return; + } + + /* Pop the stack and delete an object if present in this stack entry */ + + WalkState->NumOperands--; + ObjDesc = WalkState->Operands [i]; + if (ObjDesc) + { + AcpiUtRemoveReference (WalkState->Operands [i]); + WalkState->Operands [i] = NULL; + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", + PopCount, WalkState, WalkState->NumOperands)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsGetCurrentWalkState + * + * PARAMETERS: Thread - Get current active state for this Thread + * + * RETURN: Pointer to the current walk state + * + * DESCRIPTION: Get the walk state that is at the head of the list (the "current" + * walk state.) + * + ******************************************************************************/ + +ACPI_WALK_STATE * +AcpiDsGetCurrentWalkState ( + ACPI_THREAD_STATE *Thread) +{ + ACPI_FUNCTION_NAME (DsGetCurrentWalkState); + + + if (!Thread) + { + return (NULL); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current WalkState %p\n", + Thread->WalkStateList)); + + return (Thread->WalkStateList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsPushWalkState + * + * PARAMETERS: WalkState - State to push + * Thread - Thread state object + * + * RETURN: None + * + * DESCRIPTION: Place the Thread state at the head of the state list + * + ******************************************************************************/ + +void +AcpiDsPushWalkState ( + ACPI_WALK_STATE *WalkState, + ACPI_THREAD_STATE *Thread) +{ + ACPI_FUNCTION_TRACE (DsPushWalkState); + + + WalkState->Next = Thread->WalkStateList; + Thread->WalkStateList = WalkState; + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsPopWalkState + * + * PARAMETERS: Thread - Current thread state + * + * RETURN: A WalkState object popped from the thread's stack + * + * DESCRIPTION: Remove and return the walkstate object that is at the head of + * the walk stack for the given walk list. NULL indicates that + * the list is empty. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +AcpiDsPopWalkState ( + ACPI_THREAD_STATE *Thread) +{ + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_TRACE (DsPopWalkState); + + + WalkState = Thread->WalkStateList; + + if (WalkState) + { + /* Next walk state becomes the current walk state */ + + Thread->WalkStateList = WalkState->Next; + + /* + * Don't clear the NEXT field, this serves as an indicator + * that there is a parent WALK STATE + * Do Not: WalkState->Next = NULL; + */ + } + + return_PTR (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateWalkState + * + * PARAMETERS: OwnerId - ID for object creation + * Origin - Starting point for this walk + * MethodDesc - Method object + * Thread - Current thread state + * + * RETURN: Pointer to the new walk state. + * + * DESCRIPTION: Allocate and initialize a new walk state. The current walk + * state is set to this new state. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +AcpiDsCreateWalkState ( + ACPI_OWNER_ID OwnerId, + ACPI_PARSE_OBJECT *Origin, + ACPI_OPERAND_OBJECT *MethodDesc, + ACPI_THREAD_STATE *Thread) +{ + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_TRACE (DsCreateWalkState); + + + WalkState = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE)); + if (!WalkState) + { + return_PTR (NULL); + } + + WalkState->DescriptorType = ACPI_DESC_TYPE_WALK; + WalkState->MethodDesc = MethodDesc; + WalkState->OwnerId = OwnerId; + WalkState->Origin = Origin; + WalkState->Thread = Thread; + + WalkState->ParserState.StartOp = Origin; + + /* Init the method args/local */ + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + AcpiDsMethodDataInit (WalkState); +#endif + + /* Put the new state at the head of the walk list */ + + if (Thread) + { + AcpiDsPushWalkState (WalkState, Thread); + } + + return_PTR (WalkState); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitAmlWalk + * + * PARAMETERS: WalkState - New state to be initialized + * Op - Current parse op + * MethodNode - Control method NS node, if any + * AmlStart - Start of AML + * AmlLength - Length of AML + * Info - Method info block (params, etc.) + * PassNumber - 1, 2, or 3 + * + * RETURN: Status + * + * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitAmlWalk ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *MethodNode, + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_EVALUATE_INFO *Info, + UINT8 PassNumber) +{ + ACPI_STATUS Status; + ACPI_PARSE_STATE *ParserState = &WalkState->ParserState; + ACPI_PARSE_OBJECT *ExtraOp; + + + ACPI_FUNCTION_TRACE (DsInitAmlWalk); + + + WalkState->ParserState.Aml = + WalkState->ParserState.AmlStart = AmlStart; + WalkState->ParserState.AmlEnd = + WalkState->ParserState.PkgEnd = AmlStart + AmlLength; + + /* The NextOp of the NextWalk will be the beginning of the method */ + + WalkState->NextOp = NULL; + WalkState->PassNumber = PassNumber; + + if (Info) + { + WalkState->Params = Info->Parameters; + WalkState->CallerReturnDesc = &Info->ReturnObject; + } + + Status = AcpiPsInitScope (&WalkState->ParserState, Op); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (MethodNode) + { + WalkState->ParserState.StartNode = MethodNode; + WalkState->WalkType = ACPI_WALK_METHOD; + WalkState->MethodNode = MethodNode; + WalkState->MethodDesc = AcpiNsGetAttachedObject (MethodNode); + + /* Push start scope on scope stack and make it current */ + + Status = AcpiDsScopeStackPush (MethodNode, ACPI_TYPE_METHOD, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Init the method arguments */ + + Status = AcpiDsMethodDataInitArgs (WalkState->Params, + ACPI_METHOD_NUM_ARGS, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + else + { + /* + * Setup the current scope. + * Find a Named Op that has a namespace node associated with it. + * search upwards from this Op. Current scope is the first + * Op with a namespace node. + */ + ExtraOp = ParserState->StartOp; + while (ExtraOp && !ExtraOp->Common.Node) + { + ExtraOp = ExtraOp->Common.Parent; + } + + if (!ExtraOp) + { + ParserState->StartNode = NULL; + } + else + { + ParserState->StartNode = ExtraOp->Common.Node; + } + + if (ParserState->StartNode) + { + /* Push start scope on scope stack and make it current */ + + Status = AcpiDsScopeStackPush (ParserState->StartNode, + ParserState->StartNode->Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + + Status = AcpiDsInitCallbacks (WalkState, PassNumber); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsDeleteWalkState + * + * PARAMETERS: WalkState - State to delete + * + * RETURN: Status + * + * DESCRIPTION: Delete a walk state including all internal data structures + * + ******************************************************************************/ + +void +AcpiDsDeleteWalkState ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState); + + + if (!WalkState) + { + return; + } + + if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK) + { + ACPI_ERROR ((AE_INFO, "%p is not a valid walk state", + WalkState)); + return; + } + + /* There should not be any open scopes */ + + if (WalkState->ParserState.Scope) + { + ACPI_ERROR ((AE_INFO, "%p walk still has a scope list", + WalkState)); + AcpiPsCleanupScope (&WalkState->ParserState); + } + + /* Always must free any linked control states */ + + while (WalkState->ControlState) + { + State = WalkState->ControlState; + WalkState->ControlState = State->Common.Next; + + AcpiUtDeleteGenericState (State); + } + + /* Always must free any linked parse states */ + + while (WalkState->ScopeInfo) + { + State = WalkState->ScopeInfo; + WalkState->ScopeInfo = State->Common.Next; + + AcpiUtDeleteGenericState (State); + } + + /* Always must free any stacked result states */ + + while (WalkState->Results) + { + State = WalkState->Results; + WalkState->Results = State->Common.Next; + + AcpiUtDeleteGenericState (State); + } + + ACPI_FREE (WalkState); + return_VOID; +} + + diff --git a/source/components/events/evevent.c b/source/components/events/evevent.c new file mode 100644 index 000000000000..b5a7acde7293 --- /dev/null +++ b/source/components/events/evevent.c @@ -0,0 +1,336 @@ +/****************************************************************************** + * + * Module Name: evevent - Fixed Event handling and dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evevent") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static ACPI_STATUS +AcpiEvFixedEventInitialize ( + void); + +static UINT32 +AcpiEvFixedEventDispatch ( + UINT32 Event); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInitializeEvents + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitializeEvents ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvInitializeEvents); + + + /* If Hardware Reduced flag is set, there are no fixed events */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Initialize the Fixed and General Purpose Events. This is done prior to + * enabling SCIs to prevent interrupts from occurring before the handlers + * are installed. + */ + Status = AcpiEvFixedEventInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to initialize fixed events")); + return_ACPI_STATUS (Status); + } + + Status = AcpiEvGpeInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to initialize general purpose events")); + return_ACPI_STATUS (Status); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallXruptHandlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInstallXruptHandlers ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvInstallXruptHandlers); + + + /* If Hardware Reduced flag is set, there is no ACPI h/w */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* Install the SCI handler */ + + Status = AcpiEvInstallSciHandler (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to install System Control Interrupt handler")); + return_ACPI_STATUS (Status); + } + + /* Install the handler for the Global Lock */ + + Status = AcpiEvInitGlobalLockHandler (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to initialize Global Lock handler")); + return_ACPI_STATUS (Status); + } + + AcpiGbl_EventsInitialized = TRUE; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvFixedEventInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install the fixed event handlers and disable all fixed events. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvFixedEventInitialize ( + void) +{ + UINT32 i; + ACPI_STATUS Status; + + + /* + * Initialize the structure that keeps track of fixed event handlers and + * enable the fixed events. + */ + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + AcpiGbl_FixedEventHandlers[i].Handler = NULL; + AcpiGbl_FixedEventHandlers[i].Context = NULL; + + /* Disable the fixed event */ + + if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF) + { + Status = AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[i].EnableRegisterId, + ACPI_DISABLE_EVENT); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvFixedEventDetect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Checks the PM status register for active fixed events + * + ******************************************************************************/ + +UINT32 +AcpiEvFixedEventDetect ( + void) +{ + UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; + UINT32 FixedStatus; + UINT32 FixedEnable; + UINT32 i; + + + ACPI_FUNCTION_NAME (EvFixedEventDetect); + + + /* + * Read the fixed feature status and enable registers, as all the cases + * depend on their values. Ignore errors here. + */ + (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus); + (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable); + + ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, + "Fixed Event Block: Enable %08X Status %08X\n", + FixedEnable, FixedStatus)); + + /* + * Check for all possible Fixed Events and dispatch those that are active + */ + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + /* Both the status and enable bits must be on for this event */ + + if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) && + (FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask)) + { + /* + * Found an active (signalled) event. Invoke global event + * handler if present. + */ + AcpiFixedEventCount[i]++; + if (AcpiGbl_GlobalEventHandler) + { + AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL, + i, AcpiGbl_GlobalEventHandlerContext); + } + + IntStatus |= AcpiEvFixedEventDispatch (i); + } + } + + return (IntStatus); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvFixedEventDispatch + * + * PARAMETERS: Event - Event type + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Clears the status bit for the requested event, calls the + * handler that previously registered for the event. + * + ******************************************************************************/ + +static UINT32 +AcpiEvFixedEventDispatch ( + UINT32 Event) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* Clear the status bit */ + + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].StatusRegisterId, + ACPI_CLEAR_STATUS); + + /* + * Make sure we've got a handler. If not, report an error. The event is + * disabled to prevent further interrupts. + */ + if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler) + { + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, + ACPI_DISABLE_EVENT); + + ACPI_ERROR ((AE_INFO, + "No installed handler for fixed event [0x%08X]", + Event)); + + return (ACPI_INTERRUPT_NOT_HANDLED); + } + + /* Invoke the Fixed Event handler */ + + return ((AcpiGbl_FixedEventHandlers[Event].Handler)( + AcpiGbl_FixedEventHandlers[Event].Context)); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ + + diff --git a/source/components/events/evglock.c b/source/components/events/evglock.c new file mode 100644 index 000000000000..f40d1295086c --- /dev/null +++ b/source/components/events/evglock.c @@ -0,0 +1,377 @@ +/****************************************************************************** + * + * Module Name: evglock - Global Lock support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evglock") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static UINT32 +AcpiEvGlobalLockHandler ( + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInitGlobalLockHandler + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the global lock release event + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitGlobalLockHandler ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler); + + + /* If Hardware Reduced flag is set, there is no global lock */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* Attempt installation of the global lock handler */ + + Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, + AcpiEvGlobalLockHandler, NULL); + + /* + * If the global lock does not exist on this platform, the attempt to + * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). + * Map to AE_OK, but mark global lock as not present. Any attempt to + * actually use the global lock will be flagged with an error. + */ + AcpiGbl_GlobalLockPresent = FALSE; + if (Status == AE_NO_HARDWARE_RESPONSE) + { + ACPI_ERROR ((AE_INFO, + "No response from Global Lock hardware, disabling lock")); + + return_ACPI_STATUS (AE_OK); + } + + Status = AcpiOsCreateLock (&AcpiGbl_GlobalLockPendingLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiGbl_GlobalLockPending = FALSE; + AcpiGbl_GlobalLockPresent = TRUE; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvRemoveGlobalLockHandler + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Remove the handler for the Global Lock + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvRemoveGlobalLockHandler ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler); + + AcpiGbl_GlobalLockPresent = FALSE; + Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL, + AcpiEvGlobalLockHandler); + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGlobalLockHandler + * + * PARAMETERS: Context - From thread interface, not used + * + * RETURN: ACPI_INTERRUPT_HANDLED + * + * DESCRIPTION: Invoked directly from the SCI handler when a global lock + * release interrupt occurs. If there is actually a pending + * request for the lock, signal the waiting thread. + * + ******************************************************************************/ + +static UINT32 +AcpiEvGlobalLockHandler ( + void *Context) +{ + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); + + /* + * If a request for the global lock is not actually pending, + * we are done. This handles "spurious" global lock interrupts + * which are possible (and have been seen) with bad BIOSs. + */ + if (!AcpiGbl_GlobalLockPending) + { + goto CleanupAndExit; + } + + /* + * Send a unit to the global lock semaphore. The actual acquisition + * of the global lock will be performed by the waiting thread. + */ + Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); + } + + AcpiGbl_GlobalLockPending = FALSE; + + +CleanupAndExit: + + AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); + return (ACPI_INTERRUPT_HANDLED); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiEvAcquireGlobalLock + * + * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. + * + * RETURN: Status + * + * DESCRIPTION: Attempt to gain ownership of the Global Lock. + * + * MUTEX: Interpreter must be locked + * + * Note: The original implementation allowed multiple threads to "acquire" the + * Global Lock, and the OS would hold the lock until the last thread had + * released it. However, this could potentially starve the BIOS out of the + * lock, especially in the case where there is a tight handshake between the + * Embedded Controller driver and the BIOS. Therefore, this implementation + * allows only one thread to acquire the HW Global Lock at a time, and makes + * the global lock appear as a standard mutex on the OS side. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiEvAcquireGlobalLock ( + UINT16 Timeout) +{ + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status; + BOOLEAN Acquired = FALSE; + + + ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); + + + /* + * Only one thread can acquire the GL at a time, the GlobalLockMutex + * enforces this. This interface releases the interpreter if we must wait. + */ + Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, + Timeout); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Update the global lock handle and check for wraparound. The handle is + * only used for the external global lock interfaces, but it is updated + * here to properly handle the case where a single thread may acquire the + * lock via both the AML and the AcpiAcquireGlobalLock interfaces. The + * handle is therefore updated on the first acquire from a given thread + * regardless of where the acquisition request originated. + */ + AcpiGbl_GlobalLockHandle++; + if (AcpiGbl_GlobalLockHandle == 0) + { + AcpiGbl_GlobalLockHandle = 1; + } + + /* + * Make sure that a global lock actually exists. If not, just + * treat the lock as a standard mutex. + */ + if (!AcpiGbl_GlobalLockPresent) + { + AcpiGbl_GlobalLockAcquired = TRUE; + return_ACPI_STATUS (AE_OK); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); + + do + { + /* Attempt to acquire the actual hardware lock */ + + ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); + if (Acquired) + { + AcpiGbl_GlobalLockAcquired = TRUE; + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Acquired hardware Global Lock\n")); + break; + } + + /* + * Did not get the lock. The pending bit was set above, and + * we must now wait until we receive the global lock + * released interrupt. + */ + AcpiGbl_GlobalLockPending = TRUE; + AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Waiting for hardware Global Lock\n")); + + /* + * Wait for handshake with the global lock interrupt handler. + * This interface releases the interpreter if we must wait. + */ + Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, + ACPI_WAIT_FOREVER); + + Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); + + } while (ACPI_SUCCESS (Status)); + + AcpiGbl_GlobalLockPending = FALSE; + AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvReleaseGlobalLock + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Releases ownership of the Global Lock. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvReleaseGlobalLock ( + void) +{ + BOOLEAN Pending = FALSE; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (EvReleaseGlobalLock); + + + /* Lock must be already acquired */ + + if (!AcpiGbl_GlobalLockAcquired) + { + ACPI_WARNING ((AE_INFO, + "Cannot release the ACPI Global Lock, it has not been acquired")); + return_ACPI_STATUS (AE_NOT_ACQUIRED); + } + + if (AcpiGbl_GlobalLockPresent) + { + /* Allow any thread to release the lock */ + + ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending); + + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (Pending) + { + Status = AcpiWriteBitRegister ( + ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n")); + } + + AcpiGbl_GlobalLockAcquired = FALSE; + + /* Release the local GL mutex */ + + AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evgpe.c b/source/components/events/evgpe.c new file mode 100644 index 000000000000..a3781a55c66b --- /dev/null +++ b/source/components/events/evgpe.c @@ -0,0 +1,831 @@ +/****************************************************************************** + * + * Module Name: evgpe - General Purpose Event handling and dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpe") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static void ACPI_SYSTEM_XFACE +AcpiEvAsynchExecuteGpeMethod ( + void *Context); + +static void ACPI_SYSTEM_XFACE +AcpiEvAsynchEnableGpe ( + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvUpdateGpeEnableMask + * + * PARAMETERS: GpeEventInfo - GPE to update + * + * RETURN: Status + * + * DESCRIPTION: Updates GPE register enable mask based upon whether there are + * runtime references to this GPE + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvUpdateGpeEnableMask ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + UINT32 RegisterBit; + + + ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); + + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + if (!GpeRegisterInfo) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); + + /* Clear the run bit up front */ + + ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); + + /* Set the mask bit only if there are references to this GPE */ + + if (GpeEventInfo->RuntimeCount) + { + ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvEnableGpe + * + * PARAMETERS: GpeEventInfo - GPE to enable + * + * RETURN: Status + * + * DESCRIPTION: Clear a GPE of stale events and enable it. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvEnableGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvEnableGpe); + + + /* + * We will only allow a GPE to be enabled if it has either an associated + * method (_Lxx/_Exx) or a handler, or is using the implicit notify + * feature. Otherwise, the GPE will be immediately disabled by + * AcpiEvGpeDispatch the first time it fires. + */ + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) + { + return_ACPI_STATUS (AE_NO_HANDLER); + } + + /* Clear the GPE (of stale events) */ + + Status = AcpiHwClearGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Enable the requested GPE */ + + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAddGpeReference + * + * PARAMETERS: GpeEventInfo - Add a reference to this GPE + * + * RETURN: Status + * + * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is + * hardware-enabled. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvAddGpeReference ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (EvAddGpeReference); + + + if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) + { + return_ACPI_STATUS (AE_LIMIT); + } + + GpeEventInfo->RuntimeCount++; + if (GpeEventInfo->RuntimeCount == 1) + { + /* Enable on first reference */ + + Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiEvEnableGpe (GpeEventInfo); + } + + if (ACPI_FAILURE (Status)) + { + GpeEventInfo->RuntimeCount--; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvRemoveGpeReference + * + * PARAMETERS: GpeEventInfo - Remove a reference to this GPE + * + * RETURN: Status + * + * DESCRIPTION: Remove a reference to a GPE. When the last reference is + * removed, the GPE is hardware-disabled. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvRemoveGpeReference ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (EvRemoveGpeReference); + + + if (!GpeEventInfo->RuntimeCount) + { + return_ACPI_STATUS (AE_LIMIT); + } + + GpeEventInfo->RuntimeCount--; + if (!GpeEventInfo->RuntimeCount) + { + /* Disable on last reference */ + + Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + } + + if (ACPI_FAILURE (Status)) + { + GpeEventInfo->RuntimeCount++; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvLowGetGpeInfo + * + * PARAMETERS: GpeNumber - Raw GPE number + * GpeBlock - A GPE info block + * + * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber + * is not within the specified GPE block) + * + * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is + * the low-level implementation of EvGetGpeEventInfo. + * + ******************************************************************************/ + +ACPI_GPE_EVENT_INFO * +AcpiEvLowGetGpeInfo ( + UINT32 GpeNumber, + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + UINT32 GpeIndex; + + + /* + * Validate that the GpeNumber is within the specified GpeBlock. + * (Two steps) + */ + if (!GpeBlock || + (GpeNumber < GpeBlock->BlockBaseNumber)) + { + return (NULL); + } + + GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; + if (GpeIndex >= GpeBlock->GpeCount) + { + return (NULL); + } + + return (&GpeBlock->EventInfo[GpeIndex]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGetGpeEventInfo + * + * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 + * GpeNumber - Raw GPE number + * + * RETURN: A GPE EventInfo struct. NULL if not a valid GPE + * + * DESCRIPTION: Returns the EventInfo struct associated with this GPE. + * Validates the GpeBlock and the GpeNumber + * + * Should be called only when the GPE lists are semaphore locked + * and not subject to change. + * + ******************************************************************************/ + +ACPI_GPE_EVENT_INFO * +AcpiEvGetGpeEventInfo ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_GPE_EVENT_INFO *GpeInfo; + UINT32 i; + + + ACPI_FUNCTION_ENTRY (); + + + /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ + + if (!GpeDevice) + { + /* Examine GPE Block 0 and 1 (These blocks are permanent) */ + + for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) + { + GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, + AcpiGbl_GpeFadtBlocks[i]); + if (GpeInfo) + { + return (GpeInfo); + } + } + + /* The GpeNumber was not in the range of either FADT GPE block */ + + return (NULL); + } + + /* A Non-NULL GpeDevice means this is a GPE Block Device */ + + ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); + if (!ObjDesc || + !ObjDesc->Device.GpeBlock) + { + return (NULL); + } + + return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGpeDetect + * + * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. + * Can have multiple GPE blocks attached. + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Detect if any GP events have occurred. This function is + * executed at interrupt level. + * + ******************************************************************************/ + +UINT32 +AcpiEvGpeDetect ( + ACPI_GPE_XRUPT_INFO *GpeXruptList) +{ + ACPI_STATUS Status; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; + UINT8 EnabledStatusByte; + UINT32 StatusReg; + UINT32 EnableReg; + ACPI_CPU_FLAGS Flags; + UINT32 i; + UINT32 j; + + + ACPI_FUNCTION_NAME (EvGpeDetect); + + /* Check for the case where there are no GPEs */ + + if (!GpeXruptList) + { + return (IntStatus); + } + + /* + * We need to obtain the GPE lock for both the data structs and registers + * Note: Not necessary to obtain the hardware lock, since the GPE + * registers are owned by the GpeLock. + */ + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Examine all GPE blocks attached to this interrupt level */ + + GpeBlock = GpeXruptList->GpeBlockListHead; + while (GpeBlock) + { + /* + * Read all of the 8-bit GPE status and enable registers in this GPE + * block, saving all of them. Find all currently active GP events. + */ + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Get the next status/enable pair */ + + GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; + + /* + * Optimization: If there are no GPEs enabled within this + * register, we can safely ignore the entire register. + */ + if (!(GpeRegisterInfo->EnableForRun | + GpeRegisterInfo->EnableForWake)) + { + continue; + } + + /* Read the Status Register */ + + Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* Read the Enable Register */ + + Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, + "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", + GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); + + /* Check if there is anything active at all in this register */ + + EnabledStatusByte = (UINT8) (StatusReg & EnableReg); + if (!EnabledStatusByte) + { + /* No active GPEs in this register, move on */ + + continue; + } + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + /* Examine one GPE bit */ + + if (EnabledStatusByte & (1 << j)) + { + /* + * Found an active GPE. Dispatch the event to a handler + * or method. + */ + IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, + &GpeBlock->EventInfo[((ACPI_SIZE) i * + ACPI_GPE_REGISTER_WIDTH) + j], + j + GpeRegisterInfo->BaseGpeNumber); + } + } + } + + GpeBlock = GpeBlock->Next; + } + +UnlockAndExit: + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return (IntStatus); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAsynchExecuteGpeMethod + * + * PARAMETERS: Context (GpeEventInfo) - Info for this GPE + * + * RETURN: None + * + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of AcpiOsExecute and + * therefore does NOT execute at interrupt level - so that + * the control method itself is not executed in the context of + * an interrupt handler. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE +AcpiEvAsynchExecuteGpeMethod ( + void *Context) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; + ACPI_STATUS Status; + ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; + ACPI_EVALUATE_INFO *Info; + + + ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); + + + /* Allocate a local GPE block */ + + LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); + if (!LocalGpeEventInfo) + { + ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, + "while handling a GPE")); + return_VOID; + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* Must revalidate the GpeNumber/GpeBlock */ + + if (!AcpiEvValidGpeEvent (GpeEventInfo)) + { + Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_VOID; + } + + /* + * Take a snapshot of the GPE info for this level - we copy the info to + * prevent a race condition with RemoveHandler/RemoveBlock. + */ + ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, + sizeof (ACPI_GPE_EVENT_INFO)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* Do the correct dispatch - normal method or implicit notify */ + + switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) + { + case ACPI_GPE_DISPATCH_NOTIFY: + + /* + * Implicit notify. + * Dispatch a DEVICE_WAKE notify to the appropriate handler. + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + Status = AcpiEvQueueNotifyRequest ( + LocalGpeEventInfo->Dispatch.DeviceNode, + ACPI_NOTIFY_DEVICE_WAKE); + break; + + case ACPI_GPE_DISPATCH_METHOD: + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + Status = AE_NO_MEMORY; + } + else + { + /* + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the + * _Lxx/_Exx control method that corresponds to this GPE + */ + Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; + Info->Flags = ACPI_IGNORE_RETURN_VALUE; + + Status = AcpiNsEvaluate (Info); + ACPI_FREE (Info); + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "while evaluating GPE method [%4.4s]", + AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); + } + + break; + + default: + return_VOID; /* Should never happen */ + } + + /* Defer enabling of GPE until all notify handlers are done */ + + Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, + AcpiEvAsynchEnableGpe, LocalGpeEventInfo); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (LocalGpeEventInfo); + } + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAsynchEnableGpe + * + * PARAMETERS: Context (GpeEventInfo) - Info for this GPE + * Callback from AcpiOsExecute + * + * RETURN: None + * + * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to + * complete (i.e., finish execution of Notify) + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE +AcpiEvAsynchEnableGpe ( + void *Context) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; + + + (void) AcpiEvFinishGpe (GpeEventInfo); + + ACPI_FREE (GpeEventInfo); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvFinishGpe + * + * PARAMETERS: GpeEventInfo - Info for this GPE + * + * RETURN: Status + * + * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution + * of a GPE method or a synchronous or asynchronous GPE handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvFinishGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_STATUS Status; + + + if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_LEVEL_TRIGGERED) + { + /* + * GPE is level-triggered, we clear the GPE status bit after + * handling the event. + */ + Status = AcpiHwClearGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + /* + * Enable this GPE, conditionally. This means that the GPE will + * only be physically enabled if the EnableForRun bit is set + * in the EventInfo. + */ + (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGpeDispatch + * + * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 + * GpeEventInfo - Info for this GPE + * GpeNumber - Number relative to the parent GPE block + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) + * or method (e.g. _Lxx/_Exx) handler. + * + * This function executes at interrupt level. + * + ******************************************************************************/ + +UINT32 +AcpiEvGpeDispatch ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 GpeNumber) +{ + ACPI_STATUS Status; + UINT32 ReturnValue; + + + ACPI_FUNCTION_TRACE (EvGpeDispatch); + + + /* Invoke global event handler if present */ + + AcpiGpeCount++; + if (AcpiGbl_GlobalEventHandler) + { + AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, + GpeNumber, AcpiGbl_GlobalEventHandlerContext); + } + + /* + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced. + */ + if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_EDGE_TRIGGERED) + { + Status = AcpiHwClearGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to clear GPE%02X", GpeNumber)); + return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); + } + } + + /* + * Always disable the GPE so that it does not keep firing before + * any asynchronous activity completes (either from the execution + * of a GPE method or an asynchronous GPE handler.) + * + * If there is no handler or method to run, just disable the + * GPE and leave it disabled permanently to prevent further such + * pointless events from firing. + */ + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to disable GPE%02X", GpeNumber)); + return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); + } + + /* + * Dispatch the GPE to either an installed handler or the control + * method associated with this GPE (_Lxx or _Exx). If a handler + * exists, we invoke it and do not attempt to run the method. + * If there is neither a handler nor a method, leave the GPE + * disabled. + */ + switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) + { + case ACPI_GPE_DISPATCH_HANDLER: + + /* Invoke the installed handler (at interrupt level) */ + + ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( + GpeDevice, GpeNumber, + GpeEventInfo->Dispatch.Handler->Context); + + /* If requested, clear (if level-triggered) and reenable the GPE */ + + if (ReturnValue & ACPI_REENABLE_GPE) + { + (void) AcpiEvFinishGpe (GpeEventInfo); + } + break; + + case ACPI_GPE_DISPATCH_METHOD: + case ACPI_GPE_DISPATCH_NOTIFY: + + /* + * Execute the method associated with the GPE + * NOTE: Level-triggered GPEs are cleared after the method completes. + */ + Status = AcpiOsExecute (OSL_GPE_HANDLER, + AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Unable to queue handler for GPE%02X - event disabled", + GpeNumber)); + } + break; + + default: + + /* + * No handler or method to run! + * 03/2010: This case should no longer be possible. We will not allow + * a GPE to be enabled if it has no handler or method. + */ + ACPI_ERROR ((AE_INFO, + "No handler or method for GPE%02X, disabling event", + GpeNumber)); + break; + } + + return_UINT32 (ACPI_INTERRUPT_HANDLED); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evgpeblk.c b/source/components/events/evgpeblk.c new file mode 100644 index 000000000000..c281855c2c8d --- /dev/null +++ b/source/components/events/evgpeblk.c @@ -0,0 +1,550 @@ +/****************************************************************************** + * + * Module Name: evgpeblk - GPE block creation and initialization. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpeblk") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static ACPI_STATUS +AcpiEvInstallGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock, + UINT32 InterruptNumber); + +static ACPI_STATUS +AcpiEvCreateGpeInfoBlocks ( + ACPI_GPE_BLOCK_INFO *GpeBlock); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallGpeBlock + * + * PARAMETERS: GpeBlock - New GPE block + * InterruptNumber - Xrupt to be associated with this + * GPE block + * + * RETURN: Status + * + * DESCRIPTION: Install new GPE block with mutex support + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvInstallGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock, + UINT32 InterruptNumber) +{ + ACPI_GPE_BLOCK_INFO *NextGpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptBlock; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvInstallGpeBlock); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber); + if (!GpeXruptBlock) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* Install the new block at the end of the list with lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (GpeXruptBlock->GpeBlockListHead) + { + NextGpeBlock = GpeXruptBlock->GpeBlockListHead; + while (NextGpeBlock->Next) + { + NextGpeBlock = NextGpeBlock->Next; + } + + NextGpeBlock->Next = GpeBlock; + GpeBlock->Previous = NextGpeBlock; + } + else + { + GpeXruptBlock->GpeBlockListHead = GpeBlock; + } + + GpeBlock->XruptBlock = GpeXruptBlock; + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + +UnlockAndExit: + Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDeleteGpeBlock + * + * PARAMETERS: GpeBlock - Existing GPE block + * + * RETURN: Status + * + * DESCRIPTION: Remove a GPE block + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDeleteGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvInstallGpeBlock); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Disable all GPEs in this block */ + + Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL); + + if (!GpeBlock->Previous && !GpeBlock->Next) + { + /* This is the last GpeBlock on this interrupt */ + + Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + } + else + { + /* Remove the block on this interrupt with lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (GpeBlock->Previous) + { + GpeBlock->Previous->Next = GpeBlock->Next; + } + else + { + GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next; + } + + if (GpeBlock->Next) + { + GpeBlock->Next->Previous = GpeBlock->Previous; + } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + } + + AcpiCurrentGpeCount -= GpeBlock->GpeCount; + + /* Free the GpeBlock */ + + ACPI_FREE (GpeBlock->RegisterInfo); + ACPI_FREE (GpeBlock->EventInfo); + ACPI_FREE (GpeBlock); + +UnlockAndExit: + Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvCreateGpeInfoBlocks + * + * PARAMETERS: GpeBlock - New GPE block + * + * RETURN: Status + * + * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvCreateGpeInfoBlocks ( + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; + ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; + ACPI_GPE_EVENT_INFO *ThisEvent; + ACPI_GPE_REGISTER_INFO *ThisRegister; + UINT32 i; + UINT32 j; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); + + + /* Allocate the GPE register information block */ + + GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( + (ACPI_SIZE) GpeBlock->RegisterCount * + sizeof (ACPI_GPE_REGISTER_INFO)); + if (!GpeRegisterInfo) + { + ACPI_ERROR ((AE_INFO, + "Could not allocate the GpeRegisterInfo table")); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Allocate the GPE EventInfo block. There are eight distinct GPEs + * per register. Initialization to zeros is sufficient. + */ + GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * + sizeof (ACPI_GPE_EVENT_INFO)); + if (!GpeEventInfo) + { + ACPI_ERROR ((AE_INFO, + "Could not allocate the GpeEventInfo table")); + Status = AE_NO_MEMORY; + goto ErrorExit; + } + + /* Save the new Info arrays in the GPE block */ + + GpeBlock->RegisterInfo = GpeRegisterInfo; + GpeBlock->EventInfo = GpeEventInfo; + + /* + * Initialize the GPE Register and Event structures. A goal of these + * tables is to hide the fact that there are two separate GPE register + * sets in a given GPE hardware block, the status registers occupy the + * first half, and the enable registers occupy the second half. + */ + ThisRegister = GpeRegisterInfo; + ThisEvent = GpeEventInfo; + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Init the RegisterInfo for this GPE register (8 GPEs) */ + + ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber + + (i * ACPI_GPE_REGISTER_WIDTH)); + + ThisRegister->StatusAddress.Address = + GpeBlock->BlockAddress.Address + i; + + ThisRegister->EnableAddress.Address = + GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount; + + ThisRegister->StatusAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; + ThisRegister->EnableAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; + ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; + ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; + ThisRegister->StatusAddress.BitOffset = 0; + ThisRegister->EnableAddress.BitOffset = 0; + + /* Init the EventInfo for each GPE within this register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); + ThisEvent->RegisterInfo = ThisRegister; + ThisEvent++; + } + + /* Disable all GPEs within this register */ + + Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + /* Clear any pending GPE events within this register */ + + Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + ThisRegister++; + } + + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + if (GpeRegisterInfo) + { + ACPI_FREE (GpeRegisterInfo); + } + if (GpeEventInfo) + { + ACPI_FREE (GpeEventInfo); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvCreateGpeBlock + * + * PARAMETERS: GpeDevice - Handle to the parent GPE block + * GpeBlockAddress - Address and SpaceID + * RegisterCount - Number of GPE register pairs in the block + * GpeBlockBaseNumber - Starting GPE number for the block + * InterruptNumber - H/W interrupt for the block + * ReturnGpeBlock - Where the new block descriptor is returned + * + * RETURN: Status + * + * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within + * the block are disabled at exit. + * Note: Assumes namespace is locked. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvCreateGpeBlock ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GENERIC_ADDRESS *GpeBlockAddress, + UINT32 RegisterCount, + UINT8 GpeBlockBaseNumber, + UINT32 InterruptNumber, + ACPI_GPE_BLOCK_INFO **ReturnGpeBlock) +{ + ACPI_STATUS Status; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_WALK_INFO WalkInfo; + + + ACPI_FUNCTION_TRACE (EvCreateGpeBlock); + + + if (!RegisterCount) + { + return_ACPI_STATUS (AE_OK); + } + + /* Allocate a new GPE block */ + + GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); + if (!GpeBlock) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize the new GPE block */ + + GpeBlock->Node = GpeDevice; + GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); + GpeBlock->Initialized = FALSE; + GpeBlock->RegisterCount = RegisterCount; + GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; + + ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress, + sizeof (ACPI_GENERIC_ADDRESS)); + + /* + * Create the RegisterInfo and EventInfo sub-structures + * Note: disables and clears all GPEs in the block + */ + Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (GpeBlock); + return_ACPI_STATUS (Status); + } + + /* Install the new block in the global lists */ + + Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (GpeBlock); + return_ACPI_STATUS (Status); + } + + AcpiGbl_AllGpesInitialized = FALSE; + + /* Find all GPE methods (_Lxx or_Exx) for this block */ + + WalkInfo.GpeBlock = GpeBlock; + WalkInfo.GpeDevice = GpeDevice; + WalkInfo.ExecuteByOwnerId = FALSE; + + Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); + + /* Return the new block */ + + if (ReturnGpeBlock) + { + (*ReturnGpeBlock) = GpeBlock; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", + (UINT32) GpeBlock->BlockBaseNumber, + (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), + GpeDevice->Name.Ascii, GpeBlock->RegisterCount, + InterruptNumber)); + + /* Update global count of currently available GPEs */ + + AcpiCurrentGpeCount += GpeBlock->GpeCount; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInitializeGpeBlock + * + * PARAMETERS: ACPI_GPE_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have + * associated methods. + * Note: Assumes namespace is locked. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitializeGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Ignored) +{ + ACPI_STATUS Status; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 GpeEnabledCount; + UINT32 GpeIndex; + UINT32 i; + UINT32 j; + + + ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); + + + /* + * Ignore a null GPE block (e.g., if no GPE block 1 exists), and + * any GPE blocks that have been initialized already. + */ + if (!GpeBlock || GpeBlock->Initialized) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Enable all GPEs that have a corresponding method and have the + * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block + * must be enabled via the acpi_enable_gpe() interface. + */ + GpeEnabledCount = 0; + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + /* Get the info block for this particular GPE */ + + GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; + GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; + + /* + * Ignore GPEs that have no corresponding _Lxx/_Exx method + * and GPEs that are used to wake the system + */ + if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NONE) || + ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) || + (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) + { + continue; + } + + Status = AcpiEvAddGpeReference (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not enable GPE 0x%02X", + GpeIndex + GpeBlock->BlockBaseNumber)); + continue; + } + + GpeEnabledCount++; + } + } + + if (GpeEnabledCount) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "Enabled %u GPEs in this block\n", GpeEnabledCount)); + } + + GpeBlock->Initialized = TRUE; + return_ACPI_STATUS (AE_OK); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evgpeinit.c b/source/components/events/evgpeinit.c new file mode 100644 index 000000000000..f8962e947f27 --- /dev/null +++ b/source/components/events/evgpeinit.c @@ -0,0 +1,462 @@ +/****************************************************************************** + * + * Module Name: evgpeinit - System GPE initialization and update + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpeinit") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* + * Note: History of _PRW support in ACPICA + * + * Originally (2000 - 2010), the GPE initialization code performed a walk of + * the entire namespace to execute the _PRW methods and detect all GPEs + * capable of waking the system. + * + * As of 10/2010, the _PRW method execution has been removed since it is + * actually unnecessary. The host OS must in fact execute all _PRW methods + * in order to identify the device/power-resource dependencies. We now put + * the onus on the host OS to identify the wake GPEs as part of this process + * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This + * not only reduces the complexity of the ACPICA initialization code, but in + * some cases (on systems with very large namespaces) it should reduce the + * kernel boot time as well. + */ + +/******************************************************************************* + * + * FUNCTION: AcpiEvGpeInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvGpeInitialize ( + void) +{ + UINT32 RegisterCount0 = 0; + UINT32 RegisterCount1 = 0; + UINT32 GpeNumberMax = 0; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvGpeInitialize); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Initialize the GPE Block(s) defined in the FADT + * + * Why the GPE register block lengths are divided by 2: From the ACPI + * Spec, section "General-Purpose Event Registers", we have: + * + * "Each register block contains two registers of equal length + * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the + * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN + * The length of the GPE1_STS and GPE1_EN registers is equal to + * half the GPE1_LEN. If a generic register block is not supported + * then its respective block pointer and block length values in the + * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need + * to be the same size." + */ + + /* + * Determine the maximum GPE number for this machine. + * + * Note: both GPE0 and GPE1 are optional, and either can exist without + * the other. + * + * If EITHER the register length OR the block address are zero, then that + * particular block is not supported. + */ + if (AcpiGbl_FADT.Gpe0BlockLength && + AcpiGbl_FADT.XGpe0Block.Address) + { + /* GPE block 0 exists (has both length and address > 0) */ + + RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); + + GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; + + /* Install GPE Block 0 */ + + Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, + &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, + AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not create GPE Block 0")); + } + } + + if (AcpiGbl_FADT.Gpe1BlockLength && + AcpiGbl_FADT.XGpe1Block.Address) + { + /* GPE block 1 exists (has both length and address > 0) */ + + RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); + + /* Check for GPE0/GPE1 overlap (if both banks exist) */ + + if ((RegisterCount0) && + (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) + { + ACPI_ERROR ((AE_INFO, + "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " + "(GPE %u to %u) - Ignoring GPE1", + GpeNumberMax, AcpiGbl_FADT.Gpe1Base, + AcpiGbl_FADT.Gpe1Base + + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); + + /* Ignore GPE1 block by setting the register count to zero */ + + RegisterCount1 = 0; + } + else + { + /* Install GPE Block 1 */ + + Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, + &AcpiGbl_FADT.XGpe1Block, RegisterCount1, + AcpiGbl_FADT.Gpe1Base, + AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not create GPE Block 1")); + } + + /* + * GPE0 and GPE1 do not have to be contiguous in the GPE number + * space. However, GPE0 always starts at GPE number zero. + */ + GpeNumberMax = AcpiGbl_FADT.Gpe1Base + + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); + } + } + + /* Exit if there are no GPE registers */ + + if ((RegisterCount0 + RegisterCount1) == 0) + { + /* GPEs are not required by ACPI, this is OK */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "There are no GPE blocks defined in the FADT\n")); + Status = AE_OK; + goto Cleanup; + } + + /* Check for Max GPE number out-of-range */ + + if (GpeNumberMax > ACPI_GPE_MAX) + { + ACPI_ERROR ((AE_INFO, + "Maximum GPE number from FADT is too large: 0x%X", + GpeNumberMax)); + Status = AE_BAD_VALUE; + goto Cleanup; + } + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvUpdateGpes + * + * PARAMETERS: TableOwnerId - ID of the newly-loaded ACPI table + * + * RETURN: None + * + * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a + * result of a Load() or LoadTable() operation. If new GPE + * methods have been installed, register the new methods. + * + ******************************************************************************/ + +void +AcpiEvUpdateGpes ( + ACPI_OWNER_ID TableOwnerId) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_WALK_INFO WalkInfo; + ACPI_STATUS Status = AE_OK; + + + /* + * Find any _Lxx/_Exx GPE methods that have just been loaded. + * + * Any GPEs that correspond to new _Lxx/_Exx methods are immediately + * enabled. + * + * Examine the namespace underneath each GpeDevice within the + * GpeBlock lists. + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return; + } + + WalkInfo.Count = 0; + WalkInfo.OwnerId = TableOwnerId; + WalkInfo.ExecuteByOwnerId = TRUE; + + /* Walk the interrupt level descriptor list */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + /* Walk all Gpe Blocks attached to this interrupt level */ + + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + WalkInfo.GpeBlock = GpeBlock; + WalkInfo.GpeDevice = GpeBlock->Node; + + Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, + WalkInfo.GpeDevice, ACPI_UINT32_MAX, + ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, + NULL, &WalkInfo, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While decoding _Lxx/_Exx methods")); + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptInfo = GpeXruptInfo->Next; + } + + if (WalkInfo.Count) + { + ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvMatchGpeMethod + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a + * control method under the _GPE portion of the namespace. + * Extract the name and GPE type from the object, saving this + * information for quick lookup during GPE dispatch. Allows a + * per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the + * WalkInfo parameter block. + * + * The name of each GPE control method is of the form: + * "_Lxx" or "_Exx", where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * xx - is the GPE number [in HEX] + * + * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods + * with that owner. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvMatchGpeMethod ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 GpeNumber; + char Name[ACPI_NAME_SIZE + 1]; + UINT8 Type; + + + ACPI_FUNCTION_TRACE (EvMatchGpeMethod); + + + /* Check if requested OwnerId matches this OwnerId */ + + if ((WalkInfo->ExecuteByOwnerId) && + (MethodNode->OwnerId != WalkInfo->OwnerId)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Match and decode the _Lxx and _Exx GPE method names + * + * 1) Extract the method name and null terminate it + */ + ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); + Name[ACPI_NAME_SIZE] = 0; + + /* 2) Name must begin with an underscore */ + + if (Name[0] != '_') + { + return_ACPI_STATUS (AE_OK); /* Ignore this method */ + } + + /* + * 3) Edge/Level determination is based on the 2nd character + * of the method name + */ + switch (Name[1]) + { + case 'L': + Type = ACPI_GPE_LEVEL_TRIGGERED; + break; + + case 'E': + Type = ACPI_GPE_EDGE_TRIGGERED; + break; + + default: + /* Unknown method type, just ignore it */ + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Ignoring unknown GPE method type: %s " + "(name not of form _Lxx or _Exx)", Name)); + return_ACPI_STATUS (AE_OK); + } + + /* 4) The last two characters of the name are the hex GPE Number */ + + GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); + if (GpeNumber == ACPI_UINT32_MAX) + { + /* Conversion failed; invalid method, just ignore it */ + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Could not extract GPE number from name: %s " + "(name is not of form _Lxx or _Exx)", Name)); + return_ACPI_STATUS (AE_OK); + } + + /* Ensure that we have a valid GPE number for this GPE block */ + + GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); + if (!GpeEventInfo) + { + /* + * This GpeNumber is not valid for this GPE block, just ignore it. + * However, it may be valid for a different GPE block, since GPE0 + * and GPE1 methods both appear under \_GPE. + */ + return_ACPI_STATUS (AE_OK); + } + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) + { + /* If there is already a handler, ignore this GPE method */ + + return_ACPI_STATUS (AE_OK); + } + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_METHOD) + { + /* + * If there is already a method, ignore this method. But check + * for a type mismatch (if both the _Lxx AND _Exx exist) + */ + if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) + { + ACPI_ERROR ((AE_INFO, + "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", + GpeNumber, GpeNumber, GpeNumber)); + } + return_ACPI_STATUS (AE_OK); + } + + /* + * Add the GPE information from above to the GpeEventInfo block for + * use during dispatch of this GPE. + */ + GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); + GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); + GpeEventInfo->Dispatch.MethodNode = MethodNode; + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Registered GPE method %s as GPE number 0x%.2X\n", + Name, GpeNumber)); + return_ACPI_STATUS (AE_OK); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evgpeutil.c b/source/components/events/evgpeutil.c new file mode 100644 index 000000000000..70580cd853c9 --- /dev/null +++ b/source/components/events/evgpeutil.c @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * Module Name: evgpeutil - GPE utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpeutil") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/******************************************************************************* + * + * FUNCTION: AcpiEvWalkGpeList + * + * PARAMETERS: GpeWalkCallback - Routine called for each GPE block + * Context - Value passed to callback + * + * RETURN: Status + * + * DESCRIPTION: Walk the GPE lists. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvWalkGpeList ( + ACPI_GPE_CALLBACK GpeWalkCallback, + void *Context) +{ + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_STATUS Status = AE_OK; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvWalkGpeList); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Walk the interrupt level descriptor list */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + /* Walk all Gpe Blocks attached to this interrupt level */ + + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + /* One callback per GPE block */ + + Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_END) /* Callback abort */ + { + Status = AE_OK; + } + goto UnlockAndExit; + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptInfo = GpeXruptInfo->Next; + } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvValidGpeEvent + * + * PARAMETERS: GpeEventInfo - Info for this GPE + * + * RETURN: TRUE if the GpeEvent is valid + * + * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. + * Should be called only when the GPE lists are semaphore locked + * and not subject to change. + * + ******************************************************************************/ + +BOOLEAN +AcpiEvValidGpeEvent ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptBlock; + ACPI_GPE_BLOCK_INFO *GpeBlock; + + + ACPI_FUNCTION_ENTRY (); + + + /* No need for spin lock since we are not changing any list elements */ + + /* Walk the GPE interrupt levels */ + + GpeXruptBlock = AcpiGbl_GpeXruptListHead; + while (GpeXruptBlock) + { + GpeBlock = GpeXruptBlock->GpeBlockListHead; + + /* Walk the GPE blocks on this interrupt level */ + + while (GpeBlock) + { + if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) && + (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo)) + { + return (TRUE); + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptBlock = GpeXruptBlock->Next; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGetGpeDevice + * + * PARAMETERS: GPE_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Matches the input GPE index (0-CurrentGpeCount) with a GPE + * block device. NULL if the GPE is one of the FADT-defined GPEs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvGetGpeDevice ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + ACPI_GPE_DEVICE_INFO *Info = Context; + + + /* Increment Index by the number of GPEs in this block */ + + Info->NextBlockBaseIndex += GpeBlock->GpeCount; + + if (Info->Index < Info->NextBlockBaseIndex) + { + /* + * The GPE index is within this block, get the node. Leave the node + * NULL for the FADT-defined GPEs + */ + if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE) + { + Info->GpeDevice = GpeBlock->Node; + } + + Info->Status = AE_OK; + return (AE_CTRL_END); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGetGpeXruptBlock + * + * PARAMETERS: InterruptNumber - Interrupt for a GPE block + * + * RETURN: A GPE interrupt block + * + * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt + * block per unique interrupt level used for GPEs. Should be + * called only when the GPE lists are semaphore locked and not + * subject to change. + * + ******************************************************************************/ + +ACPI_GPE_XRUPT_INFO * +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber) +{ + ACPI_GPE_XRUPT_INFO *NextGpeXrupt; + ACPI_GPE_XRUPT_INFO *GpeXrupt; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock); + + + /* No need for lock since we are not changing any list elements here */ + + NextGpeXrupt = AcpiGbl_GpeXruptListHead; + while (NextGpeXrupt) + { + if (NextGpeXrupt->InterruptNumber == InterruptNumber) + { + return_PTR (NextGpeXrupt); + } + + NextGpeXrupt = NextGpeXrupt->Next; + } + + /* Not found, must allocate a new xrupt descriptor */ + + GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); + if (!GpeXrupt) + { + return_PTR (NULL); + } + + GpeXrupt->InterruptNumber = InterruptNumber; + + /* Install new interrupt descriptor with spin lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (AcpiGbl_GpeXruptListHead) + { + NextGpeXrupt = AcpiGbl_GpeXruptListHead; + while (NextGpeXrupt->Next) + { + NextGpeXrupt = NextGpeXrupt->Next; + } + + NextGpeXrupt->Next = GpeXrupt; + GpeXrupt->Previous = NextGpeXrupt; + } + else + { + AcpiGbl_GpeXruptListHead = GpeXrupt; + } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Install new interrupt handler if not SCI_INT */ + + if (InterruptNumber != AcpiGbl_FADT.SciInterrupt) + { + Status = AcpiOsInstallInterruptHandler (InterruptNumber, + AcpiEvGpeXruptHandler, GpeXrupt); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not install GPE interrupt handler at level 0x%X", + InterruptNumber)); + return_PTR (NULL); + } + } + + return_PTR (GpeXrupt); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDeleteGpeXrupt + * + * PARAMETERS: GpeXrupt - A GPE interrupt info block + * + * RETURN: Status + * + * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated + * interrupt handler if not the SCI interrupt. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDeleteGpeXrupt ( + ACPI_GPE_XRUPT_INFO *GpeXrupt) +{ + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt); + + + /* We never want to remove the SCI interrupt handler */ + + if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt) + { + GpeXrupt->GpeBlockListHead = NULL; + return_ACPI_STATUS (AE_OK); + } + + /* Disable this interrupt */ + + Status = AcpiOsRemoveInterruptHandler ( + GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Unlink the interrupt block with lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (GpeXrupt->Previous) + { + GpeXrupt->Previous->Next = GpeXrupt->Next; + } + else + { + /* No previous, update list head */ + + AcpiGbl_GpeXruptListHead = GpeXrupt->Next; + } + + if (GpeXrupt->Next) + { + GpeXrupt->Next->Previous = GpeXrupt->Previous; + } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Free the block */ + + ACPI_FREE (GpeXrupt); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDeleteGpeHandlers + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Delete all Handler objects found in the GPE data structs. + * Used only prior to termination. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDeleteGpeHandlers ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 i; + UINT32 j; + + + ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers); + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * + ACPI_GPE_REGISTER_WIDTH) + j]; + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) + { + ACPI_FREE (GpeEventInfo->Dispatch.Handler); + GpeEventInfo->Dispatch.Handler = NULL; + GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; + } + } + } + + return_ACPI_STATUS (AE_OK); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evmisc.c b/source/components/events/evmisc.c new file mode 100644 index 000000000000..69a90870add8 --- /dev/null +++ b/source/components/events/evmisc.c @@ -0,0 +1,377 @@ +/****************************************************************************** + * + * Module Name: evmisc - Miscellaneous event manager support functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evmisc") + + +/* Local prototypes */ + +static void ACPI_SYSTEM_XFACE +AcpiEvNotifyDispatch ( + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvIsNotifyObject + * + * PARAMETERS: Node - Node to check + * + * RETURN: TRUE if notifies allowed on this object + * + * DESCRIPTION: Check type of node for a object that supports notifies. + * + * TBD: This could be replaced by a flag bit in the node. + * + ******************************************************************************/ + +BOOLEAN +AcpiEvIsNotifyObject ( + ACPI_NAMESPACE_NODE *Node) +{ + switch (Node->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + /* + * These are the ONLY objects that can receive ACPI notifications + */ + return (TRUE); + + default: + return (FALSE); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvQueueNotifyRequest + * + * PARAMETERS: Node - NS node for the notified object + * NotifyValue - Value from the Notify() request + * + * RETURN: Status + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvQueueNotifyRequest ( + ACPI_NAMESPACE_NODE *Node, + UINT32 NotifyValue) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj = NULL; + ACPI_GENERIC_STATE *NotifyInfo; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_NAME (EvQueueNotifyRequest); + + + /* + * For value 0x03 (Ejection Request), may need to run a device method. + * For value 0x02 (Device Wake), if _PRW exists, may need to run + * the _PS0 method. + * For value 0x80 (Status Change) on the power button or sleep button, + * initiate soft-off or sleep operation. + * + * For all cases, simply dispatch the notify to the handler. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), + NotifyValue, AcpiUtGetNotifyName (NotifyValue), Node)); + + /* Get the notify object attached to the NS Node */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + /* We have the notify object, Get the correct handler */ + + switch (Node->Type) + { + /* Notify is allowed only on these types */ + + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_PROCESSOR: + + if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) + { + HandlerObj = ObjDesc->CommonNotify.SystemNotify; + } + else + { + HandlerObj = ObjDesc->CommonNotify.DeviceNotify; + } + break; + + default: + + /* All other types are not supported */ + + return (AE_TYPE); + } + } + + /* + * If there is a handler to run, schedule the dispatcher. + * Check for: + * 1) Global system notify handler + * 2) Global device notify handler + * 3) Per-device notify handler + */ + if ((AcpiGbl_SystemNotify.Handler && + (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || + (AcpiGbl_DeviceNotify.Handler && + (NotifyValue > ACPI_MAX_SYS_NOTIFY)) || + HandlerObj) + { + NotifyInfo = AcpiUtCreateGenericState (); + if (!NotifyInfo) + { + return (AE_NO_MEMORY); + } + + if (!HandlerObj) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Executing system notify handler for Notify (%4.4s, %X) " + "node %p\n", + AcpiUtGetNodeName (Node), NotifyValue, Node)); + } + + NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; + NotifyInfo->Notify.Node = Node; + NotifyInfo->Notify.Value = (UINT16) NotifyValue; + NotifyInfo->Notify.HandlerObj = HandlerObj; + + Status = AcpiOsExecute ( + OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo); + if (ACPI_FAILURE (Status)) + { + AcpiUtDeleteGenericState (NotifyInfo); + } + } + else + { + /* There is no notify handler (per-device or system) for this device */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "No notify handler for Notify (%4.4s, %X) node %p\n", + AcpiUtGetNodeName (Node), NotifyValue, Node)); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvNotifyDispatch + * + * PARAMETERS: Context - To be passed to the notify handler + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE +AcpiEvNotifyDispatch ( + void *Context) +{ + ACPI_GENERIC_STATE *NotifyInfo = (ACPI_GENERIC_STATE *) Context; + ACPI_NOTIFY_HANDLER GlobalHandler = NULL; + void *GlobalContext = NULL; + ACPI_OPERAND_OBJECT *HandlerObj; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * We will invoke a global notify handler if installed. This is done + * _before_ we invoke the per-device handler attached to the device. + */ + if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY) + { + /* Global system notification handler */ + + if (AcpiGbl_SystemNotify.Handler) + { + GlobalHandler = AcpiGbl_SystemNotify.Handler; + GlobalContext = AcpiGbl_SystemNotify.Context; + } + } + else + { + /* Global driver notification handler */ + + if (AcpiGbl_DeviceNotify.Handler) + { + GlobalHandler = AcpiGbl_DeviceNotify.Handler; + GlobalContext = AcpiGbl_DeviceNotify.Context; + } + } + + /* Invoke the system handler first, if present */ + + if (GlobalHandler) + { + GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, + GlobalContext); + } + + /* Now invoke the per-device handler, if present */ + + HandlerObj = NotifyInfo->Notify.HandlerObj; + if (HandlerObj) + { + HandlerObj->Notify.Handler (NotifyInfo->Notify.Node, + NotifyInfo->Notify.Value, + HandlerObj->Notify.Context); + } + + /* All done with the info object */ + + AcpiUtDeleteGenericState (NotifyInfo); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * FUNCTION: AcpiEvTerminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Disable events and free memory allocated for table storage. + * + ******************************************************************************/ + +void +AcpiEvTerminate ( + void) +{ + UINT32 i; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvTerminate); + + + if (AcpiGbl_EventsInitialized) + { + /* + * Disable all event-related functionality. In all cases, on error, + * print a message but obviously we don't abort. + */ + + /* Disable all fixed events */ + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + Status = AcpiDisableEvent (i, 0); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not disable fixed event %u", (UINT32) i)); + } + } + + /* Disable all GPEs in all GPE blocks */ + + Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); + + /* Remove SCI handler */ + + Status = AcpiEvRemoveSciHandler (); + if (ACPI_FAILURE(Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not remove SCI handler")); + } + + Status = AcpiEvRemoveGlobalLockHandler (); + if (ACPI_FAILURE(Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not remove Global Lock handler")); + } + } + + /* Deallocate all handler objects installed within GPE info structs */ + + Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL); + + /* Return to original mode if necessary */ + + if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY) + { + Status = AcpiDisable (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "AcpiDisable failed")); + } + } + return_VOID; +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evregion.c b/source/components/events/evregion.c new file mode 100644 index 000000000000..8c1a8ebbae12 --- /dev/null +++ b/source/components/events/evregion.c @@ -0,0 +1,1366 @@ +/****************************************************************************** + * + * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EVREGION_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evregion") + + +/* Local prototypes */ + +static BOOLEAN +AcpiEvHasDefaultHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId); + +static void +AcpiEvOrphanEcRegMethod ( + void); + +static ACPI_STATUS +AcpiEvRegRun ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiEvInstallHandler ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +/* These are the address spaces that will get default handlers */ + +#define ACPI_NUM_DEFAULT_SPACES 4 + +static UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = +{ + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallRegionHandlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem default address space handlers. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInstallRegionHandlers ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent and + * registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is + * currently no device associated with the address space. For these we + * use the root. + * + * We install the default PCI config space handler at the root so that + * this space is immediately available even though the we have not + * enumerated all the PCI Root Buses yet. This is to conform to the ACPI + * specification which states that the PCI config space must be always + * available -- even though we are nowhere near ready to find the PCI root + * buses at this point. + * + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via AcpiInstallAddressSpaceHandler). + * Similar for AE_SAME_HANDLER. + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) + { + Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, + AcpiGbl_DefaultAddressSpaces[i], + ACPI_DEFAULT_HANDLER, NULL, NULL); + switch (Status) + { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + Status = AE_OK; + break; + + default: + + goto UnlockAndExit; + } + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvHasDefaultHandler + * + * PARAMETERS: Node - Namespace node for the device + * SpaceId - The address space ID + * + * RETURN: TRUE if default handler is installed, FALSE otherwise + * + * DESCRIPTION: Check if the default handler is installed for the requested + * space ID. + * + ******************************************************************************/ + +static BOOLEAN +AcpiEvHasDefaultHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + + + /* Must have an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + HandlerObj = ObjDesc->Device.Handler; + + /* Walk the linked list of handlers for this object */ + + while (HandlerObj) + { + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + if (HandlerObj->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + { + return (TRUE); + } + } + + HandlerObj = HandlerObj->AddressSpace.Next; + } + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInitializeOpRegions + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG methods for all Operation Regions that have + * an installed default region handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitializeOpRegions ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (EvInitializeOpRegions); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Run the _REG methods for OpRegions in each default address space */ + + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) + { + /* + * Make sure the installed handler is the DEFAULT handler. If not the + * default, the _REG methods will have already been run (when the + * handler was installed) + */ + if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, + AcpiGbl_DefaultAddressSpaces[i])) + { + Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, + AcpiGbl_DefaultAddressSpaces[i]); + } + } + + AcpiGbl_RegMethodsExecuted = TRUE; + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvExecuteRegMethod + * + * PARAMETERS: RegionObj - Region object + * Function - Passed to _REG: On (1) or Off (0) + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG method for a region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvExecuteRegMethod ( + ACPI_OPERAND_OBJECT *RegionObj, + UINT32 Function) +{ + ACPI_EVALUATE_INFO *Info; + ACPI_OPERAND_OBJECT *Args[3]; + ACPI_OPERAND_OBJECT *RegionObj2; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvExecuteRegMethod); + + + RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); + if (!RegionObj2) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + if (RegionObj2->Extra.Method_REG == NULL) + { + return_ACPI_STATUS (AE_OK); + } + + /* Allocate and initialize the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->PrefixNode = RegionObj2->Extra.Method_REG; + Info->Pathname = NULL; + Info->Parameters = Args; + Info->Flags = ACPI_IGNORE_RETURN_VALUE; + + /* + * The _REG method has two arguments: + * + * Arg0 - Integer: + * Operation region space ID Same value as RegionObj->Region.SpaceId + * + * Arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) + */ + Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); + if (!Args[0]) + { + Status = AE_NO_MEMORY; + goto Cleanup1; + } + + Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); + if (!Args[1]) + { + Status = AE_NO_MEMORY; + goto Cleanup2; + } + + Args[2] = NULL; /* Terminate list */ + + /* Execute the method, no return value */ + + ACPI_DEBUG_EXEC ( + AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); + + Status = AcpiNsEvaluate (Info); + AcpiUtRemoveReference (Args[1]); + +Cleanup2: + AcpiUtRemoveReference (Args[0]); + +Cleanup1: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAddressSpaceDispatch + * + * PARAMETERS: RegionObj - Internal region object + * FieldObj - Corresponding field. Can be NULL. + * Function - Read or Write operation + * RegionOffset - Where in the region to read or write + * BitWidth - Field width in bits (8, 16, 32, or 64) + * Value - Pointer to in or out value, must be + * a full 64-bit integer + * + * RETURN: Status + * + * DESCRIPTION: Dispatch an address space or operation region access to + * a previously installed handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvAddressSpaceDispatch ( + ACPI_OPERAND_OBJECT *RegionObj, + ACPI_OPERAND_OBJECT *FieldObj, + UINT32 Function, + UINT32 RegionOffset, + UINT32 BitWidth, + UINT64 *Value) +{ + ACPI_STATUS Status; + ACPI_ADR_SPACE_HANDLER Handler; + ACPI_ADR_SPACE_SETUP RegionSetup; + ACPI_OPERAND_OBJECT *HandlerDesc; + ACPI_OPERAND_OBJECT *RegionObj2; + void *RegionContext = NULL; + ACPI_CONNECTION_INFO *Context; + + + ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); + + + RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); + if (!RegionObj2) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Ensure that there is a handler associated with this region */ + + HandlerDesc = RegionObj->Region.Handler; + if (!HandlerDesc) + { + ACPI_ERROR ((AE_INFO, + "No handler for Region [%4.4s] (%p) [%s]", + AcpiUtGetNodeName (RegionObj->Region.Node), + RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + + return_ACPI_STATUS (AE_NOT_EXIST); + } + + Context = HandlerDesc->AddressSpace.Context; + + /* + * It may be the case that the region has never been initialized. + * Some types of regions require special init code + */ + if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) + { + /* This region has not been initialized yet, do it */ + + RegionSetup = HandlerDesc->AddressSpace.Setup; + if (!RegionSetup) + { + /* No initialization routine, exit with error */ + + ACPI_ERROR ((AE_INFO, + "No init routine for region(%p) [%s]", + RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* + * We must exit the interpreter because the region setup will + * potentially execute control methods (for example, the _REG method + * for this region) + */ + AcpiExExitInterpreter (); + + Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, + Context, &RegionContext); + + /* Re-enter the interpreter */ + + AcpiExEnterInterpreter (); + + /* Check for failure of the Region Setup */ + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "During region initialization: [%s]", + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + return_ACPI_STATUS (Status); + } + + /* Region initialization may have been completed by RegionSetup */ + + if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) + { + RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; + + if (RegionObj2->Extra.RegionContext) + { + /* The handler for this region was already installed */ + + ACPI_FREE (RegionContext); + } + else + { + /* + * Save the returned context for use in all accesses to + * this particular region + */ + RegionObj2->Extra.RegionContext = RegionContext; + } + } + } + + /* We have everything we need, we can invoke the address space handler */ + + Handler = HandlerDesc->AddressSpace.Handler; + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + &RegionObj->Region.Handler->AddressSpace, Handler, + ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + + + /* + * Special handling for GenericSerialBus and GeneralPurposeIo: + * There are three extra parameters that must be passed to the + * handler via the context: + * 1) Connection buffer, a resource template from Connection() op. + * 2) Length of the above buffer. + * 3) Actual access length from the AccessAs() op. + */ + if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) || + (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) && + Context && + FieldObj) + { + /* Get the Connection (ResourceTemplate) buffer */ + + Context->Connection = FieldObj->Field.ResourceBuffer; + Context->Length = FieldObj->Field.ResourceLength; + Context->AccessLength = FieldObj->Field.AccessLength; + } + + if (!(HandlerDesc->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) + { + /* + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. + */ + AcpiExExitInterpreter(); + } + + /* Call the handler */ + + Status = Handler (Function, + (RegionObj->Region.Address + RegionOffset), BitWidth, Value, + Context, RegionObj2->Extra.RegionContext); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + } + + if (!(HandlerDesc->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) + { + /* + * We just returned from a non-default handler, we must re-enter the + * interpreter + */ + AcpiExEnterInterpreter (); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDetachRegion + * + * PARAMETERS: RegionObj - Region Object + * AcpiNsIsLocked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Break the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +void +AcpiEvDetachRegion( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsIsLocked) +{ + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT **LastObjPtr; + ACPI_ADR_SPACE_SETUP RegionSetup; + void **RegionContext; + ACPI_OPERAND_OBJECT *RegionObj2; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvDetachRegion); + + + RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); + if (!RegionObj2) + { + return_VOID; + } + RegionContext = &RegionObj2->Extra.RegionContext; + + /* Get the address handler from the region object */ + + HandlerObj = RegionObj->Region.Handler; + if (!HandlerObj) + { + /* This region has no handler, all done */ + + return_VOID; + } + + /* Find this region in the handler's list */ + + ObjDesc = HandlerObj->AddressSpace.RegionList; + LastObjPtr = &HandlerObj->AddressSpace.RegionList; + + while (ObjDesc) + { + /* Is this the correct Region? */ + + if (ObjDesc == RegionObj) + { + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Removing Region %p from address handler %p\n", + RegionObj, HandlerObj)); + + /* This is it, remove it from the handler's list */ + + *LastObjPtr = ObjDesc->Region.Next; + ObjDesc->Region.Next = NULL; /* Must clear field */ + + if (AcpiNsIsLocked) + { + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + } + + /* Now stop region accesses by executing the _REG method */ + + Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + } + + if (AcpiNsIsLocked) + { + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + } + + /* + * If the region has been activated, call the setup handler with + * the deactivate notification + */ + if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) + { + RegionSetup = HandlerObj->AddressSpace.Setup; + Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, + HandlerObj->AddressSpace.Context, RegionContext); + + /* Init routine may fail, Just ignore errors */ + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "from region handler - deactivate, [%s]", + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + } + + RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); + } + + /* + * Remove handler reference in the region + * + * NOTE: this doesn't mean that the region goes away, the region + * is just inaccessible as indicated to the _REG method + * + * If the region is on the handler's list, this must be the + * region's handler + */ + RegionObj->Region.Handler = NULL; + AcpiUtRemoveReference (HandlerObj); + + return_VOID; + } + + /* Walk the linked list of handlers */ + + LastObjPtr = &ObjDesc->Region.Next; + ObjDesc = ObjDesc->Region.Next; + } + + /* If we get here, the region was not in the handler's region list */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Cannot remove region %p from address handler %p\n", + RegionObj, HandlerObj)); + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAttachRegion + * + * PARAMETERS: HandlerObj - Handler Object + * RegionObj - Region Object + * AcpiNsIsLocked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Create the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvAttachRegion ( + ACPI_OPERAND_OBJECT *HandlerObj, + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsIsLocked) +{ + + ACPI_FUNCTION_TRACE (EvAttachRegion); + + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Adding Region [%4.4s] %p to address handler %p [%s]\n", + AcpiUtGetNodeName (RegionObj->Region.Node), + RegionObj, HandlerObj, + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + + /* Link this region to the front of the handler's list */ + + RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; + HandlerObj->AddressSpace.RegionList = RegionObj; + + /* Install the region's handler */ + + if (RegionObj->Region.Handler) + { + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + RegionObj->Region.Handler = HandlerObj; + AcpiUtAddReference (HandlerObj); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallHandler + * + * PARAMETERS: WalkNamespace callback + * + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region or Device. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvInstallHandler ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *NextHandlerObj; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (EvInstallHandler); + + + HandlerObj = (ACPI_OPERAND_OBJECT *) Context; + + /* Parameter validation */ + + if (!HandlerObj) + { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions and objects that are allowed to have + * address space handlers + */ + if ((Node->Type != ACPI_TYPE_DEVICE) && + (Node->Type != ACPI_TYPE_REGION) && + (Node != AcpiGbl_RootNode)) + { + return (AE_OK); + } + + /* Check for an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + /* No object, just exit */ + + return (AE_OK); + } + + /* Devices are handled different than regions */ + + if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) + { + /* Check if this Device already has a handler for this address space */ + + NextHandlerObj = ObjDesc->Device.Handler; + while (NextHandlerObj) + { + /* Found a handler, is it for the same address space? */ + + if (NextHandlerObj->AddressSpace.SpaceId == + HandlerObj->AddressSpace.SpaceId) + { + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", + AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), + ObjDesc, NextHandlerObj, HandlerObj)); + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* Walk the linked list of handlers attached to this device */ + + NextHandlerObj = NextHandlerObj->AddressSpace.Next; + } + + /* + * As long as the device didn't have a handler for this space we + * don't care about it. We just ignore it and proceed. + */ + return (AE_OK); + } + + /* Object is a Region */ + + if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) + { + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address space type. + * + * First disconnect region for any previous handler (if any) + */ + AcpiEvDetachRegion (ObjDesc, FALSE); + + /* Connect the region to the new handler */ + + Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallSpaceHandler + * + * PARAMETERS: Node - Namespace node for the device + * SpaceId - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. + * Assumes namespace is locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInstallSpaceHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_STATUS Status; + ACPI_OBJECT_TYPE Type; + UINT8 Flags = 0; + + + ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); + + + /* + * This registration is valid for only the types below and the root. This + * is where the default handlers get placed. + */ + if ((Node->Type != ACPI_TYPE_DEVICE) && + (Node->Type != ACPI_TYPE_PROCESSOR) && + (Node->Type != ACPI_TYPE_THERMAL) && + (Node != AcpiGbl_RootNode)) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + if (Handler == ACPI_DEFAULT_HANDLER) + { + Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (SpaceId) + { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + Handler = AcpiExSystemMemorySpaceHandler; + Setup = AcpiEvSystemMemoryRegionSetup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + Handler = AcpiExSystemIoSpaceHandler; + Setup = AcpiEvIoSpaceRegionSetup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + Handler = AcpiExPciConfigSpaceHandler; + Setup = AcpiEvPciConfigRegionSetup; + break; + + case ACPI_ADR_SPACE_CMOS: + Handler = AcpiExCmosSpaceHandler; + Setup = AcpiEvCmosRegionSetup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + Handler = AcpiExPciBarSpaceHandler; + Setup = AcpiEvPciBarRegionSetup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + Handler = AcpiExDataTableSpaceHandler; + Setup = NULL; + break; + + default: + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!Setup) + { + Setup = AcpiEvDefaultRegionSetup; + } + + /* Check for an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + /* + * The attached device object already exists. Make sure the handler + * is not already installed. + */ + HandlerObj = ObjDesc->Device.Handler; + + /* Walk the handler list for this device */ + + while (HandlerObj) + { + /* Same SpaceId indicates a handler already installed */ + + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + if (HandlerObj->AddressSpace.Handler == Handler) + { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with the + * PCI_Config space. + */ + Status = AE_SAME_HANDLER; + goto UnlockAndExit; + } + else + { + /* A handler is already installed */ + + Status = AE_ALREADY_EXISTS; + } + goto UnlockAndExit; + } + + /* Walk the linked list of handlers */ + + HandlerObj = HandlerObj->AddressSpace.Next; + } + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", Node)); + + /* ObjDesc does not exist, create one */ + + if (Node->Type == ACPI_TYPE_ANY) + { + Type = ACPI_TYPE_DEVICE; + } + else + { + Type = Node->Type; + } + + ObjDesc = AcpiUtCreateInternalObject (Type); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* Init new descriptor */ + + ObjDesc->Common.Type = (UINT8) Type; + + /* Attach the new object to the Node */ + + Status = AcpiNsAttachObject (Node, ObjDesc, Type); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + AcpiUtGetRegionName (SpaceId), SpaceId, + AcpiUtGetNodeName (Node), Node, ObjDesc)); + + /* + * Install the handler + * + * At this point there is no existing handler. Just allocate the object + * for the handler and link it into the list. + */ + HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!HandlerObj) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* Init handler obj */ + + HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; + HandlerObj->AddressSpace.HandlerFlags = Flags; + HandlerObj->AddressSpace.RegionList = NULL; + HandlerObj->AddressSpace.Node = Node; + HandlerObj->AddressSpace.Handler = Handler; + HandlerObj->AddressSpace.Context = Context; + HandlerObj->AddressSpace.Setup = Setup; + + /* Install at head of Device.AddressSpace list */ + + HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; + + /* + * The Device object is the first reference on the HandlerObj. + * Each region that uses the handler adds a reference. + */ + ObjDesc->Device.Handler = HandlerObj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, + HandlerObj, NULL); + +UnlockAndExit: + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvExecuteRegMethods + * + * PARAMETERS: Node - Namespace node for the device + * SpaceId - The address space ID + * + * RETURN: Status + * + * DESCRIPTION: Run all _REG methods for the input Space ID; + * Note: assumes namespace is locked, or system init time. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvExecuteRegMethods ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvExecuteRegMethods); + + + /* + * Run all _REG methods for all Operation Regions for this space ID. This + * is a separate walk in order to handle any interdependencies between + * regions and _REG methods. (i.e. handlers must be installed for all + * regions of this Space ID before we can run any _REG methods) + */ + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, + &SpaceId, NULL); + + /* Special case for EC: handle "orphan" _REG methods with no region */ + + if (SpaceId == ACPI_ADR_SPACE_EC) + { + AcpiEvOrphanEcRegMethod (); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvRegRun + * + * PARAMETERS: WalkNamespace callback + * + * DESCRIPTION: Run _REG method for region objects of the requested spaceID + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvRegRun ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_ADR_SPACE_TYPE SpaceId; + ACPI_STATUS Status; + + + SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions.and objects that are allowed to have address + * space handlers + */ + if ((Node->Type != ACPI_TYPE_REGION) && + (Node != AcpiGbl_RootNode)) + { + return (AE_OK); + } + + /* Check for an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + /* No object, just exit */ + + return (AE_OK); + } + + /* Object is a Region */ + + if (ObjDesc->Region.SpaceId != SpaceId) + { + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvOrphanEcRegMethod + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC + * device. This is a _REG method that has no corresponding region + * within the EC device scope. The orphan _REG method appears to + * have been enabled by the description of the ECDT in the ACPI + * specification: "The availability of the region space can be + * detected by providing a _REG method object underneath the + * Embedded Controller device." + * + * To quickly access the EC device, we use the EC_ID that appears + * within the ECDT. Otherwise, we would need to perform a time- + * consuming namespace walk, executing _HID methods to find the + * EC device. + * + ******************************************************************************/ + +static void +AcpiEvOrphanEcRegMethod ( + void) +{ + ACPI_TABLE_ECDT *Table; + ACPI_STATUS Status; + ACPI_OBJECT_LIST Args; + ACPI_OBJECT Objects[2]; + ACPI_NAMESPACE_NODE *EcDeviceNode; + ACPI_NAMESPACE_NODE *RegMethod; + ACPI_NAMESPACE_NODE *NextNode; + + + ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); + + + /* Get the ECDT (if present in system) */ + + Status = AcpiGetTable (ACPI_SIG_ECDT, 0, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table)); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* We need a valid EC_ID string */ + + if (!(*Table->Id)) + { + return_VOID; + } + + /* Namespace is currently locked, must release */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + /* Get a handle to the EC device referenced in the ECDT */ + + Status = AcpiGetHandle (NULL, + ACPI_CAST_PTR (char, Table->Id), + ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode)); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Get a handle to a _REG method immediately under the EC device */ + + Status = AcpiGetHandle (EcDeviceNode, + METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod)); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* + * Execute the _REG method only if there is no Operation Region in + * this scope with the Embedded Controller space ID. Otherwise, it + * will already have been executed. Note, this allows for Regions + * with other space IDs to be present; but the code below will then + * execute the _REG method with the EC space ID argument. + */ + NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); + while (NextNode) + { + if ((NextNode->Type == ACPI_TYPE_REGION) && + (NextNode->Object) && + (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) + { + goto Exit; /* Do not execute _REG */ + } + NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); + } + + /* Evaluate the _REG(EC,Connect) method */ + + Args.Count = 2; + Args.Pointer = Objects; + Objects[0].Type = ACPI_TYPE_INTEGER; + Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; + Objects[1].Type = ACPI_TYPE_INTEGER; + Objects[1].Integer.Value = ACPI_REG_CONNECT; + + Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); + +Exit: + /* We ignore all errors from above, don't care */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + return_VOID; +} diff --git a/source/components/events/evrgnini.c b/source/components/events/evrgnini.c new file mode 100644 index 000000000000..92946b5aaafa --- /dev/null +++ b/source/components/events/evrgnini.c @@ -0,0 +1,732 @@ +/****************************************************************************** + * + * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EVRGNINI_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evrgnini") + +/* Local prototypes */ + +static BOOLEAN +AcpiEvIsPciRootBridge ( + ACPI_NAMESPACE_NODE *Node); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvSystemMemoryRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a SystemMemory operation region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvSystemMemoryRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; + ACPI_MEM_SPACE_CONTEXT *LocalRegionContext; + + + ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); + + + if (Function == ACPI_REGION_DEACTIVATE) + { + if (*RegionContext) + { + LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; + + /* Delete a cached mapping if present */ + + if (LocalRegionContext->MappedLength) + { + AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress, + LocalRegionContext->MappedLength); + } + ACPI_FREE (LocalRegionContext); + *RegionContext = NULL; + } + return_ACPI_STATUS (AE_OK); + } + + /* Create a new context */ + + LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT)); + if (!(LocalRegionContext)) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Save the region length and address for use in the handler */ + + LocalRegionContext->Length = RegionDesc->Region.Length; + LocalRegionContext->Address = RegionDesc->Region.Address; + + *RegionContext = LocalRegionContext; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvIoSpaceRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a IO operation region + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvIoSpaceRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup); + + + if (Function == ACPI_REGION_DEACTIVATE) + { + *RegionContext = NULL; + } + else + { + *RegionContext = HandlerContext; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvPciConfigRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a PCI_Config operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvPciConfigRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_STATUS Status = AE_OK; + UINT64 PciValue; + ACPI_PCI_ID *PciId = *RegionContext; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_NAMESPACE_NODE *PciRootNode; + ACPI_NAMESPACE_NODE *PciDeviceNode; + ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; + + + ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); + + + HandlerObj = RegionObj->Region.Handler; + if (!HandlerObj) + { + /* + * No installed handler. This shouldn't happen because the dispatch + * routine checks before we get here, but we check again just in case. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Attempting to init a region %p, with no handler\n", RegionObj)); + return_ACPI_STATUS (AE_NOT_EXIST); + } + + *RegionContext = NULL; + if (Function == ACPI_REGION_DEACTIVATE) + { + if (PciId) + { + ACPI_FREE (PciId); + } + return_ACPI_STATUS (Status); + } + + ParentNode = RegionObj->Region.Node->Parent; + + /* + * Get the _SEG and _BBN values from the device upon which the handler + * is installed. + * + * We need to get the _SEG and _BBN objects relative to the PCI BUS device. + * This is the device the handler has been registered to handle. + */ + + /* + * If the AddressSpace.Node is still pointing to the root, we need + * to scan upward for a PCI Root bridge and re-associate the OpRegion + * handlers with that device. + */ + if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) + { + /* Start search from the parent object */ + + PciRootNode = ParentNode; + while (PciRootNode != AcpiGbl_RootNode) + { + /* Get the _HID/_CID in order to detect a RootBridge */ + + if (AcpiEvIsPciRootBridge (PciRootNode)) + { + /* Install a handler for this PCI root bridge */ + + Status = AcpiInstallAddressSpaceHandler ( + (ACPI_HANDLE) PciRootNode, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_SAME_HANDLER) + { + /* + * It is OK if the handler is already installed on the + * root bridge. Still need to return a context object + * for the new PCI_Config operation region, however. + */ + Status = AE_OK; + } + else + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not install PciConfig handler " + "for Root Bridge %4.4s", + AcpiUtGetNodeName (PciRootNode))); + } + } + break; + } + + PciRootNode = PciRootNode->Parent; + } + + /* PCI root bridge not found, use namespace root node */ + } + else + { + PciRootNode = HandlerObj->AddressSpace.Node; + } + + /* + * If this region is now initialized, we are done. + * (InstallAddressSpaceHandler could have initialized it) + */ + if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) + { + return_ACPI_STATUS (AE_OK); + } + + /* Region is still not initialized. Create a new context */ + + PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); + if (!PciId) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * For PCI_Config space access, we need the segment, bus, device and + * function numbers. Acquire them here. + * + * Find the parent device object. (This allows the operation region to be + * within a subscope under the device, such as a control method.) + */ + PciDeviceNode = RegionObj->Region.Node; + while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) + { + PciDeviceNode = PciDeviceNode->Parent; + } + + if (!PciDeviceNode) + { + ACPI_FREE (PciId); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * Get the PCI device and function numbers from the _ADR object + * contained in the parent's scope. + */ + Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, + PciDeviceNode, &PciValue); + + /* + * The default is zero, and since the allocation above zeroed the data, + * just do nothing on failure. + */ + if (ACPI_SUCCESS (Status)) + { + PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); + PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); + } + + /* The PCI segment number comes from the _SEG method */ + + Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, + PciRootNode, &PciValue); + if (ACPI_SUCCESS (Status)) + { + PciId->Segment = ACPI_LOWORD (PciValue); + } + + /* The PCI bus number comes from the _BBN method */ + + Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, + PciRootNode, &PciValue); + if (ACPI_SUCCESS (Status)) + { + PciId->Bus = ACPI_LOWORD (PciValue); + } + + /* Complete/update the PCI ID for this device */ + + Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (PciId); + return_ACPI_STATUS (Status); + } + + *RegionContext = PciId; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvIsPciRootBridge + * + * PARAMETERS: Node - Device node being examined + * + * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by + * examining the _HID and _CID for the device. + * + ******************************************************************************/ + +static BOOLEAN +AcpiEvIsPciRootBridge ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_STATUS Status; + ACPI_DEVICE_ID *Hid; + ACPI_DEVICE_ID_LIST *Cid; + UINT32 i; + BOOLEAN Match; + + + /* Get the _HID and check for a PCI Root Bridge */ + + Status = AcpiUtExecute_HID (Node, &Hid); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + + Match = AcpiUtIsPciRootBridge (Hid->String); + ACPI_FREE (Hid); + + if (Match) + { + return (TRUE); + } + + /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ + + Status = AcpiUtExecute_CID (Node, &Cid); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + + /* Check all _CIDs in the returned list */ + + for (i = 0; i < Cid->Count; i++) + { + if (AcpiUtIsPciRootBridge (Cid->Ids[i].String)) + { + ACPI_FREE (Cid); + return (TRUE); + } + } + + ACPI_FREE (Cid); + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvPciBarRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a PciBAR operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvPciBarRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_FUNCTION_TRACE (EvPciBarRegionSetup); + + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvCmosRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a CMOS operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvCmosRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_FUNCTION_TRACE (EvCmosRegionSetup); + + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDefaultRegionSetup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * HandlerContext - Address space handler context + * RegionContext - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Default region initialization + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDefaultRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_FUNCTION_TRACE (EvDefaultRegionSetup); + + + if (Function == ACPI_REGION_DEACTIVATE) + { + *RegionContext = NULL; + } + else + { + *RegionContext = HandlerContext; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInitializeRegion + * + * PARAMETERS: RegionObj - Region we are initializing + * AcpiNsLocked - Is namespace locked? + * + * RETURN: Status + * + * DESCRIPTION: Initializes the region, finds any _REG methods and saves them + * for execution at a later time + * + * Get the appropriate address space handler for a newly + * created region. + * + * This also performs address space specific initialization. For + * example, PCI regions must have an _ADR object that contains + * a PCI address in the scope of the definition. This address is + * required to perform an access to PCI config space. + * + * MUTEX: Interpreter should be unlocked, because we may run the _REG + * method for this region. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitializeRegion ( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsLocked) +{ + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_ADR_SPACE_TYPE SpaceId; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *MethodNode; + ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; + ACPI_OPERAND_OBJECT *RegionObj2; + + + ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); + + + if (!RegionObj) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) + { + return_ACPI_STATUS (AE_OK); + } + + RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); + if (!RegionObj2) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + Node = RegionObj->Region.Node->Parent; + SpaceId = RegionObj->Region.SpaceId; + + /* Setup defaults */ + + RegionObj->Region.Handler = NULL; + RegionObj2->Extra.Method_REG = NULL; + RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE); + RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; + + /* Find any "_REG" method associated with this region definition */ + + Status = AcpiNsSearchOneScope ( + *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); + if (ACPI_SUCCESS (Status)) + { + /* + * The _REG method is optional and there can be only one per region + * definition. This will be executed when the handler is attached + * or removed + */ + RegionObj2->Extra.Method_REG = MethodNode; + } + + /* + * The following loop depends upon the root Node having no parent + * ie: AcpiGbl_RootNode->ParentEntry being set to NULL + */ + while (Node) + { + /* Check to see if a handler exists */ + + HandlerObj = NULL; + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + /* Can only be a handler if the object exists */ + + switch (Node->Type) + { + case ACPI_TYPE_DEVICE: + + HandlerObj = ObjDesc->Device.Handler; + break; + + case ACPI_TYPE_PROCESSOR: + + HandlerObj = ObjDesc->Processor.Handler; + break; + + case ACPI_TYPE_THERMAL: + + HandlerObj = ObjDesc->ThermalZone.Handler; + break; + + case ACPI_TYPE_METHOD: + /* + * If we are executing module level code, the original + * Node's object was replaced by this Method object and we + * saved the handler in the method object. + * + * See AcpiNsExecModuleCode + */ + if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) + { + HandlerObj = ObjDesc->Method.Dispatch.Handler; + } + break; + + default: + /* Ignore other objects */ + break; + } + + while (HandlerObj) + { + /* Is this handler of the correct type? */ + + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + /* Found correct handler */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Found handler %p for region %p in obj %p\n", + HandlerObj, RegionObj, ObjDesc)); + + Status = AcpiEvAttachRegion (HandlerObj, RegionObj, + AcpiNsLocked); + + /* + * Tell all users that this region is usable by + * running the _REG method + */ + if (AcpiNsLocked) + { + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); + + if (AcpiNsLocked) + { + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + return_ACPI_STATUS (AE_OK); + } + + /* Try next handler in the list */ + + HandlerObj = HandlerObj->AddressSpace.Next; + } + } + + /* This node does not have the handler we need; Pop up one level */ + + Node = Node->Parent; + } + + /* If we get here, there is no handler for this region */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "No handler for RegionType %s(%X) (RegionObj %p)\n", + AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); + + return_ACPI_STATUS (AE_NOT_EXIST); +} + diff --git a/source/components/events/evsci.c b/source/components/events/evsci.c new file mode 100644 index 000000000000..c47cccc8db15 --- /dev/null +++ b/source/components/events/evsci.c @@ -0,0 +1,209 @@ +/******************************************************************************* + * + * Module Name: evsci - System Control Interrupt configuration and + * legacy to ACPI mode state transition functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evsci") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static UINT32 ACPI_SYSTEM_XFACE +AcpiEvSciXruptHandler ( + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvSciXruptHandler + * + * PARAMETERS: Context - Calling Context + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Interrupt handler that will figure out what function or + * control method to call to deal with a SCI. + * + ******************************************************************************/ + +static UINT32 ACPI_SYSTEM_XFACE +AcpiEvSciXruptHandler ( + void *Context) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptList = Context; + UINT32 InterruptHandled = ACPI_INTERRUPT_NOT_HANDLED; + + + ACPI_FUNCTION_TRACE (EvSciXruptHandler); + + + /* + * We are guaranteed by the ACPI CA initialization/shutdown code that + * if this interrupt handler is installed, ACPI is enabled. + */ + + /* + * Fixed Events: + * Check for and dispatch any Fixed Events that have occurred + */ + InterruptHandled |= AcpiEvFixedEventDetect (); + + /* + * General Purpose Events: + * Check for and dispatch any GPEs that have occurred + */ + InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); + + AcpiSciCount++; + return_UINT32 (InterruptHandled); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGpeXruptHandler + * + * PARAMETERS: Context - Calling Context + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Handler for GPE Block Device interrupts + * + ******************************************************************************/ + +UINT32 ACPI_SYSTEM_XFACE +AcpiEvGpeXruptHandler ( + void *Context) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptList = Context; + UINT32 InterruptHandled = ACPI_INTERRUPT_NOT_HANDLED; + + + ACPI_FUNCTION_TRACE (EvGpeXruptHandler); + + + /* + * We are guaranteed by the ACPI CA initialization/shutdown code that + * if this interrupt handler is installed, ACPI is enabled. + */ + + /* GPEs: Check for and dispatch any GPEs that have occurred */ + + InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); + + return_UINT32 (InterruptHandled); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiEvInstallSciHandler + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Installs SCI handler. + * + ******************************************************************************/ + +UINT32 +AcpiEvInstallSciHandler ( + void) +{ + UINT32 Status = AE_OK; + + + ACPI_FUNCTION_TRACE (EvInstallSciHandler); + + + Status = AcpiOsInstallInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, + AcpiEvSciXruptHandler, AcpiGbl_GpeXruptListHead); + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiEvRemoveSciHandler + * + * PARAMETERS: none + * + * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * installed to begin with + * + * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be + * taken. + * + * Note: It doesn't seem important to disable all events or set the event + * enable registers to their original values. The OS should disable + * the SCI interrupt level when the handler is removed, so no more + * events will come in. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvRemoveSciHandler ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvRemoveSciHandler); + + + /* Just let the OS remove the handler and disable the level */ + + Status = AcpiOsRemoveInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, + AcpiEvSciXruptHandler); + + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evxface.c b/source/components/events/evxface.c new file mode 100644 index 000000000000..cc558f7d449f --- /dev/null +++ b/source/components/events/evxface.c @@ -0,0 +1,979 @@ +/****************************************************************************** + * + * Module Name: evxface - External interfaces for ACPI events + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EVXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxface") + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallNotifyHandler + * + * PARAMETERS: Device - The device for which notifies will be handled + * HandlerType - The type of handler: + * ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) + * ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) + * ACPI_ALL_NOTIFY: both system and device + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler, + void *Context) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *NotifyObj; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); + + + /* Parameter validation */ + + if ((!Device) || + (!Handler) || + (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (Device); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* + * Root Object: + * Registering a notify handler on the root object indicates that the + * caller wishes to receive notifications for all objects. Note that + * only one global handler can be regsitered (per notify type). + */ + if (Device == ACPI_ROOT_OBJECT) + { + /* Make sure the handler is not already installed */ + + if (((HandlerType & ACPI_SYSTEM_NOTIFY) && + AcpiGbl_SystemNotify.Handler) || + ((HandlerType & ACPI_DEVICE_NOTIFY) && + AcpiGbl_DeviceNotify.Handler)) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + + if (HandlerType & ACPI_SYSTEM_NOTIFY) + { + AcpiGbl_SystemNotify.Node = Node; + AcpiGbl_SystemNotify.Handler = Handler; + AcpiGbl_SystemNotify.Context = Context; + } + + if (HandlerType & ACPI_DEVICE_NOTIFY) + { + AcpiGbl_DeviceNotify.Node = Node; + AcpiGbl_DeviceNotify.Handler = Handler; + AcpiGbl_DeviceNotify.Context = Context; + } + + /* Global notify handler installed */ + } + + /* + * All Other Objects: + * Caller will only receive notifications specific to the target object. + * Note that only certain object types can receive notifications. + */ + else + { + /* Notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + /* Check for an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + /* Object exists - make sure there's no handler */ + + if (((HandlerType & ACPI_SYSTEM_NOTIFY) && + ObjDesc->CommonNotify.SystemNotify) || + ((HandlerType & ACPI_DEVICE_NOTIFY) && + ObjDesc->CommonNotify.DeviceNotify)) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + } + else + { + /* Create a new object */ + + ObjDesc = AcpiUtCreateInternalObject (Node->Type); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* Attach new object to the Node */ + + Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + } + + /* Install the handler */ + + NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); + if (!NotifyObj) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + NotifyObj->Notify.Node = Node; + NotifyObj->Notify.Handler = Handler; + NotifyObj->Notify.Context = Context; + + if (HandlerType & ACPI_SYSTEM_NOTIFY) + { + ObjDesc->CommonNotify.SystemNotify = NotifyObj; + } + + if (HandlerType & ACPI_DEVICE_NOTIFY) + { + ObjDesc->CommonNotify.DeviceNotify = NotifyObj; + } + + if (HandlerType == ACPI_ALL_NOTIFY) + { + /* Extra ref if installed in both */ + + AcpiUtAddReference (NotifyObj); + } + } + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveNotifyHandler + * + * PARAMETERS: Device - The device for which notifies will be handled + * HandlerType - The type of handler: + * ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) + * ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) + * ACPI_ALL_NOTIFY: both system and device + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler) +{ + ACPI_OPERAND_OBJECT *NotifyObj; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); + + + /* Parameter validation */ + + if ((!Device) || + (!Handler) || + (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (Device); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Root Object */ + + if (Device == ACPI_ROOT_OBJECT) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Removing notify handler for namespace root object\n")); + + if (((HandlerType & ACPI_SYSTEM_NOTIFY) && + !AcpiGbl_SystemNotify.Handler) || + ((HandlerType & ACPI_DEVICE_NOTIFY) && + !AcpiGbl_DeviceNotify.Handler)) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + if (HandlerType & ACPI_SYSTEM_NOTIFY) + { + AcpiGbl_SystemNotify.Node = NULL; + AcpiGbl_SystemNotify.Handler = NULL; + AcpiGbl_SystemNotify.Context = NULL; + } + + if (HandlerType & ACPI_DEVICE_NOTIFY) + { + AcpiGbl_DeviceNotify.Node = NULL; + AcpiGbl_DeviceNotify.Handler = NULL; + AcpiGbl_DeviceNotify.Context = NULL; + } + } + + /* All Other Objects */ + + else + { + /* Notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + /* Check for an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + /* Object exists - make sure there's an existing handler */ + + if (HandlerType & ACPI_SYSTEM_NOTIFY) + { + NotifyObj = ObjDesc->CommonNotify.SystemNotify; + if (!NotifyObj) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + if (NotifyObj->Notify.Handler != Handler) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Remove the handler */ + + ObjDesc->CommonNotify.SystemNotify = NULL; + AcpiUtRemoveReference (NotifyObj); + } + + if (HandlerType & ACPI_DEVICE_NOTIFY) + { + NotifyObj = ObjDesc->CommonNotify.DeviceNotify; + if (!NotifyObj) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + if (NotifyObj->Notify.Handler != Handler) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Remove the handler */ + + ObjDesc->CommonNotify.DeviceNotify = NULL; + AcpiUtRemoveReference (NotifyObj); + } + } + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallExceptionHandler + * + * PARAMETERS: Handler - Pointer to the handler function for the + * event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallExceptionHandler ( + ACPI_EXCEPTION_HANDLER Handler) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (AcpiGbl_ExceptionHandler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + /* Install the handler */ + + AcpiGbl_ExceptionHandler = Handler; + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiInstallGlobalEventHandler + * + * PARAMETERS: Handler - Pointer to the global event handler function + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function. The global handler + * is invoked upon each incoming GPE and Fixed Event. It is + * invoked at interrupt level at the time of the event dispatch. + * Can be used to update event counters, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallGlobalEventHandler ( + ACPI_GBL_EVENT_HANDLER Handler, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); + + + /* Parameter validation */ + + if (!Handler) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (AcpiGbl_GlobalEventHandler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + AcpiGbl_GlobalEventHandler = Handler; + AcpiGbl_GlobalEventHandlerContext = Context; + + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallFixedEventHandler + * + * PARAMETERS: Event - Event type to enable. + * Handler - Pointer to the handler function for the + * event + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallFixedEventHandler ( + UINT32 Event, + ACPI_EVENT_HANDLER Handler, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); + + + /* Parameter validation */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + /* Install the handler before enabling the event */ + + AcpiGbl_FixedEventHandlers[Event].Handler = Handler; + AcpiGbl_FixedEventHandlers[Event].Context = Context; + + Status = AcpiEnableEvent (Event, 0); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); + + /* Remove the handler */ + + AcpiGbl_FixedEventHandlers[Event].Handler = NULL; + AcpiGbl_FixedEventHandlers[Event].Context = NULL; + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Enabled fixed event %X, Handler=%p\n", Event, Handler)); + } + + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveFixedEventHandler + * + * PARAMETERS: Event - Event type to disable. + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveFixedEventHandler ( + UINT32 Event, + ACPI_EVENT_HANDLER Handler) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); + + + /* Parameter validation */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Disable the event before removing the handler */ + + Status = AcpiDisableEvent (Event, 0); + + /* Always Remove the handler */ + + AcpiGbl_FixedEventHandlers[Event].Handler = NULL; + AcpiGbl_FixedEventHandlers[Event].Context = NULL; + + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, + "Could not write to fixed event enable register 0x%X", Event)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallGpeHandler + * + * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * GpeNumber - The GPE number within the GPE block + * Type - Whether this GPE should be treated as an + * edge- or level-triggered interrupt. + * Address - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a General Purpose Event. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT32 Type, + ACPI_GPE_HANDLER Address, + void *Context) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_GPE_HANDLER_INFO *Handler; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); + + + /* Parameter validation */ + + if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Allocate and init handler object (before lock) */ + + Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); + if (!Handler) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto FreeAndExit; + } + + /* Make sure that there isn't a handler there already */ + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) + { + Status = AE_ALREADY_EXISTS; + goto FreeAndExit; + } + + Handler->Address = Address; + Handler->Context = Context; + Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; + Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & + (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); + + /* + * If the GPE is associated with a method, it may have been enabled + * automatically during initialization, in which case it has to be + * disabled now to avoid spurious execution of the handler. + */ + if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) || + (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) && + GpeEventInfo->RuntimeCount) + { + Handler->OriginallyEnabled = TRUE; + (void) AcpiEvRemoveGpeReference (GpeEventInfo); + + /* Sanity check of original type against new type */ + + if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) + { + ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)")); + } + } + + /* Install the handler */ + + GpeEventInfo->Dispatch.Handler = Handler; + + /* Setup up dispatch flags to indicate handler (vs. method/notify) */ + + GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); + GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); + +FreeAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + ACPI_FREE (Handler); + goto UnlockAndExit; +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveGpeHandler + * + * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * GpeNumber - The event to remove a handler + * Address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + ACPI_GPE_HANDLER Address) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_GPE_HANDLER_INFO *Handler; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); + + + /* Parameter validation */ + + if (!Address) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Make sure that a handler is indeed installed */ + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != + ACPI_GPE_DISPATCH_HANDLER) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + /* Make sure that the installed handler is the same */ + + if (GpeEventInfo->Dispatch.Handler->Address != Address) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Remove the handler */ + + Handler = GpeEventInfo->Dispatch.Handler; + + /* Restore Method node (if any), set dispatch flags */ + + GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; + GpeEventInfo->Flags &= + ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); + GpeEventInfo->Flags |= Handler->OriginalFlags; + + /* + * If the GPE was previously associated with a method and it was + * enabled, it should be enabled at this point to restore the + * post-initialization configuration. + */ + if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) && + Handler->OriginallyEnabled) + { + (void) AcpiEvAddGpeReference (GpeEventInfo); + } + + /* Now we can free the handler object */ + + ACPI_FREE (Handler); + + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiAcquireGlobalLock + * + * PARAMETERS: Timeout - How long the caller is willing to wait + * Handle - Where the handle to the lock is returned + * (if acquired) + * + * RETURN: Status + * + * DESCRIPTION: Acquire the ACPI Global Lock + * + * Note: Allows callers with the same thread ID to acquire the global lock + * multiple times. In other words, externally, the behavior of the global lock + * is identical to an AML mutex. On the first acquire, a new handle is + * returned. On any subsequent calls to acquire by the same thread, the same + * handle is returned. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiAcquireGlobalLock ( + UINT16 Timeout, + UINT32 *Handle) +{ + ACPI_STATUS Status; + + + if (!Handle) + { + return (AE_BAD_PARAMETER); + } + + /* Must lock interpreter to prevent race conditions */ + + AcpiExEnterInterpreter (); + + Status = AcpiExAcquireMutexObject (Timeout, + AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); + + if (ACPI_SUCCESS (Status)) + { + /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ + + *Handle = AcpiGbl_GlobalLockHandle; + } + + AcpiExExitInterpreter (); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) + + +/******************************************************************************* + * + * FUNCTION: AcpiReleaseGlobalLock + * + * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock + * + * RETURN: Status + * + * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReleaseGlobalLock ( + UINT32 Handle) +{ + ACPI_STATUS Status; + + + if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) + { + return (AE_NOT_ACQUIRED); + } + + Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evxfevnt.c b/source/components/events/evxfevnt.c new file mode 100644 index 000000000000..254214af1927 --- /dev/null +++ b/source/components/events/evxfevnt.c @@ -0,0 +1,381 @@ +/****************************************************************************** + * + * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EVXFEVNT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxfevnt") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/******************************************************************************* + * + * FUNCTION: AcpiEnable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Transfers the system into ACPI mode. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnable ( + void) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiEnable); + + + /* ACPI tables must be present */ + + if (!AcpiTbTablesLoaded ()) + { + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } + + /* Check current mode */ + + if (AcpiHwGetMode() == ACPI_SYS_MODE_ACPI) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n")); + } + else + { + /* Transition to ACPI mode */ + + Status = AcpiHwSetMode (ACPI_SYS_MODE_ACPI); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not transition to ACPI mode")); + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "Transition to ACPI mode successful\n")); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnable) + + +/******************************************************************************* + * + * FUNCTION: AcpiDisable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDisable ( + void) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiDisable); + + + if (AcpiHwGetMode() == ACPI_SYS_MODE_LEGACY) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "System is already in legacy (non-ACPI) mode\n")); + } + else + { + /* Transition to LEGACY mode */ + + Status = AcpiHwSetMode (ACPI_SYS_MODE_LEGACY); + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not exit ACPI mode to legacy mode")); + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n")); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiDisable) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnableEvent + * + * PARAMETERS: Event - The fixed eventto be enabled + * Flags - Reserved + * + * RETURN: Status + * + * DESCRIPTION: Enable an ACPI event (fixed) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableEvent ( + UINT32 Event, + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + UINT32 Value; + + + ACPI_FUNCTION_TRACE (AcpiEnableEvent); + + + /* Decode the Fixed Event */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Enable the requested fixed event (by writing a one to the enable + * register bit) + */ + Status = AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, + ACPI_ENABLE_EVENT); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Make sure that the hardware responded */ + + Status = AcpiReadBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Value != 1) + { + ACPI_ERROR ((AE_INFO, + "Could not enable %s event", AcpiUtGetEventName (Event))); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableEvent) + + +/******************************************************************************* + * + * FUNCTION: AcpiDisableEvent + * + * PARAMETERS: Event - The fixed event to be disabled + * Flags - Reserved + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (fixed) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDisableEvent ( + UINT32 Event, + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + UINT32 Value; + + + ACPI_FUNCTION_TRACE (AcpiDisableEvent); + + + /* Decode the Fixed Event */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Disable the requested fixed event (by writing a zero to the enable + * register bit) + */ + Status = AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, + ACPI_DISABLE_EVENT); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiReadBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Value != 0) + { + ACPI_ERROR ((AE_INFO, + "Could not disable %s events", AcpiUtGetEventName (Event))); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiDisableEvent) + + +/******************************************************************************* + * + * FUNCTION: AcpiClearEvent + * + * PARAMETERS: Event - The fixed event to be cleared + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (fixed) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiClearEvent ( + UINT32 Event) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiClearEvent); + + + /* Decode the Fixed Event */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Clear the requested fixed event (By writing a one to the status + * register bit) + */ + Status = AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].StatusRegisterId, + ACPI_CLEAR_STATUS); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiClearEvent) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetEventStatus + * + * PARAMETERS: Event - The fixed event + * EventStatus - Where the current status of the event will + * be returned + * + * RETURN: Status + * + * DESCRIPTION: Obtains and returns the current status of the event + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetEventStatus ( + UINT32 Event, + ACPI_EVENT_STATUS *EventStatus) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiGetEventStatus); + + + if (!EventStatus) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Decode the Fixed Event */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the status of the requested fixed event */ + + Status = AcpiReadBitRegister ( + AcpiGbl_FixedEventInfo[Event].StatusRegisterId, EventStatus); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evxfgpe.c b/source/components/events/evxfgpe.c new file mode 100644 index 000000000000..c0dd88c77752 --- /dev/null +++ b/source/components/events/evxfgpe.c @@ -0,0 +1,903 @@ +/****************************************************************************** + * + * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EVXFGPE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxfgpe") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/******************************************************************************* + * + * FUNCTION: AcpiUpdateAllGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Complete GPE initialization and enable all GPEs that have + * associated _Lxx or _Exx methods and are not pointed to by any + * device _PRW methods (this indicates that these GPEs are + * generally intended for system or device wakeup. Such GPEs + * have to be enabled directly when the devices whose _PRW + * methods point to them are set up for wakeup signaling.) + * + * NOTE: Should be called after any GPEs are added to the system. Primarily, + * after the system _PRW methods have been run, but also after a GPE Block + * Device has been added or if any new GPE methods have been added via a + * dynamic table load. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUpdateAllGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiUpdateGpes); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (AcpiGbl_AllGpesInitialized) + { + goto UnlockAndExit; + } + + Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL); + if (ACPI_SUCCESS (Status)) + { + AcpiGbl_AllGpesInitialized = TRUE; + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnableGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is + * hardware-enabled. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiEnableGpe); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (GpeEventInfo) + { + Status = AcpiEvAddGpeReference (GpeEventInfo); + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiDisableGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Remove a reference to a GPE. When the last reference is + * removed, only then is the GPE disabled (for runtime GPEs), or + * the GPE mask bit disabled (for wake GPEs) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDisableGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiDisableGpe); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (GpeEventInfo) + { + Status = AcpiEvRemoveGpeReference (GpeEventInfo); + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiDisableGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiSetGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE + * + * RETURN: Status + * + * DESCRIPTION: Enable or disable an individual GPE. This function bypasses + * the reference count mechanism used in the AcpiEnableGpe and + * AcpiDisableGpe interfaces -- and should be used with care. + * + * Note: Typically used to disable a runtime GPE for short period of time, + * then re-enable it, without disturbing the existing reference counts. This + * is useful, for example, in the Embedded Controller (EC) driver. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT8 Action) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiSetGpe); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Perform the action */ + + switch (Action) + { + case ACPI_GPE_ENABLE: + Status = AcpiEvEnableGpe (GpeEventInfo); + break; + + case ACPI_GPE_DISABLE: + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + break; + + default: + Status = AE_BAD_PARAMETER; + break; + } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiSetGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiSetupGpeForWake + * + * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) + * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Mark a GPE as having the ability to wake the system. This + * interface is intended to be used as the host executes the + * _PRW methods (Power Resources for Wake) in the system tables. + * Each _PRW appears under a Device Object (The WakeDevice), and + * contains the info for the wake GPE associated with the + * WakeDevice. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetupGpeForWake ( + ACPI_HANDLE WakeDevice, + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_NAMESPACE_NODE *DeviceNode; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); + + + /* Parameter Validation */ + + if (!WakeDevice) + { + /* + * By forcing WakeDevice to be valid, we automatically enable the + * implicit notify feature on all hosts. + */ + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Handle root object case */ + + if (WakeDevice == ACPI_ROOT_OBJECT) + { + DeviceNode = AcpiGbl_RootNode; + } + else + { + DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); + } + + /* Validate WakeDevice is of type Device */ + + if (DeviceNode->Type != ACPI_TYPE_DEVICE) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (GpeEventInfo) + { + /* + * If there is no method or handler for this GPE, then the + * WakeDevice will be notified whenever this GPE fires (aka + * "implicit notify") Note: The GPE is assumed to be + * level-triggered (for windows compatibility). + */ + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) + { + GpeEventInfo->Flags = + (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); + GpeEventInfo->Dispatch.DeviceNode = DeviceNode; + } + + GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; + Status = AE_OK; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) + + +/******************************************************************************* + * + * FUNCTION: AcpiSetGpeWakeMask + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * Action - Enable or Disable + * + * RETURN: Status + * + * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must + * already be marked as a WAKE GPE. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetGpeWakeMask ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT8 Action) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_CPU_FLAGS Flags; + UINT32 RegisterBit; + + + ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* + * Ensure that we have a valid GPE number and that this GPE is in + * fact a wake GPE + */ + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + if (!GpeRegisterInfo) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); + + /* Perform the action */ + + switch (Action) + { + case ACPI_GPE_ENABLE: + ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); + break; + + case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); + break; + + default: + ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); + Status = AE_BAD_PARAMETER; + break; + } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) + + +/******************************************************************************* + * + * FUNCTION: AcpiClearGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiClearGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiClearGpe); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiHwClearGpe (GpeEventInfo); + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiClearGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetGpeStatus + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * EventStatus - Where the current status of the event + * will be returned + * + * RETURN: Status + * + * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetGpeStatus ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + ACPI_EVENT_STATUS *EventStatus) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Obtain status on the requested GPE number */ + + Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) + + +/******************************************************************************* + * + * FUNCTION: AcpiFinishGpe + * + * PARAMETERS: GpeDevice - Namespace node for the GPE Block + * (NULL for FADT defined GPEs) + * GpeNumber - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE + * processing. Intended for use by asynchronous host-installed + * GPE handlers. The GPE is only reenabled if the EnableForRun bit + * is set in the GPE info. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiFinishGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiFinishGpe); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiEvFinishGpe (GpeEventInfo); + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiFinishGpe) + + +/****************************************************************************** + * + * FUNCTION: AcpiDisableAllGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Disable and clear all GPEs in all GPE blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDisableAllGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwDisableAllGpes (); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) + + +/****************************************************************************** + * + * FUNCTION: AcpiEnableAllRuntimeGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableAllRuntimeGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwEnableAllRuntimeGpes (); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallGpeBlock + * + * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device + * GpeBlockAddress - Address and SpaceID + * RegisterCount - Number of GPE register pairs in the block + * InterruptNumber - H/W interrupt for the block + * + * RETURN: Status + * + * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not + * enabled here. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallGpeBlock ( + ACPI_HANDLE GpeDevice, + ACPI_GENERIC_ADDRESS *GpeBlockAddress, + UINT32 RegisterCount, + UINT32 InterruptNumber) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_GPE_BLOCK_INFO *GpeBlock; + + + ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); + + + if ((!GpeDevice) || + (!GpeBlockAddress) || + (!RegisterCount)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Node = AcpiNsValidateHandle (GpeDevice); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* + * For user-installed GPE Block Devices, the GpeBlockBaseNumber + * is always zero + */ + Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, + 0, InterruptNumber, &GpeBlock); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* Install block in the DeviceObject attached to the node */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + /* + * No object, create a new one (Device nodes do not always have + * an attached object) + */ + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + } + + /* Now install the GPE block in the DeviceObject */ + + ObjDesc->Device.GpeBlock = GpeBlock; + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveGpeBlock + * + * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device + * + * RETURN: Status + * + * DESCRIPTION: Remove a previously installed block of GPE registers + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveGpeBlock ( + ACPI_HANDLE GpeDevice) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); + + + if (!GpeDevice) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Node = AcpiNsValidateHandle (GpeDevice); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Get the DeviceObject attached to the node */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc || + !ObjDesc->Device.GpeBlock) + { + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Delete the GPE block (but not the DeviceObject) */ + + Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); + if (ACPI_SUCCESS (Status)) + { + ObjDesc->Device.GpeBlock = NULL; + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetGpeDevice + * + * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) + * GpeDevice - Where the parent GPE Device is returned + * + * RETURN: Status + * + * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL + * gpe device indicates that the gpe number is contained in one of + * the FADT-defined gpe blocks. Otherwise, the GPE block device. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetGpeDevice ( + UINT32 Index, + ACPI_HANDLE *GpeDevice) +{ + ACPI_GPE_DEVICE_INFO Info; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); + + + if (!GpeDevice) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (Index >= AcpiCurrentGpeCount) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Setup and walk the GPE list */ + + Info.Index = Index; + Info.Status = AE_NOT_EXIST; + Info.GpeDevice = NULL; + Info.NextBlockBaseIndex = 0; + + Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); + return_ACPI_STATUS (Info.Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evxfregn.c b/source/components/events/evxfregn.c new file mode 100644 index 000000000000..493df9217de1 --- /dev/null +++ b/source/components/events/evxfregn.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and + * Address Spaces. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EVXFREGN_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxfregn") + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallAddressSpaceHandler + * + * PARAMETERS: Device - Handle for the device + * SpaceId - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. + * + * NOTE: This function should only be called after AcpiEnableSubsystem has + * been called. This is because any _REG methods associated with the Space ID + * are executed here, and these methods can only be safely executed after + * the default handlers have been installed and the hardware has been + * initialized (via AcpiEnableSubsystem.) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler); + + + /* Parameter validation */ + + if (!Device) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (Device); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Install the handler for all Regions for this Space ID */ + + Status = AcpiEvInstallSpaceHandler (Node, SpaceId, Handler, Setup, Context); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* + * For the default SpaceIDs, (the IDs for which there are default region handlers + * installed) Only execute the _REG methods if the global initialization _REG + * methods have already been run (via AcpiInitializeObjects). In other words, + * we will defer the execution of the _REG methods for these SpaceIDs until + * execution of AcpiInitializeObjects. This is done because we need the handlers + * for the default spaces (mem/io/pci/table) to be installed before we can run + * any control methods (or _REG methods). There is known BIOS code that depends + * on this. + * + * For all other SpaceIDs, we can safely execute the _REG methods immediately. + * This means that for IDs like EmbeddedController, this function should be called + * only after AcpiEnableSubsystem has been called. + */ + switch (SpaceId) + { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + case ACPI_ADR_SPACE_SYSTEM_IO: + case ACPI_ADR_SPACE_PCI_CONFIG: + case ACPI_ADR_SPACE_DATA_TABLE: + + if (!AcpiGbl_RegMethodsExecuted) + { + /* We will defer execution of the _REG methods for this space */ + goto UnlockAndExit; + } + break; + + default: + break; + } + + /* Run all _REG methods for this address space */ + + Status = AcpiEvExecuteRegMethods (Node, SpaceId); + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveAddressSpaceHandler + * + * PARAMETERS: Device - Handle for the device + * SpaceId - The address space ID + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a previously installed handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *RegionObj; + ACPI_OPERAND_OBJECT **LastObjPtr; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler); + + + /* Parameter validation */ + + if (!Device) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Convert and validate the device handle */ + + Node = AcpiNsValidateHandle (Device); + if (!Node || + ((Node->Type != ACPI_TYPE_DEVICE) && + (Node->Type != ACPI_TYPE_PROCESSOR) && + (Node->Type != ACPI_TYPE_THERMAL) && + (Node != AcpiGbl_RootNode))) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Make sure the internal object exists */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + /* Find the address handler the user requested */ + + HandlerObj = ObjDesc->Device.Handler; + LastObjPtr = &ObjDesc->Device.Handler; + while (HandlerObj) + { + /* We have a handler, see if user requested this one */ + + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + /* Handler must be the same as the installed handler */ + + if (HandlerObj->AddressSpace.Handler != Handler) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Matched SpaceId, first dereference this in the Regions */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Removing address handler %p(%p) for region %s " + "on Device %p(%p)\n", + HandlerObj, Handler, AcpiUtGetRegionName (SpaceId), + Node, ObjDesc)); + + RegionObj = HandlerObj->AddressSpace.RegionList; + + /* Walk the handler's region list */ + + while (RegionObj) + { + /* + * First disassociate the handler from the region. + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + */ + AcpiEvDetachRegion (RegionObj, TRUE); + + /* + * Walk the list: Just grab the head because the + * DetachRegion removed the previous head. + */ + RegionObj = HandlerObj->AddressSpace.RegionList; + + } + + /* Remove this Handler object from the list */ + + *LastObjPtr = HandlerObj->AddressSpace.Next; + + /* Now we can delete the handler object */ + + AcpiUtRemoveReference (HandlerObj); + goto UnlockAndExit; + } + + /* Walk the linked list of handlers */ + + LastObjPtr = &HandlerObj->AddressSpace.Next; + HandlerObj = HandlerObj->AddressSpace.Next; + } + + /* The handler does not exist */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", + Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc)); + + Status = AE_NOT_EXIST; + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler) + diff --git a/source/components/executer/exconfig.c b/source/components/executer/exconfig.c new file mode 100644 index 000000000000..9e05497b9f56 --- /dev/null +++ b/source/components/executer/exconfig.c @@ -0,0 +1,688 @@ +/****************************************************************************** + * + * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXCONFIG_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acdispat.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exconfig") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExAddTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_OPERAND_OBJECT **DdbHandle); + +static ACPI_STATUS +AcpiExRegionRead ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Length, + UINT8 *Buffer); + + +/******************************************************************************* + * + * FUNCTION: AcpiExAddTable + * + * PARAMETERS: Table - Pointer to raw table + * ParentNode - Where to load the table (scope) + * DdbHandle - Where to return the table handle. + * + * RETURN: Status + * + * DESCRIPTION: Common function to Install and Load an ACPI table with a + * returned table handle. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExAddTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_OPERAND_OBJECT **DdbHandle) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_OWNER_ID OwnerId; + + + ACPI_FUNCTION_TRACE (ExAddTable); + + + /* Create an object to be the table handle */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Init the table handle */ + + ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; + ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; + *DdbHandle = ObjDesc; + + /* Install the new table into the local data structures */ + + ObjDesc->Reference.Value = TableIndex; + + /* Add the table to the namespace */ + + Status = AcpiNsLoadTable (TableIndex, ParentNode); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ObjDesc); + *DdbHandle = NULL; + return_ACPI_STATUS (Status); + } + + /* Execute any module-level code that was found in the table */ + + AcpiExExitInterpreter (); + AcpiNsExecModuleCodeList (); + AcpiExEnterInterpreter (); + + /* + * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is + * responsible for discovering any new wake GPEs by running _PRW methods + * that may have been loaded by this table. + */ + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_SUCCESS (Status)) + { + AcpiEvUpdateGpes (OwnerId); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExLoadTableOp + * + * PARAMETERS: WalkState - Current state with operands + * ReturnDesc - Where to store the return object + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from the RSDT/XSDT + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExLoadTableOp ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **ReturnDesc) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_NAMESPACE_NODE *StartNode; + ACPI_NAMESPACE_NODE *ParameterNode = NULL; + ACPI_OPERAND_OBJECT *DdbHandle; + ACPI_TABLE_HEADER *Table; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (ExLoadTableOp); + + + /* Validate lengths for the SignatureString, OEMIDString, OEMTableID */ + + if ((Operand[0]->String.Length > ACPI_NAME_SIZE) || + (Operand[1]->String.Length > ACPI_OEM_ID_SIZE) || + (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Find the ACPI table in the RSDT/XSDT */ + + Status = AcpiTbFindTable (Operand[0]->String.Pointer, + Operand[1]->String.Pointer, + Operand[2]->String.Pointer, &TableIndex); + if (ACPI_FAILURE (Status)) + { + if (Status != AE_NOT_FOUND) + { + return_ACPI_STATUS (Status); + } + + /* Table not found, return an Integer=0 and AE_OK */ + + DdbHandle = AcpiUtCreateIntegerObject ((UINT64) 0); + if (!DdbHandle) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + *ReturnDesc = DdbHandle; + return_ACPI_STATUS (AE_OK); + } + + /* Default nodes */ + + StartNode = WalkState->ScopeInfo->Scope.Node; + ParentNode = AcpiGbl_RootNode; + + /* RootPath (optional parameter) */ + + if (Operand[3]->String.Length > 0) + { + /* + * Find the node referenced by the RootPathString. This is the + * location within the namespace where the table will be loaded. + */ + Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer, + ACPI_NS_SEARCH_PARENT, &ParentNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* ParameterPath (optional parameter) */ + + if (Operand[4]->String.Length > 0) + { + if ((Operand[4]->String.Pointer[0] != '\\') && + (Operand[4]->String.Pointer[0] != '^')) + { + /* + * Path is not absolute, so it will be relative to the node + * referenced by the RootPathString (or the NS root if omitted) + */ + StartNode = ParentNode; + } + + /* Find the node referenced by the ParameterPathString */ + + Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer, + ACPI_NS_SEARCH_PARENT, &ParameterNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Load the table into the namespace */ + + Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Parameter Data (optional) */ + + if (ParameterNode) + { + /* Store the parameter data into the optional parameter object */ + + Status = AcpiExStore (Operand[5], + ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), + WalkState); + if (ACPI_FAILURE (Status)) + { + (void) AcpiExUnloadTable (DdbHandle); + + AcpiUtRemoveReference (DdbHandle); + return_ACPI_STATUS (Status); + } + } + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_SUCCESS (Status)) + { + ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); + AcpiTbPrintTableHeader (0, Table); + } + + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, + AcpiGbl_TableHandlerContext); + } + + *ReturnDesc = DdbHandle; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExRegionRead + * + * PARAMETERS: ObjDesc - Region descriptor + * Length - Number of bytes to read + * Buffer - Pointer to where to put the data + * + * RETURN: Status + * + * DESCRIPTION: Read data from an operation region. The read starts from the + * beginning of the region. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExRegionRead ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Length, + UINT8 *Buffer) +{ + ACPI_STATUS Status; + UINT64 Value; + UINT32 RegionOffset = 0; + UINT32 i; + + + /* Bytewise reads */ + + for (i = 0; i < Length; i++) + { + Status = AcpiEvAddressSpaceDispatch (ObjDesc, NULL, ACPI_READ, + RegionOffset, 8, &Value); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *Buffer = (UINT8) Value; + Buffer++; + RegionOffset++; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExLoadOp + * + * PARAMETERS: ObjDesc - Region or Buffer/Field where the table will be + * obtained + * Target - Where a handle to the table will be stored + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a field or operation region + * + * NOTE: Region Fields (Field, BankField, IndexFields) are resolved to buffer + * objects before this code is reached. + * + * If source is an operation region, it must refer to SystemMemory, as + * per the ACPI specification. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExLoadOp ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *Target, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *DdbHandle; + ACPI_TABLE_HEADER *Table; + ACPI_TABLE_DESC TableDesc; + UINT32 TableIndex; + ACPI_STATUS Status; + UINT32 Length; + + + ACPI_FUNCTION_TRACE (ExLoadOp); + + + ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC)); + + /* Source Object can be either an OpRegion or a Buffer/Field */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Load table from Region %p\n", ObjDesc)); + + /* Region must be SystemMemory (from ACPI spec) */ + + if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetRegionArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Get the table header first so we can get the table length */ + + Table = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); + if (!Table) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), + ACPI_CAST_PTR (UINT8, Table)); + Length = Table->Length; + ACPI_FREE (Table); + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Must have at least an ACPI table header */ + + if (Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + + /* + * The original implementation simply mapped the table, with no copy. + * However, the memory region is not guaranteed to remain stable and + * we must copy the table to a local buffer. For example, the memory + * region is corrupted after suspend on some machines. Dynamically + * loaded tables are usually small, so this overhead is minimal. + * + * The latest implementation (5/2009) does not use a mapping at all. + * We use the low-level operation region interface to read the table + * instead of the obvious optimization of using a direct mapping. + * This maintains a consistent use of operation regions across the + * entire subsystem. This is important if additional processing must + * be performed in the (possibly user-installed) operation region + * handler. For example, AcpiExec and ASLTS depend on this. + */ + + /* Allocate a buffer for the table */ + + TableDesc.Pointer = ACPI_ALLOCATE (Length); + if (!TableDesc.Pointer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Read the entire table */ + + Status = AcpiExRegionRead (ObjDesc, Length, + ACPI_CAST_PTR (UINT8, TableDesc.Pointer)); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (TableDesc.Pointer); + return_ACPI_STATUS (Status); + } + + TableDesc.Address = ObjDesc->Region.Address; + break; + + + case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */ + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Load table from Buffer or Field %p\n", ObjDesc)); + + /* Must have at least an ACPI table header */ + + if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + + /* Get the actual table length from the table header */ + + Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); + Length = Table->Length; + + /* Table cannot extend beyond the buffer */ + + if (Length > ObjDesc->Buffer.Length) + { + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + if (Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + + /* + * Copy the table from the buffer because the buffer could be modified + * or even deleted in the future + */ + TableDesc.Pointer = ACPI_ALLOCATE (Length); + if (!TableDesc.Pointer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ACPI_MEMCPY (TableDesc.Pointer, Table, Length); + TableDesc.Address = ACPI_TO_INTEGER (TableDesc.Pointer); + break; + + + default: + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Validate table checksum (will not get validated in TbAddTable) */ + + Status = AcpiTbVerifyChecksum (TableDesc.Pointer, Length); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (TableDesc.Pointer); + return_ACPI_STATUS (Status); + } + + /* Complete the table descriptor */ + + TableDesc.Length = Length; + TableDesc.Flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + /* Install the new table into the local data structures */ + + Status = AcpiTbAddTable (&TableDesc, &TableIndex); + if (ACPI_FAILURE (Status)) + { + /* Delete allocated table buffer */ + + AcpiTbDeleteTable (&TableDesc); + return_ACPI_STATUS (Status); + } + + /* + * Add the table to the namespace. + * + * Note: Load the table objects relative to the root of the namespace. + * This appears to go against the ACPI specification, but we do it for + * compatibility with other ACPI implementations. + */ + Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle); + if (ACPI_FAILURE (Status)) + { + /* On error, TablePtr was deallocated above */ + + return_ACPI_STATUS (Status); + } + + /* Store the DdbHandle into the Target operand */ + + Status = AcpiExStore (DdbHandle, Target, WalkState); + if (ACPI_FAILURE (Status)) + { + (void) AcpiExUnloadTable (DdbHandle); + + /* TablePtr was deallocated above */ + + AcpiUtRemoveReference (DdbHandle); + return_ACPI_STATUS (Status); + } + + ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); + AcpiTbPrintTableHeader (0, TableDesc.Pointer); + + /* Remove the reference by added by AcpiExStore above */ + + AcpiUtRemoveReference (DdbHandle); + + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, TableDesc.Pointer, + AcpiGbl_TableHandlerContext); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExUnloadTable + * + * PARAMETERS: DdbHandle - Handle to a previously loaded table + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExUnloadTable ( + ACPI_OPERAND_OBJECT *DdbHandle) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *TableDesc = DdbHandle; + UINT32 TableIndex; + ACPI_TABLE_HEADER *Table; + + + ACPI_FUNCTION_TRACE (ExUnloadTable); + + + /* + * Validate the handle + * Although the handle is partially validated in AcpiExReconfiguration() + * when it calls AcpiExResolveOperands(), the handle is more completely + * validated here. + * + * Handle must be a valid operand object of type reference. Also, the + * DdbHandle must still be marked valid (table has not been previously + * unloaded) + */ + if ((!DdbHandle) || + (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) || + (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) || + (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID))) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the table index from the DdbHandle */ + + TableIndex = TableDesc->Reference.Value; + + /* Ensure the table is still loaded */ + + if (!AcpiTbIsTableLoaded (TableIndex)) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_SUCCESS (Status)) + { + (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, + AcpiGbl_TableHandlerContext); + } + } + + /* Delete the portion of the namespace owned by this table */ + + Status = AcpiTbDeleteNamespaceByOwner (TableIndex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + (void) AcpiTbReleaseOwnerId (TableIndex); + AcpiTbSetTableLoadedFlag (TableIndex, FALSE); + + /* + * Invalidate the handle. We do this because the handle may be stored + * in a named object and may not be actually deleted until much later. + */ + DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; + return_ACPI_STATUS (AE_OK); +} + diff --git a/source/components/executer/exconvrt.c b/source/components/executer/exconvrt.c new file mode 100644 index 000000000000..e79cbc96e975 --- /dev/null +++ b/source/components/executer/exconvrt.c @@ -0,0 +1,754 @@ +/****************************************************************************** + * + * Module Name: exconvrt - Object conversion routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EXCONVRT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exconvrt") + +/* Local prototypes */ + +static UINT32 +AcpiExConvertToAscii ( + UINT64 Integer, + UINT16 Base, + UINT8 *String, + UINT8 MaxLength); + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToInteger + * + * PARAMETERS: ObjDesc - Object to be converted. Must be an + * Integer, Buffer, or String + * ResultDesc - Where the new Integer object is returned + * Flags - Used for string conversion + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an integer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExConvertToInteger ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + UINT32 Flags) +{ + ACPI_OPERAND_OBJECT *ReturnDesc; + UINT8 *Pointer; + UINT64 Result; + UINT32 i; + UINT32 Count; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc); + + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* No conversion necessary */ + + *ResultDesc = ObjDesc; + return_ACPI_STATUS (AE_OK); + + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + + /* Note: Takes advantage of common buffer/string fields */ + + Pointer = ObjDesc->Buffer.Pointer; + Count = ObjDesc->Buffer.Length; + break; + + default: + return_ACPI_STATUS (AE_TYPE); + } + + /* + * Convert the buffer/string to an integer. Note that both buffers and + * strings are treated as raw data - we don't convert ascii to hex for + * strings. + * + * There are two terminating conditions for the loop: + * 1) The size of an integer has been reached, or + * 2) The end of the buffer or string has been reached + */ + Result = 0; + + /* String conversion is different than Buffer conversion */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_STRING: + + /* + * Convert string to an integer - for most cases, the string must be + * hexadecimal as per the ACPI specification. The only exception (as + * of ACPI 3.0) is that the ToInteger() operator allows both decimal + * and hexadecimal strings (hex prefixed with "0x"). + */ + Status = AcpiUtStrtoul64 ((char *) Pointer, Flags, &Result); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + break; + + + case ACPI_TYPE_BUFFER: + + /* Check for zero-length buffer */ + + if (!Count) + { + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + + /* Transfer no more than an integer's worth of data */ + + if (Count > AcpiGbl_IntegerByteWidth) + { + Count = AcpiGbl_IntegerByteWidth; + } + + /* + * Convert buffer to an integer - we simply grab enough raw data + * from the buffer to fill an integer + */ + for (i = 0; i < Count; i++) + { + /* + * Get next byte and shift it into the Result. + * Little endian is used, meaning that the first byte of the buffer + * is the LSB of the integer + */ + Result |= (((UINT64) Pointer[i]) << (i * 8)); + } + break; + + + default: + + /* No other types can get here */ + break; + } + + /* Create a new integer */ + + ReturnDesc = AcpiUtCreateIntegerObject (Result); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (Result))); + + /* Save the Result */ + + AcpiExTruncateFor32bitTable (ReturnDesc); + *ResultDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToBuffer + * + * PARAMETERS: ObjDesc - Object to be converted. Must be an + * Integer, Buffer, or String + * ResultDesc - Where the new buffer object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a Buffer + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExConvertToBuffer ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc) +{ + ACPI_OPERAND_OBJECT *ReturnDesc; + UINT8 *NewBuf; + + + ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc); + + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + + /* No conversion necessary */ + + *ResultDesc = ObjDesc; + return_ACPI_STATUS (AE_OK); + + + case ACPI_TYPE_INTEGER: + + /* + * Create a new Buffer object. + * Need enough space for one integer + */ + ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the integer to the buffer, LSB first */ + + NewBuf = ReturnDesc->Buffer.Pointer; + ACPI_MEMCPY (NewBuf, + &ObjDesc->Integer.Value, + AcpiGbl_IntegerByteWidth); + break; + + + case ACPI_TYPE_STRING: + + /* + * Create a new Buffer object + * Size will be the string length + * + * NOTE: Add one to the string length to include the null terminator. + * The ACPI spec is unclear on this subject, but there is existing + * ASL/AML code that depends on the null being transferred to the new + * buffer. + */ + ReturnDesc = AcpiUtCreateBufferObject ( + (ACPI_SIZE) ObjDesc->String.Length + 1); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the string to the buffer */ + + NewBuf = ReturnDesc->Buffer.Pointer; + ACPI_STRNCPY ((char *) NewBuf, (char *) ObjDesc->String.Pointer, + ObjDesc->String.Length); + break; + + + default: + return_ACPI_STATUS (AE_TYPE); + } + + /* Mark buffer initialized */ + + ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID; + *ResultDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToAscii + * + * PARAMETERS: Integer - Value to be converted + * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX + * String - Where the string is returned + * DataWidth - Size of data item to be converted, in bytes + * + * RETURN: Actual string length + * + * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string + * + ******************************************************************************/ + +static UINT32 +AcpiExConvertToAscii ( + UINT64 Integer, + UINT16 Base, + UINT8 *String, + UINT8 DataWidth) +{ + UINT64 Digit; + UINT32 i; + UINT32 j; + UINT32 k = 0; + UINT32 HexLength; + UINT32 DecimalLength; + UINT32 Remainder; + BOOLEAN SupressZeros; + + + ACPI_FUNCTION_ENTRY (); + + + switch (Base) + { + case 10: + + /* Setup max length for the decimal number */ + + switch (DataWidth) + { + case 1: + DecimalLength = ACPI_MAX8_DECIMAL_DIGITS; + break; + + case 4: + DecimalLength = ACPI_MAX32_DECIMAL_DIGITS; + break; + + case 8: + default: + DecimalLength = ACPI_MAX64_DECIMAL_DIGITS; + break; + } + + SupressZeros = TRUE; /* No leading zeros */ + Remainder = 0; + + for (i = DecimalLength; i > 0; i--) + { + /* Divide by nth factor of 10 */ + + Digit = Integer; + for (j = 0; j < i; j++) + { + (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder); + } + + /* Handle leading zeros */ + + if (Remainder != 0) + { + SupressZeros = FALSE; + } + + if (!SupressZeros) + { + String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder); + k++; + } + } + break; + + case 16: + + /* HexLength: 2 ascii hex chars per data byte */ + + HexLength = ACPI_MUL_2 (DataWidth); + for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) + { + /* Get one hex digit, most significant digits first */ + + String[k] = (UINT8) AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j)); + k++; + } + break; + + default: + return (0); + } + + /* + * Since leading zeros are suppressed, we must check for the case where + * the integer equals 0 + * + * Finally, null terminate the string and return the length + */ + if (!k) + { + String [0] = ACPI_ASCII_ZERO; + k = 1; + } + + String [k] = 0; + return ((UINT32) k); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToString + * + * PARAMETERS: ObjDesc - Object to be converted. Must be an + * Integer, Buffer, or String + * ResultDesc - Where the string object is returned + * Type - String flags (base and conversion type) + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a string + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExConvertToString ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + UINT32 Type) +{ + ACPI_OPERAND_OBJECT *ReturnDesc; + UINT8 *NewBuf; + UINT32 i; + UINT32 StringLength = 0; + UINT16 Base = 16; + UINT8 Separator = ','; + + + ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); + + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_STRING: + + /* No conversion necessary */ + + *ResultDesc = ObjDesc; + return_ACPI_STATUS (AE_OK); + + + case ACPI_TYPE_INTEGER: + + switch (Type) + { + case ACPI_EXPLICIT_CONVERT_DECIMAL: + + /* Make room for maximum decimal number */ + + StringLength = ACPI_MAX_DECIMAL_DIGITS; + Base = 10; + break; + + default: + + /* Two hex string characters for each integer byte */ + + StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); + break; + } + + /* + * Create a new String + * Need enough space for one ASCII integer (plus null terminator) + */ + ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + NewBuf = ReturnDesc->Buffer.Pointer; + + /* Convert integer to string */ + + StringLength = AcpiExConvertToAscii (ObjDesc->Integer.Value, Base, + NewBuf, AcpiGbl_IntegerByteWidth); + + /* Null terminate at the correct place */ + + ReturnDesc->String.Length = StringLength; + NewBuf [StringLength] = 0; + break; + + + case ACPI_TYPE_BUFFER: + + /* Setup string length, base, and separator */ + + switch (Type) + { + case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * decimal values separated by commas." + */ + Base = 10; + + /* + * Calculate the final string length. Individual string values + * are variable length (include separator for each) + */ + for (i = 0; i < ObjDesc->Buffer.Length; i++) + { + if (ObjDesc->Buffer.Pointer[i] >= 100) + { + StringLength += 4; + } + else if (ObjDesc->Buffer.Pointer[i] >= 10) + { + StringLength += 3; + } + else + { + StringLength += 2; + } + } + break; + + case ACPI_IMPLICIT_CONVERT_HEX: + /* + * From the ACPI spec: + *"The entire contents of the buffer are converted to a string of + * two-character hexadecimal numbers, each separated by a space." + */ + Separator = ' '; + StringLength = (ObjDesc->Buffer.Length * 3); + break; + + case ACPI_EXPLICIT_CONVERT_HEX: /* Used by ToHexString */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * hexadecimal values separated by commas." + */ + StringLength = (ObjDesc->Buffer.Length * 3); + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Create a new string object and string buffer + * (-1 because of extra separator included in StringLength from above) + * Allow creation of zero-length strings from zero-length buffers. + */ + if (StringLength) + { + StringLength--; + } + + ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + NewBuf = ReturnDesc->Buffer.Pointer; + + /* + * Convert buffer bytes to hex or decimal values + * (separated by commas or spaces) + */ + for (i = 0; i < ObjDesc->Buffer.Length; i++) + { + NewBuf += AcpiExConvertToAscii ( + (UINT64) ObjDesc->Buffer.Pointer[i], Base, + NewBuf, 1); + *NewBuf++ = Separator; /* each separated by a comma or space */ + } + + /* + * Null terminate the string + * (overwrites final comma/space from above) + */ + if (ObjDesc->Buffer.Length) + { + NewBuf--; + } + *NewBuf = 0; + break; + + default: + return_ACPI_STATUS (AE_TYPE); + } + + *ResultDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToTargetType + * + * PARAMETERS: DestinationType - Current type of the destination + * SourceDesc - Source object to be converted. + * ResultDesc - Where the converted object is returned + * WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Implements "implicit conversion" rules for storing an object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExConvertToTargetType ( + ACPI_OBJECT_TYPE DestinationType, + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExConvertToTargetType); + + + /* Default behavior */ + + *ResultDesc = SourceDesc; + + /* + * If required by the target, + * perform implicit conversion on the source before we store it. + */ + switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs)) + { + case ARGI_SIMPLE_TARGET: + case ARGI_FIXED_TARGET: + case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ + + switch (DestinationType) + { + case ACPI_TYPE_LOCAL_REGION_FIELD: + /* + * Named field can always handle conversions + */ + break; + + default: + /* No conversion allowed for these types */ + + if (DestinationType != SourceDesc->Common.Type) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Explicit operator, will store (%s) over existing type (%s)\n", + AcpiUtGetObjectTypeName (SourceDesc), + AcpiUtGetTypeName (DestinationType))); + Status = AE_TYPE; + } + } + break; + + + case ARGI_TARGETREF: + + switch (DestinationType) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * These types require an Integer operand. We can convert + * a Buffer or a String to an Integer if necessary. + */ + Status = AcpiExConvertToInteger (SourceDesc, ResultDesc, + 16); + break; + + + case ACPI_TYPE_STRING: + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + Status = AcpiExConvertToString (SourceDesc, ResultDesc, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + + case ACPI_TYPE_BUFFER: + /* + * The operand must be a Buffer. We can convert an + * Integer or String if necessary + */ + Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc); + break; + + + default: + ACPI_ERROR ((AE_INFO, "Bad destination type during conversion: 0x%X", + DestinationType)); + Status = AE_AML_INTERNAL; + break; + } + break; + + + case ARGI_REFERENCE: + /* + * CreateXxxxField cases - we are storing the field object into the name + */ + break; + + + default: + ACPI_ERROR ((AE_INFO, + "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", + GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs), + WalkState->Opcode, AcpiUtGetTypeName (DestinationType))); + Status = AE_AML_INTERNAL; + } + + /* + * Source-to-Target conversion semantics: + * + * If conversion to the target type cannot be performed, then simply + * overwrite the target with the new object and type. + */ + if (Status == AE_TYPE) + { + Status = AE_OK; + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/excreate.c b/source/components/executer/excreate.c new file mode 100644 index 000000000000..888ff7d7c4ad --- /dev/null +++ b/source/components/executer/excreate.c @@ -0,0 +1,574 @@ +/****************************************************************************** + * + * Module Name: excreate - Named object creation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXCREATE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("excreate") + + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: AcpiExCreateAlias + * + * PARAMETERS: WalkState - Current state, contains operands + * + * RETURN: Status + * + * DESCRIPTION: Create a new named alias + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateAlias ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_NAMESPACE_NODE *TargetNode; + ACPI_NAMESPACE_NODE *AliasNode; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExCreateAlias); + + + /* Get the source/alias operands (both namespace nodes) */ + + AliasNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0]; + TargetNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[1]; + + if ((TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS) || + (TargetNode->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) + { + /* + * Dereference an existing alias so that we don't create a chain + * of aliases. With this code, we guarantee that an alias is + * always exactly one level of indirection away from the + * actual aliased name. + */ + TargetNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, TargetNode->Object); + } + + /* + * For objects that can never change (i.e., the NS node will + * permanently point to the same object), we can simply attach + * the object to the new NS node. For other objects (such as + * Integers, buffers, etc.), we have to point the Alias node + * to the original Node. + */ + switch (TargetNode->Type) + { + + /* For these types, the sub-object can change dynamically via a Store */ + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_BUFFER_FIELD: + + /* + * These types open a new scope, so we need the NS node in order to access + * any children. + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + /* + * The new alias has the type ALIAS and points to the original + * NS node, not the object itself. + */ + AliasNode->Type = ACPI_TYPE_LOCAL_ALIAS; + AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); + break; + + case ACPI_TYPE_METHOD: + + /* + * Control method aliases need to be differentiated + */ + AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS; + AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); + break; + + default: + + /* Attach the original source object to the new Alias Node */ + + /* + * The new alias assumes the type of the target, and it points + * to the same object. The reference count of the object has an + * additional reference to prevent deletion out from under either the + * target node or the alias Node + */ + Status = AcpiNsAttachObject (AliasNode, + AcpiNsGetAttachedObject (TargetNode), TargetNode->Type); + break; + } + + /* Since both operands are Nodes, we don't need to delete them */ + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreateEvent + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new event object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateEvent ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE (ExCreateEvent); + + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_EVENT); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Create the actual OS semaphore, with zero initial units -- meaning + * that the event is created in an unsignalled state + */ + Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, + &ObjDesc->Event.OsSemaphore); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Attach object to the Node */ + + Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) WalkState->Operands[0], + ObjDesc, ACPI_TYPE_EVENT); + +Cleanup: + /* + * Remove local reference to the object (on error, will cause deletion + * of both object and semaphore if present.) + */ + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreateMutex + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + * Mutex (Name[0], SyncLevel[1]) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateMutex ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE_PTR (ExCreateMutex, ACPI_WALK_OPERANDS); + + + /* Create the new mutex object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Create the actual OS Mutex */ + + Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Init object and attach to NS node */ + + ObjDesc->Mutex.SyncLevel = (UINT8) WalkState->Operands[1]->Integer.Value; + ObjDesc->Mutex.Node = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0]; + + Status = AcpiNsAttachObject (ObjDesc->Mutex.Node, ObjDesc, ACPI_TYPE_MUTEX); + + +Cleanup: + /* + * Remove local reference to the object (on error, will cause deletion + * of both object and semaphore if present.) + */ + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreateRegion + * + * PARAMETERS: AmlStart - Pointer to the region declaration AML + * AmlLength - Max length of the declaration AML + * SpaceId - Address space ID for the region + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new operation region object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateRegion ( + UINT8 *AmlStart, + UINT32 AmlLength, + UINT8 SpaceId, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *RegionObj2; + + + ACPI_FUNCTION_TRACE (ExCreateRegion); + + + /* Get the Namespace Node */ + + Node = WalkState->Op->Common.Node; + + /* + * If the region object is already attached to this node, + * just return + */ + if (AcpiNsGetAttachedObject (Node)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Space ID must be one of the predefined IDs, or in the user-defined + * range + */ + if (!AcpiIsValidSpaceId (SpaceId)) + { + /* + * Print an error message, but continue. We don't want to abort + * a table load for this exception. Instead, if the region is + * actually used at runtime, abort the executing method. + */ + ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId)); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n", + AcpiUtGetRegionName (SpaceId), SpaceId)); + + /* Create the region descriptor */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Remember location in AML stream of address & length + * operands since they need to be evaluated at run time. + */ + RegionObj2 = ObjDesc->Common.NextObject; + RegionObj2->Extra.AmlStart = AmlStart; + RegionObj2->Extra.AmlLength = AmlLength; + if (WalkState->ScopeInfo) + { + RegionObj2->Extra.ScopeNode = WalkState->ScopeInfo->Scope.Node; + } + else + { + RegionObj2->Extra.ScopeNode = Node; + } + + /* Init the region from the operands */ + + ObjDesc->Region.SpaceId = SpaceId; + ObjDesc->Region.Address = 0; + ObjDesc->Region.Length = 0; + ObjDesc->Region.Node = Node; + + /* Install the new region object in the parent Node */ + + Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_REGION); + + +Cleanup: + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreateProcessor + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new processor object and populate the fields + * + * Processor (Name[0], CpuID[1], PblockAddr[2], PblockLength[3]) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateProcessor ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExCreateProcessor, WalkState); + + + /* Create the processor object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PROCESSOR); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize the processor object from the operands */ + + ObjDesc->Processor.ProcId = (UINT8) Operand[1]->Integer.Value; + ObjDesc->Processor.Length = (UINT8) Operand[3]->Integer.Value; + ObjDesc->Processor.Address = (ACPI_IO_ADDRESS) Operand[2]->Integer.Value; + + /* Install the processor object in the parent Node */ + + Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], + ObjDesc, ACPI_TYPE_PROCESSOR); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreatePowerResource + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new PowerResource object and populate the fields + * + * PowerResource (Name[0], SystemLevel[1], ResourceOrder[2]) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreatePowerResource ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE_PTR (ExCreatePowerResource, WalkState); + + + /* Create the power resource object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_POWER); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize the power object from the operands */ + + ObjDesc->PowerResource.SystemLevel = (UINT8) Operand[1]->Integer.Value; + ObjDesc->PowerResource.ResourceOrder = (UINT16) Operand[2]->Integer.Value; + + /* Install the power resource object in the parent Node */ + + Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], + ObjDesc, ACPI_TYPE_POWER); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiExCreateMethod + * + * PARAMETERS: AmlStart - First byte of the method's AML + * AmlLength - AML byte count for this method + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new method object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCreateMethod ( + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + UINT8 MethodFlags; + + + ACPI_FUNCTION_TRACE_PTR (ExCreateMethod, WalkState); + + + /* Create a new method object */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto Exit; + } + + /* Save the method's AML pointer and length */ + + ObjDesc->Method.AmlStart = AmlStart; + ObjDesc->Method.AmlLength = AmlLength; + + /* + * Disassemble the method flags. Split off the ArgCount, Serialized + * flag, and SyncLevel for efficiency. + */ + MethodFlags = (UINT8) Operand[1]->Integer.Value; + ObjDesc->Method.ParamCount = (UINT8) (MethodFlags & AML_METHOD_ARG_COUNT); + + /* + * Get the SyncLevel. If method is serialized, a mutex will be + * created for this method when it is parsed. + */ + if (MethodFlags & AML_METHOD_SERIALIZED) + { + ObjDesc->Method.InfoFlags = ACPI_METHOD_SERIALIZED; + + /* + * ACPI 1.0: SyncLevel = 0 + * ACPI 2.0: SyncLevel = SyncLevel in method declaration + */ + ObjDesc->Method.SyncLevel = (UINT8) + ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4); + } + + /* Attach the new object to the method Node */ + + Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], + ObjDesc, ACPI_TYPE_METHOD); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + +Exit: + /* Remove a reference to the operand */ + + AcpiUtRemoveReference (Operand[1]); + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exdebug.c b/source/components/executer/exdebug.c new file mode 100644 index 000000000000..166b2af170ff --- /dev/null +++ b/source/components/executer/exdebug.c @@ -0,0 +1,278 @@ +/****************************************************************************** + * + * Module Name: exdebug - Support for stores to the AML Debug Object + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXDEBUG_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exdebug") + + +#ifndef ACPI_NO_ERROR_MESSAGES +/******************************************************************************* + * + * FUNCTION: AcpiExDoDebugObject + * + * PARAMETERS: SourceDesc - Object to be output to "Debug Object" + * Level - Indentation level (used for packages) + * Index - Current package element, zero if not pkg + * + * RETURN: None + * + * DESCRIPTION: Handles stores to the AML Debug Object. For example: + * Store(INT1, Debug) + * + * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set. + * + * This function is only enabled if AcpiGbl_EnableAmlDebugObject is set, or + * if ACPI_LV_DEBUG_OBJECT is set in the AcpiDbgLevel. Thus, in the normal + * operational case, stores to the debug object are ignored but can be easily + * enabled if necessary. + * + ******************************************************************************/ + +void +AcpiExDoDebugObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + UINT32 Level, + UINT32 Index) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (ExDoDebugObject, SourceDesc); + + + /* Output must be enabled via the DebugObject global or the DbgLevel */ + + if (!AcpiGbl_EnableAmlDebugObject && + !(AcpiDbgLevel & ACPI_LV_DEBUG_OBJECT)) + { + return_VOID; + } + + /* + * Print line header as long as we are not in the middle of an + * object display + */ + if (!((Level > 0) && Index == 0)) + { + AcpiOsPrintf ("[ACPI Debug] %*s", Level, " "); + } + + /* Display the index for package output only */ + + if (Index > 0) + { + AcpiOsPrintf ("(%.2u) ", Index-1); + } + + if (!SourceDesc) + { + AcpiOsPrintf ("[Null Object]\n"); + return_VOID; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf ("%s ", AcpiUtGetObjectTypeName (SourceDesc)); + + if (!AcpiUtValidInternalObject (SourceDesc)) + { + AcpiOsPrintf ("%p, Invalid Internal Object!\n", SourceDesc); + return_VOID; + } + } + else if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) + { + AcpiOsPrintf ("%s: %p\n", + AcpiUtGetTypeName (((ACPI_NAMESPACE_NODE *) SourceDesc)->Type), + SourceDesc); + return_VOID; + } + else + { + return_VOID; + } + + /* SourceDesc is of type ACPI_DESC_TYPE_OPERAND */ + + switch (SourceDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* Output correct integer width */ + + if (AcpiGbl_IntegerByteWidth == 4) + { + AcpiOsPrintf ("0x%8.8X\n", + (UINT32) SourceDesc->Integer.Value); + } + else + { + AcpiOsPrintf ("0x%8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (SourceDesc->Integer.Value)); + } + break; + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("[0x%.2X]\n", (UINT32) SourceDesc->Buffer.Length); + AcpiUtDumpBuffer2 (SourceDesc->Buffer.Pointer, + (SourceDesc->Buffer.Length < 256) ? + SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY); + break; + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("[0x%.2X] \"%s\"\n", + SourceDesc->String.Length, SourceDesc->String.Pointer); + break; + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("[Contains 0x%.2X Elements]\n", + SourceDesc->Package.Count); + + /* Output the entire contents of the package */ + + for (i = 0; i < SourceDesc->Package.Count; i++) + { + AcpiExDoDebugObject (SourceDesc->Package.Elements[i], + Level+4, i+1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (SourceDesc)); + + /* Decode the reference */ + + switch (SourceDesc->Reference.Class) + { + case ACPI_REFCLASS_INDEX: + + AcpiOsPrintf ("0x%X\n", SourceDesc->Reference.Value); + break; + + case ACPI_REFCLASS_TABLE: + + /* Case for DdbHandle */ + + AcpiOsPrintf ("Table Index 0x%X\n", SourceDesc->Reference.Value); + return; + + default: + break; + } + + AcpiOsPrintf (" "); + + /* Check for valid node first, then valid object */ + + if (SourceDesc->Reference.Node) + { + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Node) != + ACPI_DESC_TYPE_NAMED) + { + AcpiOsPrintf (" %p - Not a valid namespace node\n", + SourceDesc->Reference.Node); + } + else + { + AcpiOsPrintf ("Node %p [%4.4s] ", SourceDesc->Reference.Node, + (SourceDesc->Reference.Node)->Name.Ascii); + + switch ((SourceDesc->Reference.Node)->Type) + { + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + AcpiOsPrintf ("Device\n"); + break; + + case ACPI_TYPE_THERMAL: + AcpiOsPrintf ("Thermal Zone\n"); + break; + + default: + AcpiExDoDebugObject ((SourceDesc->Reference.Node)->Object, + Level+4, 0); + break; + } + } + } + else if (SourceDesc->Reference.Object) + { + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Object) == + ACPI_DESC_TYPE_NAMED) + { + AcpiExDoDebugObject (((ACPI_NAMESPACE_NODE *) + SourceDesc->Reference.Object)->Object, + Level+4, 0); + } + else + { + AcpiExDoDebugObject (SourceDesc->Reference.Object, + Level+4, 0); + } + } + break; + + default: + + AcpiOsPrintf ("%p\n", SourceDesc); + break; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n")); + return_VOID; +} +#endif + + diff --git a/source/components/executer/exdump.c b/source/components/executer/exdump.c new file mode 100644 index 000000000000..4b49ceca09e7 --- /dev/null +++ b/source/components/executer/exdump.c @@ -0,0 +1,1124 @@ +/****************************************************************************** + * + * Module Name: exdump - Interpreter debug output routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXDUMP_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exdump") + +/* + * The following routines are used for debug output only + */ +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Local prototypes */ + +static void +AcpiExOutString ( + char *Title, + char *Value); + +static void +AcpiExOutPointer ( + char *Title, + void *Value); + +static void +AcpiExDumpObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_EXDUMP_INFO *Info); + +static void +AcpiExDumpReferenceObj ( + ACPI_OPERAND_OBJECT *ObjDesc); + +static void +AcpiExDumpPackageObj ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Level, + UINT32 Index); + + +/******************************************************************************* + * + * Object Descriptor info tables + * + * Note: The first table entry must be an INIT opcode and must contain + * the table length (number of table entries) + * + ******************************************************************************/ + +static ACPI_EXDUMP_INFO AcpiExDumpInteger[2] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpInteger), NULL}, + {ACPI_EXD_UINT64, ACPI_EXD_OFFSET (Integer.Value), "Value"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpString[4] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpString), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (String.Length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (String.Pointer), "Pointer"}, + {ACPI_EXD_STRING, 0, NULL} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpBuffer[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBuffer), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Buffer.Length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Buffer.Pointer), "Pointer"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Buffer.Node), "Parent Node"}, + {ACPI_EXD_BUFFER, 0, NULL} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpPackage[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpPackage), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Package.Flags), "Flags"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Package.Count), "Elements"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Package.Elements), "Element List"}, + {ACPI_EXD_PACKAGE, 0, NULL} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpDevice[4] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpDevice), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.Handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.SystemNotify), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.DeviceNotify), "Device Notify"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpEvent[2] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpEvent), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Event.OsSemaphore), "OsSemaphore"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpMethod[9] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMethod), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.InfoFlags), "Info Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ParamCount), "Parameter Count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.SyncLevel), "Sync Level"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Method.Mutex), "Mutex"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.OwnerId), "Owner Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ThreadCount), "Thread Count"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Method.AmlLength), "Aml Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Method.AmlStart), "Aml Start"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpMutex[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMutex), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Mutex.SyncLevel), "Sync Level"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Mutex.OwnerThread), "Owner Thread"}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET (Mutex.AcquisitionDepth), "Acquire Depth"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Mutex.OsMutex), "OsMutex"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpRegion[7] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpRegion), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Region.SpaceId), "Space Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Region.Flags), "Flags"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET (Region.Address), "Address"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Region.Length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Region.Handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Region.Next), "Next"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpPower[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpPower), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (PowerResource.SystemLevel), "System Level"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (PowerResource.ResourceOrder), "Resource Order"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.SystemNotify), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.DeviceNotify), "Device Notify"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpProcessor[7] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpProcessor), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Processor.ProcId), "Processor ID"}, + {ACPI_EXD_UINT8 , ACPI_EXD_OFFSET (Processor.Length), "Length"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET (Processor.Address), "Address"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.SystemNotify), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.DeviceNotify), "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.Handler), "Handler"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpThermal[4] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpThermal), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.SystemNotify), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.DeviceNotify), "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.Handler), "Handler"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpBufferField[3] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBufferField), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BufferField.BufferObj), "Buffer Object"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpRegionField[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpRegionField), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Field.AccessLength), "AccessLength"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Field.RegionObj), "Region Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Field.ResourceBuffer), "ResourceBuffer"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpBankField[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBankField), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (BankField.Value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BankField.RegionObj), "Region Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BankField.BankObj), "Bank Object"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpIndexField[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBankField), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (IndexField.Value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (IndexField.IndexObj), "Index Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (IndexField.DataObj), "Data Object"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpReference[8] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpReference), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Reference.Class), "Class"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Reference.TargetType), "Target Type"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Reference.Value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Object), "Object Desc"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Where), "Where"}, + {ACPI_EXD_REFERENCE,0, NULL} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpAddressHandler[6] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpAddressHandler), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (AddressSpace.SpaceId), "Space Id"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Next), "Next"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.RegionList), "Region List"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Context), "Context"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpNotify[3] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNotify), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Context), "Context"} +}; + + +/* Miscellaneous tables */ + +static ACPI_EXDUMP_INFO AcpiExDumpCommon[4] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpCommon), NULL}, + {ACPI_EXD_TYPE , 0, NULL}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET (Common.ReferenceCount), "Reference Count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Common.Flags), "Flags"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpFieldCommon[7] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpFieldCommon), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.FieldFlags), "Field Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.AccessByteWidth), "Access Byte Width"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (CommonField.BitLength), "Bit Length"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.StartFieldBitOffset),"Field Bit Offset"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (CommonField.BaseByteOffset), "Base Byte Offset"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (CommonField.Node), "Parent Node"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpNode[5] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNode), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET (Flags), "Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET (OwnerId), "Owner Id"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET (Child), "Child List"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET (Peer), "Next Peer"} +}; + + +/* Dispatch table, indexed by object type */ + +static ACPI_EXDUMP_INFO *AcpiExDumpInfo[] = +{ + NULL, + AcpiExDumpInteger, + AcpiExDumpString, + AcpiExDumpBuffer, + AcpiExDumpPackage, + NULL, + AcpiExDumpDevice, + AcpiExDumpEvent, + AcpiExDumpMethod, + AcpiExDumpMutex, + AcpiExDumpRegion, + AcpiExDumpPower, + AcpiExDumpProcessor, + AcpiExDumpThermal, + AcpiExDumpBufferField, + NULL, + NULL, + AcpiExDumpRegionField, + AcpiExDumpBankField, + AcpiExDumpIndexField, + AcpiExDumpReference, + NULL, + NULL, + AcpiExDumpNotify, + AcpiExDumpAddressHandler, + NULL, + NULL, + NULL +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpObject + * + * PARAMETERS: ObjDesc - Descriptor to dump + * Info - Info table corresponding to this object + * type + * + * RETURN: None + * + * DESCRIPTION: Walk the info table for this object + * + ******************************************************************************/ + +static void +AcpiExDumpObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_EXDUMP_INFO *Info) +{ + UINT8 *Target; + char *Name; + UINT8 Count; + + + if (!Info) + { + AcpiOsPrintf ( + "ExDumpObject: Display not implemented for object type %s\n", + AcpiUtGetObjectTypeName (ObjDesc)); + return; + } + + /* First table entry must contain the table length (# of table entries) */ + + Count = Info->Offset; + + while (Count) + { + Target = ACPI_ADD_PTR (UINT8, ObjDesc, Info->Offset); + Name = Info->Name; + + switch (Info->Opcode) + { + case ACPI_EXD_INIT: + break; + + case ACPI_EXD_TYPE: + + AcpiExOutString ("Type", AcpiUtGetObjectTypeName (ObjDesc)); + break; + + case ACPI_EXD_UINT8: + + AcpiOsPrintf ("%20s : %2.2X\n", Name, *Target); + break; + + case ACPI_EXD_UINT16: + + AcpiOsPrintf ("%20s : %4.4X\n", Name, ACPI_GET16 (Target)); + break; + + case ACPI_EXD_UINT32: + + AcpiOsPrintf ("%20s : %8.8X\n", Name, ACPI_GET32 (Target)); + break; + + case ACPI_EXD_UINT64: + + AcpiOsPrintf ("%20s : %8.8X%8.8X\n", "Value", + ACPI_FORMAT_UINT64 (ACPI_GET64 (Target))); + break; + + case ACPI_EXD_POINTER: + case ACPI_EXD_ADDRESS: + + AcpiExOutPointer (Name, *ACPI_CAST_PTR (void *, Target)); + break; + + case ACPI_EXD_STRING: + + AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); + AcpiOsPrintf ("\n"); + break; + + case ACPI_EXD_BUFFER: + + ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, ObjDesc->Buffer.Length); + break; + + case ACPI_EXD_PACKAGE: + + /* Dump the package contents */ + + AcpiOsPrintf ("\nPackage Contents:\n"); + AcpiExDumpPackageObj (ObjDesc, 0, 0); + break; + + case ACPI_EXD_FIELD: + + AcpiExDumpObject (ObjDesc, AcpiExDumpFieldCommon); + break; + + case ACPI_EXD_REFERENCE: + + AcpiExOutString ("Class Name", + ACPI_CAST_PTR (char, AcpiUtGetReferenceName (ObjDesc))); + AcpiExDumpReferenceObj (ObjDesc); + break; + + default: + + AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n", + Info->Opcode); + return; + } + + Info++; + Count--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpOperand + * + * PARAMETERS: *ObjDesc - Pointer to entry to be dumped + * Depth - Current nesting depth + * + * RETURN: None + * + * DESCRIPTION: Dump an operand object + * + ******************************************************************************/ + +void +AcpiExDumpOperand ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Depth) +{ + UINT32 Length; + UINT32 Index; + + + ACPI_FUNCTION_NAME (ExDumpOperand) + + + if (!((ACPI_LV_EXEC & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) + { + return; + } + + if (!ObjDesc) + { + /* This could be a null element of a package */ + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p Namespace Node: ", ObjDesc)); + ACPI_DUMP_ENTRY (ObjDesc, ACPI_LV_EXEC); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%p is not a node or operand object: [%s]\n", + ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); + ACPI_DUMP_BUFFER (ObjDesc, sizeof (ACPI_OPERAND_OBJECT)); + return; + } + + /* ObjDesc is a valid object */ + + if (Depth > 0) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ", + Depth, " ", Depth, ObjDesc)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", ObjDesc)); + } + + /* Decode object type */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("Reference: [%s] ", AcpiUtGetReferenceName (ObjDesc)); + + switch (ObjDesc->Reference.Class) + { + case ACPI_REFCLASS_DEBUG: + + AcpiOsPrintf ("\n"); + break; + + + case ACPI_REFCLASS_INDEX: + + AcpiOsPrintf ("%p\n", ObjDesc->Reference.Object); + break; + + + case ACPI_REFCLASS_TABLE: + + AcpiOsPrintf ("Table Index %X\n", ObjDesc->Reference.Value); + break; + + + case ACPI_REFCLASS_REFOF: + + AcpiOsPrintf ("%p [%s]\n", ObjDesc->Reference.Object, + AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) + ObjDesc->Reference.Object)->Common.Type)); + break; + + + case ACPI_REFCLASS_NAME: + + AcpiOsPrintf ("- [%4.4s]\n", ObjDesc->Reference.Node->Name.Ascii); + break; + + + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + + AcpiOsPrintf ("%X\n", ObjDesc->Reference.Value); + break; + + + default: /* Unknown reference class */ + + AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class); + break; + } + break; + + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("Buffer length %.2X @ %p\n", + ObjDesc->Buffer.Length, ObjDesc->Buffer.Pointer); + + /* Debug only -- dump the buffer contents */ + + if (ObjDesc->Buffer.Pointer) + { + Length = ObjDesc->Buffer.Length; + if (Length > 128) + { + Length = 128; + } + + AcpiOsPrintf ("Buffer Contents: (displaying length 0x%.2X)\n", + Length); + ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, Length); + } + break; + + + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf ("Integer %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("Package [Len %X] ElementArray %p\n", + ObjDesc->Package.Count, ObjDesc->Package.Elements); + + /* + * If elements exist, package element pointer is valid, + * and debug_level exceeds 1, dump package's elements. + */ + if (ObjDesc->Package.Count && + ObjDesc->Package.Elements && + AcpiDbgLevel > 1) + { + for (Index = 0; Index < ObjDesc->Package.Count; Index++) + { + AcpiExDumpOperand (ObjDesc->Package.Elements[Index], Depth+1); + } + } + break; + + + case ACPI_TYPE_REGION: + + AcpiOsPrintf ("Region %s (%X)", + AcpiUtGetRegionName (ObjDesc->Region.SpaceId), + ObjDesc->Region.SpaceId); + + /* + * If the address and length have not been evaluated, + * don't print them. + */ + if (!(ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)) + { + AcpiOsPrintf ("\n"); + } + else + { + AcpiOsPrintf (" base %8.8X%8.8X Length %X\n", + ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), + ObjDesc->Region.Length); + } + break; + + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("String length %X @ %p ", + ObjDesc->String.Length, + ObjDesc->String.Pointer); + + AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); + AcpiOsPrintf ("\n"); + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + AcpiOsPrintf ("BankField\n"); + break; + + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + AcpiOsPrintf ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at " + "byte=%X bit=%X of below:\n", + ObjDesc->Field.BitLength, + ObjDesc->Field.AccessByteWidth, + ObjDesc->Field.FieldFlags & AML_FIELD_LOCK_RULE_MASK, + ObjDesc->Field.FieldFlags & AML_FIELD_UPDATE_RULE_MASK, + ObjDesc->Field.BaseByteOffset, + ObjDesc->Field.StartFieldBitOffset); + + AcpiExDumpOperand (ObjDesc->Field.RegionObj, Depth+1); + break; + + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + AcpiOsPrintf ("IndexField\n"); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + AcpiOsPrintf ("BufferField: %X bits at byte %X bit %X of\n", + ObjDesc->BufferField.BitLength, + ObjDesc->BufferField.BaseByteOffset, + ObjDesc->BufferField.StartFieldBitOffset); + + if (!ObjDesc->BufferField.BufferObj) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL*\n")); + } + else if ((ObjDesc->BufferField.BufferObj)->Common.Type != + ACPI_TYPE_BUFFER) + { + AcpiOsPrintf ("*not a Buffer*\n"); + } + else + { + AcpiExDumpOperand (ObjDesc->BufferField.BufferObj, Depth+1); + } + break; + + + case ACPI_TYPE_EVENT: + + AcpiOsPrintf ("Event\n"); + break; + + + case ACPI_TYPE_METHOD: + + AcpiOsPrintf ("Method(%X) @ %p:%X\n", + ObjDesc->Method.ParamCount, + ObjDesc->Method.AmlStart, + ObjDesc->Method.AmlLength); + break; + + + case ACPI_TYPE_MUTEX: + + AcpiOsPrintf ("Mutex\n"); + break; + + + case ACPI_TYPE_DEVICE: + + AcpiOsPrintf ("Device\n"); + break; + + + case ACPI_TYPE_POWER: + + AcpiOsPrintf ("Power\n"); + break; + + + case ACPI_TYPE_PROCESSOR: + + AcpiOsPrintf ("Processor\n"); + break; + + + case ACPI_TYPE_THERMAL: + + AcpiOsPrintf ("Thermal\n"); + break; + + + default: + /* Unknown Type */ + + AcpiOsPrintf ("Unknown Type %X\n", ObjDesc->Common.Type); + break; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpOperands + * + * PARAMETERS: Operands - A list of Operand objects + * OpcodeName - AML opcode name + * NumOperands - Operand count for this opcode + * + * DESCRIPTION: Dump the operands associated with the opcode + * + ******************************************************************************/ + +void +AcpiExDumpOperands ( + ACPI_OPERAND_OBJECT **Operands, + const char *OpcodeName, + UINT32 NumOperands) +{ + ACPI_FUNCTION_NAME (ExDumpOperands); + + + if (!OpcodeName) + { + OpcodeName = "UNKNOWN"; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "**** Start operand dump for opcode [%s], %u operands\n", + OpcodeName, NumOperands)); + + if (NumOperands == 0) + { + NumOperands = 1; + } + + /* Dump the individual operands */ + + while (NumOperands) + { + AcpiExDumpOperand (*Operands, 0); + Operands++; + NumOperands--; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "**** End operand dump for [%s]\n", OpcodeName)); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOut* functions + * + * PARAMETERS: Title - Descriptive text + * Value - Value to be displayed + * + * DESCRIPTION: Object dump output formatting functions. These functions + * reduce the number of format strings required and keeps them + * all in one place for easy modification. + * + ******************************************************************************/ + +static void +AcpiExOutString ( + char *Title, + char *Value) +{ + AcpiOsPrintf ("%20s : %s\n", Title, Value); +} + +static void +AcpiExOutPointer ( + char *Title, + void *Value) +{ + AcpiOsPrintf ("%20s : %p\n", Title, Value); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpNamespaceNode + * + * PARAMETERS: Node - Descriptor to dump + * Flags - Force display if TRUE + * + * DESCRIPTION: Dumps the members of the given.Node + * + ******************************************************************************/ + +void +AcpiExDumpNamespaceNode ( + ACPI_NAMESPACE_NODE *Node, + UINT32 Flags) +{ + + ACPI_FUNCTION_ENTRY (); + + + if (!Flags) + { + if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) + { + return; + } + } + + AcpiOsPrintf ("%20s : %4.4s\n", "Name", AcpiUtGetNodeName (Node)); + AcpiExOutString ("Type", AcpiUtGetTypeName (Node->Type)); + AcpiExOutPointer ("Attached Object", AcpiNsGetAttachedObject (Node)); + AcpiExOutPointer ("Parent", Node->Parent); + + AcpiExDumpObject (ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node), + AcpiExDumpNode); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpReferenceObj + * + * PARAMETERS: Object - Descriptor to dump + * + * DESCRIPTION: Dumps a reference object + * + ******************************************************************************/ + +static void +AcpiExDumpReferenceObj ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_BUFFER RetBuf; + ACPI_STATUS Status; + + + RetBuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + if (ObjDesc->Reference.Class == ACPI_REFCLASS_NAME) + { + AcpiOsPrintf (" %p ", ObjDesc->Reference.Node); + + Status = AcpiNsHandleToPathname (ObjDesc->Reference.Node, &RetBuf); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf (" Could not convert name to pathname\n"); + } + else + { + AcpiOsPrintf ("%s\n", (char *) RetBuf.Pointer); + ACPI_FREE (RetBuf.Pointer); + } + } + else if (ObjDesc->Reference.Object) + { + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf (" Target: %p", ObjDesc->Reference.Object); + if (ObjDesc->Reference.Class == ACPI_REFCLASS_TABLE) + { + AcpiOsPrintf (" Table Index: %X\n", ObjDesc->Reference.Value); + } + else + { + AcpiOsPrintf (" Target: %p [%s]\n", ObjDesc->Reference.Object, + AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) + ObjDesc->Reference.Object)->Common.Type)); + } + } + else + { + AcpiOsPrintf (" Target: %p\n", ObjDesc->Reference.Object); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpPackageObj + * + * PARAMETERS: ObjDesc - Descriptor to dump + * Level - Indentation Level + * Index - Package index for this object + * + * DESCRIPTION: Dumps the elements of the package + * + ******************************************************************************/ + +static void +AcpiExDumpPackageObj ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Level, + UINT32 Index) +{ + UINT32 i; + + + /* Indentation and index output */ + + if (Level > 0) + { + for (i = 0; i < Level; i++) + { + AcpiOsPrintf (" "); + } + + AcpiOsPrintf ("[%.2d] ", Index); + } + + AcpiOsPrintf ("%p ", ObjDesc); + + /* Null package elements are allowed */ + + if (!ObjDesc) + { + AcpiOsPrintf ("[Null Object]\n"); + return; + } + + /* Packages may only contain a few object types */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("[String] Value: "); + for (i = 0; i < ObjDesc->String.Length; i++) + { + AcpiOsPrintf ("%c", ObjDesc->String.Pointer[i]); + } + AcpiOsPrintf ("\n"); + break; + + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length); + if (ObjDesc->Buffer.Length) + { + AcpiUtDumpBuffer (ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer), + ObjDesc->Buffer.Length, DB_DWORD_DISPLAY, _COMPONENT); + } + else + { + AcpiOsPrintf ("\n"); + } + break; + + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("[Package] Contains %u Elements:\n", + ObjDesc->Package.Count); + + for (i = 0; i < ObjDesc->Package.Count; i++) + { + AcpiExDumpPackageObj (ObjDesc->Package.Elements[i], Level+1, i); + } + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("[Object Reference] Type [%s] %2.2X", + AcpiUtGetReferenceName (ObjDesc), + ObjDesc->Reference.Class); + AcpiExDumpReferenceObj (ObjDesc); + break; + + + default: + + AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Common.Type); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDumpObjectDescriptor + * + * PARAMETERS: ObjDesc - Descriptor to dump + * Flags - Force display if TRUE + * + * DESCRIPTION: Dumps the members of the object descriptor given. + * + ******************************************************************************/ + +void +AcpiExDumpObjectDescriptor ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Flags) +{ + ACPI_FUNCTION_TRACE (ExDumpObjectDescriptor); + + + if (!ObjDesc) + { + return_VOID; + } + + if (!Flags) + { + if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) + { + return_VOID; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) + { + AcpiExDumpNamespaceNode ((ACPI_NAMESPACE_NODE *) ObjDesc, Flags); + + AcpiOsPrintf ("\nAttached Object (%p):\n", + ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object); + + AcpiExDumpObjectDescriptor ( + ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object, Flags); + return_VOID; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf ( + "ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", + ObjDesc, AcpiUtGetDescriptorName (ObjDesc)); + return_VOID; + } + + if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) + { + return_VOID; + } + + /* Common Fields */ + + AcpiExDumpObject (ObjDesc, AcpiExDumpCommon); + + /* Object-specific fields */ + + AcpiExDumpObject (ObjDesc, AcpiExDumpInfo[ObjDesc->Common.Type]); + return_VOID; +} + +#endif + diff --git a/source/components/executer/exfield.c b/source/components/executer/exfield.c new file mode 100644 index 000000000000..a68240682607 --- /dev/null +++ b/source/components/executer/exfield.c @@ -0,0 +1,406 @@ +/****************************************************************************** + * + * Module Name: exfield - ACPI AML (p-code) execution - field manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EXFIELD_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exfield") + + +/******************************************************************************* + * + * FUNCTION: AcpiExReadDataFromField + * + * PARAMETERS: WalkState - Current execution state + * ObjDesc - The named field + * RetBufferDesc - Where the return data object is stored + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field. Returns either an Integer or a + * Buffer, depending on the size of the field. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadDataFromField ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **RetBufferDesc) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *BufferDesc; + ACPI_SIZE Length; + void *Buffer; + UINT32 Function; + + + ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); + + + /* Parameter validation */ + + if (!ObjDesc) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + if (!RetBufferDesc) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) + { + /* + * If the BufferField arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetBufferFieldArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) + { + /* + * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold + * the data and then directly access the region handler. + * + * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function + */ + if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS) + { + Length = ACPI_SMBUS_BUFFER_SIZE; + Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); + } + else if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) + { + Length = ACPI_GSBUS_BUFFER_SIZE; + Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); + } + else /* IPMI */ + { + Length = ACPI_IPMI_BUFFER_SIZE; + Function = ACPI_READ; + } + + BufferDesc = AcpiUtCreateBufferObject (Length); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Call the region handler for the read */ + + Status = AcpiExAccessRegion (ObjDesc, 0, + ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), + Function); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + goto Exit; + } + + /* + * Allocate a buffer for the contents of the field. + * + * If the field is larger than the current integer width, create + * a BUFFER to hold it. Otherwise, use an INTEGER. This allows + * the use of arithmetic operators on the returned value if the + * field size is equal or smaller than an Integer. + * + * Note: Field.length is in bits. + */ + Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->Field.BitLength); + if (Length > AcpiGbl_IntegerByteWidth) + { + /* Field is too large for an Integer, create a Buffer instead */ + + BufferDesc = AcpiUtCreateBufferObject (Length); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + Buffer = BufferDesc->Buffer.Pointer; + } + else + { + /* Field will fit within an Integer (normal case) */ + + BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Length = AcpiGbl_IntegerByteWidth; + Buffer = &BufferDesc->Integer.Value; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", + ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", + ObjDesc->CommonField.BitLength, + ObjDesc->CommonField.StartFieldBitOffset, + ObjDesc->CommonField.BaseByteOffset)); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Read from the field */ + + Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + +Exit: + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (BufferDesc); + } + else + { + *RetBufferDesc = BufferDesc; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteDataToField + * + * PARAMETERS: SourceDesc - Contains data to write + * ObjDesc - The named field + * ResultDesc - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteDataToField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc) +{ + ACPI_STATUS Status; + UINT32 Length; + void *Buffer; + ACPI_OPERAND_OBJECT *BufferDesc; + UINT32 Function; + + + ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); + + + /* Parameter validation */ + + if (!SourceDesc || !ObjDesc) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) + { + /* + * If the BufferField arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetBufferFieldArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) + { + /* + * This is an SMBus, GSBus or IPMI write. We will bypass the entire field + * mechanism and handoff the buffer directly to the handler. For + * these address spaces, the buffer is bi-directional; on a write, + * return data is returned in the same buffer. + * + * Source must be a buffer of sufficient size: + * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. + * + * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function + */ + if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) + { + ACPI_ERROR ((AE_INFO, + "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS) + { + Length = ACPI_SMBUS_BUFFER_SIZE; + Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); + } + else if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) + { + Length = ACPI_GSBUS_BUFFER_SIZE; + Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); + } + else /* IPMI */ + { + Length = ACPI_IPMI_BUFFER_SIZE; + Function = ACPI_WRITE; + } + + if (SourceDesc->Buffer.Length < Length) + { + ACPI_ERROR ((AE_INFO, + "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u", + Length, SourceDesc->Buffer.Length)); + + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + + /* Create the bi-directional buffer */ + + BufferDesc = AcpiUtCreateBufferObject (Length); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Buffer = BufferDesc->Buffer.Pointer; + ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, Length); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* + * Perform the write (returns status and perhaps data in the + * same buffer) + */ + Status = AcpiExAccessRegion (ObjDesc, 0, + (UINT64 *) Buffer, Function); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + *ResultDesc = BufferDesc; + return_ACPI_STATUS (Status); + } + + /* Get a pointer to the data to be written */ + + switch (SourceDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + Buffer = &SourceDesc->Integer.Value; + Length = sizeof (SourceDesc->Integer.Value); + break; + + case ACPI_TYPE_BUFFER: + Buffer = SourceDesc->Buffer.Pointer; + Length = SourceDesc->Buffer.Length; + break; + + case ACPI_TYPE_STRING: + Buffer = SourceDesc->String.Pointer; + Length = SourceDesc->String.Length; + break; + + default: + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", + SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), + SourceDesc->Common.Type, Buffer, Length)); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", + ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), + ObjDesc->Common.Type, + ObjDesc->CommonField.BitLength, + ObjDesc->CommonField.StartFieldBitOffset, + ObjDesc->CommonField.BaseByteOffset)); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Write to the field */ + + Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exfldio.c b/source/components/executer/exfldio.c new file mode 100644 index 000000000000..e138e9a13ce4 --- /dev/null +++ b/source/components/executer/exfldio.c @@ -0,0 +1,1055 @@ +/****************************************************************************** + * + * Module Name: exfldio - Aml Field I/O + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EXFLDIO_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acevents.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exfldio") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExFieldDatumIo ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset, + UINT64 *Value, + UINT32 ReadWrite); + +static BOOLEAN +AcpiExRegisterOverflow ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT64 Value); + +static ACPI_STATUS +AcpiExSetupRegion ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset); + + +/******************************************************************************* + * + * FUNCTION: AcpiExSetupRegion + * + * PARAMETERS: ObjDesc - Field to be read or written + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field + * + * RETURN: Status + * + * DESCRIPTION: Common processing for AcpiExExtractFromField and + * AcpiExInsertIntoField. Initialize the Region if necessary and + * validate the request. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExSetupRegion ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *RgnDesc; + UINT8 SpaceId; + + + ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset); + + + RgnDesc = ObjDesc->CommonField.RegionObj; + + /* We must have a valid region */ + + if (RgnDesc->Common.Type != ACPI_TYPE_REGION) + { + ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", + RgnDesc->Common.Type, + AcpiUtGetObjectTypeName (RgnDesc))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + SpaceId = RgnDesc->Region.SpaceId; + + /* Validate the Space ID */ + + if (!AcpiIsValidSpaceId (SpaceId)) + { + ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId)); + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); + } + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetRegionArguments (RgnDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear + * address space and the request cannot be directly validated + */ + if (SpaceId == ACPI_ADR_SPACE_SMBUS || + SpaceId == ACPI_ADR_SPACE_GSBUS || + SpaceId == ACPI_ADR_SPACE_IPMI) + { + /* SMBus or IPMI has a non-linear address space */ + + return_ACPI_STATUS (AE_OK); + } + +#ifdef ACPI_UNDER_DEVELOPMENT + /* + * If the Field access is AnyAcc, we can now compute the optimal + * access (because we know know the length of the parent region) + */ + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } +#endif + + /* + * Validate the request. The entire request from the byte offset for a + * length of one field datum (access width) must fit within the region. + * (Region length is specified in bytes) + */ + if (RgnDesc->Region.Length < + (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset + + ObjDesc->CommonField.AccessByteWidth)) + { + if (AcpiGbl_EnableInterpreterSlack) + { + /* + * Slack mode only: We will go ahead and allow access to this + * field if it is within the region length rounded up to the next + * access width boundary. ACPI_SIZE cast for 64-bit compile. + */ + if (ACPI_ROUND_UP (RgnDesc->Region.Length, + ObjDesc->CommonField.AccessByteWidth) >= + ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset + + ObjDesc->CommonField.AccessByteWidth + + FieldDatumByteOffset)) + { + return_ACPI_STATUS (AE_OK); + } + } + + if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth) + { + /* + * This is the case where the AccessType (AccWord, etc.) is wider + * than the region itself. For example, a region of length one + * byte, and a field with Dword access specified. + */ + ACPI_ERROR ((AE_INFO, + "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)", + AcpiUtGetNodeName (ObjDesc->CommonField.Node), + ObjDesc->CommonField.AccessByteWidth, + AcpiUtGetNodeName (RgnDesc->Region.Node), + RgnDesc->Region.Length)); + } + + /* + * Offset rounded up to next multiple of field width + * exceeds region length, indicate an error + */ + ACPI_ERROR ((AE_INFO, + "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)", + AcpiUtGetNodeName (ObjDesc->CommonField.Node), + ObjDesc->CommonField.BaseByteOffset, + FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth, + AcpiUtGetNodeName (RgnDesc->Region.Node), + RgnDesc->Region.Length)); + + return_ACPI_STATUS (AE_AML_REGION_LIMIT); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExAccessRegion + * + * PARAMETERS: ObjDesc - Field to be read + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field + * Value - Where to store value (must at least + * 64 bits) + * Function - Read or Write flag plus other region- + * dependent flags + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single field datum to an Operation Region. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExAccessRegion ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset, + UINT64 *Value, + UINT32 Function) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *RgnDesc; + UINT32 RegionOffset; + + + ACPI_FUNCTION_TRACE (ExAccessRegion); + + + /* + * Ensure that the region operands are fully evaluated and verify + * the validity of the request + */ + Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + RgnDesc = ObjDesc->CommonField.RegionObj; + RegionOffset = + ObjDesc->CommonField.BaseByteOffset + + FieldDatumByteOffset; + + if ((Function & ACPI_IO_MASK) == ACPI_READ) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD, + " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId, + ObjDesc->CommonField.AccessByteWidth, + ObjDesc->CommonField.BaseByteOffset, + FieldDatumByteOffset, + ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset)))); + + /* Invoke the appropriate AddressSpace/OpRegion handler */ + + Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc, + Function, RegionOffset, + ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value); + + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_IMPLEMENTED) + { + ACPI_ERROR ((AE_INFO, + "Region %s (ID=%u) not implemented", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId)); + } + else if (Status == AE_NOT_EXIST) + { + ACPI_ERROR ((AE_INFO, + "Region %s (ID=%u) has no handler", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId)); + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExRegisterOverflow + * + * PARAMETERS: ObjDesc - Register(Field) to be written + * Value - Value to be stored + * + * RETURN: TRUE if value overflows the field, FALSE otherwise + * + * DESCRIPTION: Check if a value is out of range of the field being written. + * Used to check if the values written to Index and Bank registers + * are out of range. Normally, the value is simply truncated + * to fit the field, but this case is most likely a serious + * coding error in the ASL. + * + ******************************************************************************/ + +static BOOLEAN +AcpiExRegisterOverflow ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT64 Value) +{ + + if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE) + { + /* + * The field is large enough to hold the maximum integer, so we can + * never overflow it. + */ + return (FALSE); + } + + if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength)) + { + /* + * The Value is larger than the maximum value that can fit into + * the register. + */ + ACPI_ERROR ((AE_INFO, + "Index value 0x%8.8X%8.8X overflows field width 0x%X", + ACPI_FORMAT_UINT64 (Value), + ObjDesc->CommonField.BitLength)); + + return (TRUE); + } + + /* The Value will fit into the field with no truncation */ + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExFieldDatumIo + * + * PARAMETERS: ObjDesc - Field to be read + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field + * Value - Where to store value (must be 64 bits) + * ReadWrite - Read or Write flag + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single datum of a field. The FieldType is + * demultiplexed here to handle the different types of fields + * (BufferField, RegionField, IndexField, BankField) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExFieldDatumIo ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset, + UINT64 *Value, + UINT32 ReadWrite) +{ + ACPI_STATUS Status; + UINT64 LocalValue; + + + ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset); + + + if (ReadWrite == ACPI_READ) + { + if (!Value) + { + LocalValue = 0; + + /* To support reads without saving return value */ + Value = &LocalValue; + } + + /* Clear the entire return buffer first, [Very Important!] */ + + *Value = 0; + } + + /* + * The four types of fields are: + * + * BufferField - Read/write from/to a Buffer + * RegionField - Read/write from/to a Operation Region. + * BankField - Write to a Bank Register, then read/write from/to an + * OperationRegion + * IndexField - Write to an Index Register, then read/write from/to a + * Data Register + */ + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_BUFFER_FIELD: + /* + * If the BufferField arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetBufferFieldArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (ReadWrite == ACPI_READ) + { + /* + * Copy the data from the source buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY (Value, + (ObjDesc->BufferField.BufferObj)->Buffer.Pointer + + ObjDesc->BufferField.BaseByteOffset + + FieldDatumByteOffset, + ObjDesc->CommonField.AccessByteWidth); + } + else + { + /* + * Copy the data to the target buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer + + ObjDesc->BufferField.BaseByteOffset + + FieldDatumByteOffset, + Value, ObjDesc->CommonField.AccessByteWidth); + } + + Status = AE_OK; + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* + * Ensure that the BankValue is not beyond the capacity of + * the register + */ + if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj, + (UINT64) ObjDesc->BankField.Value)) + { + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + + /* + * For BankFields, we must write the BankValue to the BankRegister + * (itself a RegionField) before we can access the data. + */ + Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj, + &ObjDesc->BankField.Value, + sizeof (ObjDesc->BankField.Value)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Now that the Bank has been selected, fall through to the + * RegionField case and write the datum to the Operation Region + */ + + /*lint -fallthrough */ + + + case ACPI_TYPE_LOCAL_REGION_FIELD: + /* + * For simple RegionFields, we just directly access the owning + * Operation Region. + */ + Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value, + ReadWrite); + break; + + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + + /* + * Ensure that the IndexValue is not beyond the capacity of + * the register + */ + if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj, + (UINT64) ObjDesc->IndexField.Value)) + { + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + + /* Write the index value to the IndexRegister (itself a RegionField) */ + + FieldDatumByteOffset += ObjDesc->IndexField.Value; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Write to Index Register: Value %8.8X\n", + FieldDatumByteOffset)); + + Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj, + &FieldDatumByteOffset, + sizeof (FieldDatumByteOffset)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (ReadWrite == ACPI_READ) + { + /* Read the datum from the DataRegister */ + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Read from Data Register\n")); + + Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj, + Value, sizeof (UINT64)); + } + else + { + /* Write the datum to the DataRegister */ + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Write to Data Register: Value %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (*Value))); + + Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj, + Value, sizeof (UINT64)); + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u", + ObjDesc->Common.Type)); + Status = AE_AML_INTERNAL; + break; + } + + if (ACPI_SUCCESS (Status)) + { + if (ReadWrite == ACPI_READ) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Value Read %8.8X%8.8X, Width %u\n", + ACPI_FORMAT_UINT64 (*Value), + ObjDesc->CommonField.AccessByteWidth)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Value Written %8.8X%8.8X, Width %u\n", + ACPI_FORMAT_UINT64 (*Value), + ObjDesc->CommonField.AccessByteWidth)); + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteWithUpdateRule + * + * PARAMETERS: ObjDesc - Field to be written + * Mask - bitmask within field datum + * FieldValue - Value to write + * FieldDatumByteOffset - Offset of datum within field + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteWithUpdateRule ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT64 Mask, + UINT64 FieldValue, + UINT32 FieldDatumByteOffset) +{ + ACPI_STATUS Status = AE_OK; + UINT64 MergedValue; + UINT64 CurrentValue; + + + ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask); + + + /* Start with the new bits */ + + MergedValue = FieldValue; + + /* If the mask is all ones, we don't need to worry about the update rule */ + + if (Mask != ACPI_UINT64_MAX) + { + /* Decode the update rule */ + + switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK) + { + case AML_FIELD_UPDATE_PRESERVE: + /* + * Check if update rule needs to be applied (not if mask is all + * ones) The left shift drops the bits we want to ignore. + */ + if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) - + ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0) + { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &CurrentValue, ACPI_READ); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + MergedValue |= (CurrentValue & ~Mask); + } + break; + + case AML_FIELD_UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + MergedValue |= ~Mask; + break; + + case AML_FIELD_UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + MergedValue &= Mask; + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown UpdateRule value: 0x%X", + (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK))); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (Mask), + FieldDatumByteOffset, + ObjDesc->CommonField.AccessByteWidth, + ACPI_FORMAT_UINT64 (FieldValue), + ACPI_FORMAT_UINT64 (MergedValue))); + + /* Write the merged value */ + + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &MergedValue, ACPI_WRITE); + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExExtractFromField + * + * PARAMETERS: ObjDesc - Field to be read + * Buffer - Where to store the field data + * BufferLength - Length of Buffer + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the current value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExExtractFromField ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer, + UINT32 BufferLength) +{ + ACPI_STATUS Status; + UINT64 RawDatum; + UINT64 MergedDatum; + UINT32 FieldOffset = 0; + UINT32 BufferOffset = 0; + UINT32 BufferTailBits; + UINT32 DatumCount; + UINT32 FieldDatumCount; + UINT32 AccessBitWidth; + UINT32 i; + + + ACPI_FUNCTION_TRACE (ExExtractFromField); + + + /* Validate target buffer and clear it */ + + if (BufferLength < + ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength)) + { + ACPI_ERROR ((AE_INFO, + "Field size %u (bits) is too large for buffer (%u)", + ObjDesc->CommonField.BitLength, BufferLength)); + + return_ACPI_STATUS (AE_BUFFER_OVERFLOW); + } + + ACPI_MEMSET (Buffer, 0, BufferLength); + AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth); + + /* Handle the simple case here */ + + if ((ObjDesc->CommonField.StartFieldBitOffset == 0) && + (ObjDesc->CommonField.BitLength == AccessBitWidth)) + { + Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ); + return_ACPI_STATUS (Status); + } + +/* TBD: Move to common setup code */ + + /* Field algorithm is limited to sizeof(UINT64), truncate if needed */ + + if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64)) + { + ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64); + AccessBitWidth = sizeof (UINT64) * 8; + } + + /* Compute the number of datums (access width data items) */ + + DatumCount = ACPI_ROUND_UP_TO ( + ObjDesc->CommonField.BitLength, AccessBitWidth); + + FieldDatumCount = ACPI_ROUND_UP_TO ( + ObjDesc->CommonField.BitLength + + ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth); + + /* Priming read from the field */ + + Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset; + + /* Read the rest of the field */ + + for (i = 1; i < FieldDatumCount; i++) + { + /* Get next input datum from the field */ + + FieldOffset += ObjDesc->CommonField.AccessByteWidth; + Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, + &RawDatum, ACPI_READ); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Merge with previous datum if necessary. + * + * Note: Before the shift, check if the shift value will be larger than + * the integer size. If so, there is no need to perform the operation. + * This avoids the differences in behavior between different compilers + * concerning shift values larger than the target data width. + */ + if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset < + ACPI_INTEGER_BIT_SIZE) + { + MergedDatum |= RawDatum << + (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset); + } + + if (i == DatumCount) + { + break; + } + + /* Write merged datum to target buffer */ + + ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum, + ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, + BufferLength - BufferOffset)); + + BufferOffset += ObjDesc->CommonField.AccessByteWidth; + MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset; + } + + /* Mask off any extra bits in the last datum */ + + BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth; + if (BufferTailBits) + { + MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits); + } + + /* Write the last datum to the buffer */ + + ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum, + ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, + BufferLength - BufferOffset)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExInsertIntoField + * + * PARAMETERS: ObjDesc - Field to be written + * Buffer - Data to be written + * BufferLength - Length of Buffer + * + * RETURN: Status + * + * DESCRIPTION: Store the Buffer contents into the given field + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExInsertIntoField ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer, + UINT32 BufferLength) +{ + void *NewBuffer; + ACPI_STATUS Status; + UINT64 Mask; + UINT64 WidthMask; + UINT64 MergedDatum; + UINT64 RawDatum = 0; + UINT32 FieldOffset = 0; + UINT32 BufferOffset = 0; + UINT32 BufferTailBits; + UINT32 DatumCount; + UINT32 FieldDatumCount; + UINT32 AccessBitWidth; + UINT32 RequiredLength; + UINT32 i; + + + ACPI_FUNCTION_TRACE (ExInsertIntoField); + + + /* Validate input buffer */ + + NewBuffer = NULL; + RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->CommonField.BitLength); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (BufferLength < RequiredLength) + { + /* We need to create a new buffer */ + + NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength); + if (!NewBuffer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength); + Buffer = NewBuffer; + BufferLength = RequiredLength; + } + +/* TBD: Move to common setup code */ + + /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */ + if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64)) + { + ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64); + } + + AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth); + + /* + * Create the bitmasks used for bit insertion. + * Note: This if/else is used to bypass compiler differences with the + * shift operator + */ + if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE) + { + WidthMask = ACPI_UINT64_MAX; + } + else + { + WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth); + } + + Mask = WidthMask & + ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset); + + /* Compute the number of datums (access width data items) */ + + DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength, + AccessBitWidth); + + FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength + + ObjDesc->CommonField.StartFieldBitOffset, + AccessBitWidth); + + /* Get initial Datum from the input buffer */ + + ACPI_MEMCPY (&RawDatum, Buffer, + ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, + BufferLength - BufferOffset)); + + MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset; + + /* Write the entire field */ + + for (i = 1; i < FieldDatumCount; i++) + { + /* Write merged datum to the target field */ + + MergedDatum &= Mask; + Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, + MergedDatum, FieldOffset); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + FieldOffset += ObjDesc->CommonField.AccessByteWidth; + + /* + * Start new output datum by merging with previous input datum + * if necessary. + * + * Note: Before the shift, check if the shift value will be larger than + * the integer size. If so, there is no need to perform the operation. + * This avoids the differences in behavior between different compilers + * concerning shift values larger than the target data width. + */ + if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) < + ACPI_INTEGER_BIT_SIZE) + { + MergedDatum = RawDatum >> + (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset); + } + else + { + MergedDatum = 0; + } + + Mask = WidthMask; + + if (i == DatumCount) + { + break; + } + + /* Get the next input datum from the buffer */ + + BufferOffset += ObjDesc->CommonField.AccessByteWidth; + ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset, + ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, + BufferLength - BufferOffset)); + + MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset; + } + + /* Mask off any extra bits in the last datum */ + + BufferTailBits = (ObjDesc->CommonField.BitLength + + ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth; + if (BufferTailBits) + { + Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits); + } + + /* Write the last datum to the field */ + + MergedDatum &= Mask; + Status = AcpiExWriteWithUpdateRule (ObjDesc, + Mask, MergedDatum, FieldOffset); + +Exit: + /* Free temporary buffer if we used one */ + + if (NewBuffer) + { + ACPI_FREE (NewBuffer); + } + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exmisc.c b/source/components/executer/exmisc.c new file mode 100644 index 000000000000..63114f5584d6 --- /dev/null +++ b/source/components/executer/exmisc.c @@ -0,0 +1,800 @@ + +/****************************************************************************** + * + * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXMISC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "amlresrc.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exmisc") + + +/******************************************************************************* + * + * FUNCTION: AcpiExGetObjectReference + * + * PARAMETERS: ObjDesc - Create a reference to this object + * ReturnDesc - Where to store the reference + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Obtain and return a "reference" to the target object + * Common code for the RefOfOp and the CondRefOfOp. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExGetObjectReference ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *ReferenceObj; + ACPI_OPERAND_OBJECT *ReferencedObj; + + + ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc); + + + *ReturnDesc = NULL; + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) + { + case ACPI_DESC_TYPE_OPERAND: + + if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * Must be a reference to a Local or Arg + */ + switch (ObjDesc->Reference.Class) + { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_DEBUG: + + /* The referenced object is the pseudo-node for the local/arg */ + + ReferencedObj = ObjDesc->Reference.Object; + break; + + default: + + ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", + ObjDesc->Reference.Class)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + break; + + + case ACPI_DESC_TYPE_NAMED: + + /* + * A named reference that has already been resolved to a Node + */ + ReferencedObj = ObjDesc; + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X", + ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))); + return_ACPI_STATUS (AE_TYPE); + } + + + /* Create a new reference object */ + + ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); + if (!ReferenceObj) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF; + ReferenceObj->Reference.Object = ReferencedObj; + *ReturnDesc = ReferenceObj; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Object %p Type [%s], returning Reference %p\n", + ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConcatTemplate + * + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * ActualReturnDesc - Where to place the return object + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two resource templates + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExConcatTemplate ( + ACPI_OPERAND_OBJECT *Operand0, + ACPI_OPERAND_OBJECT *Operand1, + ACPI_OPERAND_OBJECT **ActualReturnDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ReturnDesc; + UINT8 *NewBuf; + UINT8 *EndTag; + ACPI_SIZE Length0; + ACPI_SIZE Length1; + ACPI_SIZE NewLength; + + + ACPI_FUNCTION_TRACE (ExConcatTemplate); + + + /* + * Find the EndTag descriptor in each resource template. + * Note1: returned pointers point TO the EndTag, not past it. + * Note2: zero-length buffers are allowed; treated like one EndTag + */ + + /* Get the length of the first resource template */ + + Status = AcpiUtGetResourceEndTag (Operand0, &EndTag); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer); + + /* Get the length of the second resource template */ + + Status = AcpiUtGetResourceEndTag (Operand1, &EndTag); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer); + + /* Combine both lengths, minimum size will be 2 for EndTag */ + + NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG); + + /* Create a new buffer object for the result (with one EndTag) */ + + ReturnDesc = AcpiUtCreateBufferObject (NewLength); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Copy the templates to the new buffer, 0 first, then 1 follows. One + * EndTag descriptor is copied from Operand1. + */ + NewBuf = ReturnDesc->Buffer.Pointer; + ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0); + ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); + + /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ + + NewBuf[NewLength - 1] = 0; + NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; + + /* Return the completed resource template */ + + *ActualReturnDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDoConcatenate + * + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * ActualReturnDesc - Where to place the return object + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExDoConcatenate ( + ACPI_OPERAND_OBJECT *Operand0, + ACPI_OPERAND_OBJECT *Operand1, + ACPI_OPERAND_OBJECT **ActualReturnDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; + ACPI_OPERAND_OBJECT *ReturnDesc; + char *NewBuf; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExDoConcatenate); + + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (Operand0->Common.Type) + { + case ACPI_TYPE_INTEGER: + Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); + break; + + case ACPI_TYPE_STRING: + Status = AcpiExConvertToString (Operand1, &LocalOperand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); + break; + + default: + ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", + Operand0->Common.Type)); + Status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ + + /* + * There are three cases to handle: + * + * 1) Two Integers concatenated to produce a new Buffer + * 2) Two Strings concatenated to produce a new String + * 3) Two Buffers concatenated to produce a new Buffer + */ + switch (Operand0->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* Result of two Integers is a Buffer */ + /* Need enough buffer space for two integers */ + + ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) + ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + NewBuf = (char *) ReturnDesc->Buffer.Pointer; + + /* Copy the first integer, LSB first */ + + ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, + AcpiGbl_IntegerByteWidth); + + /* Copy the second integer (LSB first) after the first */ + + ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, + &LocalOperand1->Integer.Value, + AcpiGbl_IntegerByteWidth); + break; + + case ACPI_TYPE_STRING: + + /* Result of two Strings is a String */ + + ReturnDesc = AcpiUtCreateStringObject ( + ((ACPI_SIZE) Operand0->String.Length + + LocalOperand1->String.Length)); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + NewBuf = ReturnDesc->String.Pointer; + + /* Concatenate the strings */ + + ACPI_STRCPY (NewBuf, Operand0->String.Pointer); + ACPI_STRCPY (NewBuf + Operand0->String.Length, + LocalOperand1->String.Pointer); + break; + + case ACPI_TYPE_BUFFER: + + /* Result of two Buffers is a Buffer */ + + ReturnDesc = AcpiUtCreateBufferObject ( + ((ACPI_SIZE) Operand0->Buffer.Length + + LocalOperand1->Buffer.Length)); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + NewBuf = (char *) ReturnDesc->Buffer.Pointer; + + /* Concatenate the buffers */ + + ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, + Operand0->Buffer.Length); + ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, + LocalOperand1->Buffer.Pointer, + LocalOperand1->Buffer.Length); + break; + + default: + + /* Invalid object type, should not happen here */ + + ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", + Operand0->Common.Type)); + Status =AE_AML_INTERNAL; + goto Cleanup; + } + + *ActualReturnDesc = ReturnDesc; + +Cleanup: + if (LocalOperand1 != Operand1) + { + AcpiUtRemoveReference (LocalOperand1); + } + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDoMathOp + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * + * RETURN: Integer result of the operation + * + * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the + * math functions here is to prevent a lot of pointer dereferencing + * to obtain the operands. + * + ******************************************************************************/ + +UINT64 +AcpiExDoMathOp ( + UINT16 Opcode, + UINT64 Integer0, + UINT64 Integer1) +{ + + ACPI_FUNCTION_ENTRY (); + + + switch (Opcode) + { + case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ + + return (Integer0 + Integer1); + + + case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ + + return (Integer0 & Integer1); + + + case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ + + return (~(Integer0 & Integer1)); + + + case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ + + return (Integer0 | Integer1); + + + case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ + + return (~(Integer0 | Integer1)); + + + case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ + + return (Integer0 ^ Integer1); + + + case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ + + return (Integer0 * Integer1); + + + case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/ + + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (Integer1 >= AcpiGbl_IntegerBitWidth) + { + return (0); + } + return (Integer0 << Integer1); + + + case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */ + + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (Integer1 >= AcpiGbl_IntegerBitWidth) + { + return (0); + } + return (Integer0 >> Integer1); + + + case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ + + return (Integer0 - Integer1); + + default: + + return (0); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDoLogicalNumericOp + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * LogicalResult - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric + * operators (LAnd and LOr), both operands must be integers. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Integer0 && Integer1); + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExDoLogicalNumericOp ( + UINT16 Opcode, + UINT64 Integer0, + UINT64 Integer1, + BOOLEAN *LogicalResult) +{ + ACPI_STATUS Status = AE_OK; + BOOLEAN LocalResult = FALSE; + + + ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp); + + + switch (Opcode) + { + case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ + + if (Integer0 && Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LOR_OP: /* LOr (Integer0, Integer1) */ + + if (Integer0 || Integer1) + { + LocalResult = TRUE; + } + break; + + default: + Status = AE_AML_INTERNAL; + break; + } + + /* Return the logical result and status */ + + *LogicalResult = LocalResult; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDoLogicalOp + * + * PARAMETERS: Opcode - AML opcode + * Operand0 - operand #0 + * Operand1 - operand #1 + * LogicalResult - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the + * functions here is to prevent a lot of pointer dereferencing + * to obtain the operands and to simplify the generation of the + * logical value. For the Numeric operators (LAnd and LOr), both + * operands must be integers. For the other logical operators, + * operands can be any combination of Integer/String/Buffer. The + * first operand determines the type to which the second operand + * will be converted. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Operand0 == Operand1); + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExDoLogicalOp ( + UINT16 Opcode, + ACPI_OPERAND_OBJECT *Operand0, + ACPI_OPERAND_OBJECT *Operand1, + BOOLEAN *LogicalResult) +{ + ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; + UINT64 Integer0; + UINT64 Integer1; + UINT32 Length0; + UINT32 Length1; + ACPI_STATUS Status = AE_OK; + BOOLEAN LocalResult = FALSE; + int Compare; + + + ACPI_FUNCTION_TRACE (ExDoLogicalOp); + + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI 3.0+ specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (Operand0->Common.Type) + { + case ACPI_TYPE_INTEGER: + Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); + break; + + case ACPI_TYPE_STRING: + Status = AcpiExConvertToString (Operand1, &LocalOperand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); + break; + + default: + Status = AE_AML_INTERNAL; + break; + } + + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * Two cases: 1) Both Integers, 2) Both Strings or Buffers + */ + if (Operand0->Common.Type == ACPI_TYPE_INTEGER) + { + /* + * 1) Both operands are of type integer + * Note: LocalOperand1 may have changed above + */ + Integer0 = Operand0->Integer.Value; + Integer1 = LocalOperand1->Integer.Value; + + switch (Opcode) + { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + + if (Integer0 == Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (Integer0 > Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (Integer0 < Integer1) + { + LocalResult = TRUE; + } + break; + + default: + Status = AE_AML_INTERNAL; + break; + } + } + else + { + /* + * 2) Both operands are Strings or both are Buffers + * Note: Code below takes advantage of common Buffer/String + * object fields. LocalOperand1 may have changed above. Use + * memcmp to handle nulls in buffers. + */ + Length0 = Operand0->Buffer.Length; + Length1 = LocalOperand1->Buffer.Length; + + /* Lexicographic compare: compare the data bytes */ + + Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer, + LocalOperand1->Buffer.Pointer, + (Length0 > Length1) ? Length1 : Length0); + + switch (Opcode) + { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + + /* Length and all bytes must be equal */ + + if ((Length0 == Length1) && + (Compare == 0)) + { + /* Length and all bytes match ==> TRUE */ + + LocalResult = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (Compare > 0) + { + LocalResult = TRUE; + goto Cleanup; /* TRUE */ + } + if (Compare < 0) + { + goto Cleanup; /* FALSE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (Length0 > Length1) + { + LocalResult = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (Compare > 0) + { + goto Cleanup; /* FALSE */ + } + if (Compare < 0) + { + LocalResult = TRUE; + goto Cleanup; /* TRUE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (Length0 < Length1) + { + LocalResult = TRUE; + } + break; + + default: + Status = AE_AML_INTERNAL; + break; + } + } + +Cleanup: + + /* New object was created if implicit conversion performed - delete */ + + if (LocalOperand1 != Operand1) + { + AcpiUtRemoveReference (LocalOperand1); + } + + /* Return the logical result and status */ + + *LogicalResult = LocalResult; + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exmutex.c b/source/components/executer/exmutex.c new file mode 100644 index 000000000000..4c702b8baa6d --- /dev/null +++ b/source/components/executer/exmutex.c @@ -0,0 +1,554 @@ + +/****************************************************************************** + * + * Module Name: exmutex - ASL Mutex Acquire/Release functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXMUTEX_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exmutex") + +/* Local prototypes */ + +static void +AcpiExLinkMutex ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_THREAD_STATE *Thread); + + +/******************************************************************************* + * + * FUNCTION: AcpiExUnlinkMutex + * + * PARAMETERS: ObjDesc - The mutex to be unlinked + * + * RETURN: None + * + * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list + * + ******************************************************************************/ + +void +AcpiExUnlinkMutex ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread; + + + if (!Thread) + { + return; + } + + /* Doubly linked list */ + + if (ObjDesc->Mutex.Next) + { + (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev; + } + + if (ObjDesc->Mutex.Prev) + { + (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next; + + /* + * Migrate the previous sync level associated with this mutex to + * the previous mutex on the list so that it may be preserved. + * This handles the case where several mutexes have been acquired + * at the same level, but are not released in opposite order. + */ + (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = + ObjDesc->Mutex.OriginalSyncLevel; + } + else + { + Thread->AcquiredMutexList = ObjDesc->Mutex.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExLinkMutex + * + * PARAMETERS: ObjDesc - The mutex to be linked + * Thread - Current executing thread object + * + * RETURN: None + * + * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk + * + ******************************************************************************/ + +static void +AcpiExLinkMutex ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_THREAD_STATE *Thread) +{ + ACPI_OPERAND_OBJECT *ListHead; + + + ListHead = Thread->AcquiredMutexList; + + /* This object will be the first object in the list */ + + ObjDesc->Mutex.Prev = NULL; + ObjDesc->Mutex.Next = ListHead; + + /* Update old first object to point back to this object */ + + if (ListHead) + { + ListHead->Mutex.Prev = ObjDesc; + } + + /* Update list head */ + + Thread->AcquiredMutexList = ObjDesc; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExAcquireMutexObject + * + * PARAMETERS: Timeout - Timeout in milliseconds + * ObjDesc - Mutex object + * ThreadId - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common + * path that supports multiple acquires by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From AcpiExAcquireMutex, via an AML Acquire() operator + * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the + * global lock + * 3) From the external interface, AcpiAcquireGlobalLock + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExAcquireMutexObject ( + UINT16 Timeout, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_THREAD_ID ThreadId) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc); + + + if (!ObjDesc) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Support for multiple acquires by the owning thread */ + + if (ObjDesc->Mutex.ThreadId == ThreadId) + { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + ObjDesc->Mutex.AcquisitionDepth++; + return_ACPI_STATUS (AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (ObjDesc == AcpiGbl_GlobalLockMutex) + { + Status = AcpiEvAcquireGlobalLock (Timeout); + } + else + { + Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, + Timeout); + } + + if (ACPI_FAILURE (Status)) + { + /* Includes failure from a timeout on TimeDesc */ + + return_ACPI_STATUS (Status); + } + + /* Acquired the mutex: update mutex object */ + + ObjDesc->Mutex.ThreadId = ThreadId; + ObjDesc->Mutex.AcquisitionDepth = 1; + ObjDesc->Mutex.OriginalSyncLevel = 0; + ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExAcquireMutex + * + * PARAMETERS: TimeDesc - Timeout integer + * ObjDesc - Mutex object + * WalkState - Current method execution state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExAcquireMutex ( + ACPI_OPERAND_OBJECT *TimeDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc); + + + if (!ObjDesc) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Must have a valid thread state struct */ + + if (!WalkState->Thread) + { + ACPI_ERROR ((AE_INFO, + "Cannot acquire Mutex [%4.4s], null thread info", + AcpiUtGetNodeName (ObjDesc->Mutex.Node))); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* + * Current sync level must be less than or equal to the sync level of the + * mutex. This mechanism provides some deadlock prevention + */ + if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel) + { + ACPI_ERROR ((AE_INFO, + "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)", + AcpiUtGetNodeName (ObjDesc->Mutex.Node), + WalkState->Thread->CurrentSyncLevel)); + return_ACPI_STATUS (AE_AML_MUTEX_ORDER); + } + + Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value, + ObjDesc, WalkState->Thread->ThreadId); + if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1) + { + /* Save Thread object, original/current sync levels */ + + ObjDesc->Mutex.OwnerThread = WalkState->Thread; + ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel; + WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel; + + /* Link the mutex to the current thread for force-unlock at method exit */ + + AcpiExLinkMutex (ObjDesc, WalkState->Thread); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReleaseMutexObject + * + * PARAMETERS: ObjDesc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * Provides a common path that supports multiple releases (after + * previous multiple acquires) by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From AcpiExReleaseMutex, via an AML Acquire() operator + * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the + * global lock + * 3) From the external interface, AcpiReleaseGlobalLock + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReleaseMutexObject ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExReleaseMutexObject); + + + if (ObjDesc->Mutex.AcquisitionDepth == 0) + { + return (AE_NOT_ACQUIRED); + } + + /* Match multiple Acquires with multiple Releases */ + + ObjDesc->Mutex.AcquisitionDepth--; + if (ObjDesc->Mutex.AcquisitionDepth != 0) + { + /* Just decrement the depth and return */ + + return_ACPI_STATUS (AE_OK); + } + + if (ObjDesc->Mutex.OwnerThread) + { + /* Unlink the mutex from the owner's list */ + + AcpiExUnlinkMutex (ObjDesc); + ObjDesc->Mutex.OwnerThread = NULL; + } + + /* Release the mutex, special case for Global Lock */ + + if (ObjDesc == AcpiGbl_GlobalLockMutex) + { + Status = AcpiEvReleaseGlobalLock (); + } + else + { + AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); + } + + /* Clear mutex info */ + + ObjDesc->Mutex.ThreadId = 0; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReleaseMutex + * + * PARAMETERS: ObjDesc - The object descriptor for this op + * WalkState - Current method execution state + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReleaseMutex ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + UINT8 PreviousSyncLevel; + ACPI_THREAD_STATE *OwnerThread; + + + ACPI_FUNCTION_TRACE (ExReleaseMutex); + + + if (!ObjDesc) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + OwnerThread = ObjDesc->Mutex.OwnerThread; + + /* The mutex must have been previously acquired in order to release it */ + + if (!OwnerThread) + { + ACPI_ERROR ((AE_INFO, + "Cannot release Mutex [%4.4s], not acquired", + AcpiUtGetNodeName (ObjDesc->Mutex.Node))); + return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); + } + + /* Must have a valid thread ID */ + + if (!WalkState->Thread) + { + ACPI_ERROR ((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + AcpiUtGetNodeName (ObjDesc->Mutex.Node))); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* + * The Mutex is owned, but this thread must be the owner. + * Special case for Global Lock, any thread can release + */ + if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && + (ObjDesc != AcpiGbl_GlobalLockMutex)) + { + ACPI_ERROR ((AE_INFO, + "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", + (UINT32) WalkState->Thread->ThreadId, + AcpiUtGetNodeName (ObjDesc->Mutex.Node), + (UINT32) OwnerThread->ThreadId)); + return_ACPI_STATUS (AE_AML_NOT_OWNER); + } + + /* + * The sync level of the mutex must be equal to the current sync level. In + * other words, the current level means that at least one mutex at that + * level is currently being held. Attempting to release a mutex of a + * different level can only mean that the mutex ordering rule is being + * violated. This behavior is clarified in ACPI 4.0 specification. + */ + if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel) + { + ACPI_ERROR ((AE_INFO, + "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u", + AcpiUtGetNodeName (ObjDesc->Mutex.Node), + ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel)); + return_ACPI_STATUS (AE_AML_MUTEX_ORDER); + } + + /* + * Get the previous SyncLevel from the head of the acquired mutex list. + * This handles the case where several mutexes at the same level have been + * acquired, but are not released in reverse order. + */ + PreviousSyncLevel = + OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; + + Status = AcpiExReleaseMutexObject (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (ObjDesc->Mutex.AcquisitionDepth == 0) + { + /* Restore the previous SyncLevel */ + + OwnerThread->CurrentSyncLevel = PreviousSyncLevel; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReleaseAllMutexes + * + * PARAMETERS: Thread - Current executing thread object + * + * RETURN: Status + * + * DESCRIPTION: Release all mutexes held by this thread + * + * NOTE: This function is called as the thread is exiting the interpreter. + * Mutexes are not released when an individual control method is exited, but + * only when the parent thread actually exits the interpreter. This allows one + * method to acquire a mutex, and a different method to release it, as long as + * this is performed underneath a single parent control method. + * + ******************************************************************************/ + +void +AcpiExReleaseAllMutexes ( + ACPI_THREAD_STATE *Thread) +{ + ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_ENTRY (); + + + /* Traverse the list of owned mutexes, releasing each one */ + + while (Next) + { + ObjDesc = Next; + Next = ObjDesc->Mutex.Next; + + ObjDesc->Mutex.Prev = NULL; + ObjDesc->Mutex.Next = NULL; + ObjDesc->Mutex.AcquisitionDepth = 0; + + /* Release the mutex, special case for Global Lock */ + + if (ObjDesc == AcpiGbl_GlobalLockMutex) + { + /* Ignore errors */ + + (void) AcpiEvReleaseGlobalLock (); + } + else + { + AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); + } + + /* Mark mutex unowned */ + + ObjDesc->Mutex.OwnerThread = NULL; + ObjDesc->Mutex.ThreadId = 0; + + /* Update Thread SyncLevel (Last mutex is the important one) */ + + Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; + } +} diff --git a/source/components/executer/exnames.c b/source/components/executer/exnames.c new file mode 100644 index 000000000000..c3cb6b0b4cad --- /dev/null +++ b/source/components/executer/exnames.c @@ -0,0 +1,488 @@ + +/****************************************************************************** + * + * Module Name: exnames - interpreter/scanner name load/execute + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXNAMES_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exnames") + +/* Local prototypes */ + +static char * +AcpiExAllocateNameString ( + UINT32 PrefixCount, + UINT32 NumNameSegs); + +static ACPI_STATUS +AcpiExNameSegment ( + UINT8 **InAmlAddress, + char *NameString); + + +/******************************************************************************* + * + * FUNCTION: AcpiExAllocateNameString + * + * PARAMETERS: PrefixCount - Count of parent levels. Special cases: + * (-1)==root, 0==none + * NumNameSegs - count of 4-character name segments + * + * RETURN: A pointer to the allocated string segment. This segment must + * be deleted by the caller. + * + * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name + * string is long enough, and set up prefix if any. + * + ******************************************************************************/ + +static char * +AcpiExAllocateNameString ( + UINT32 PrefixCount, + UINT32 NumNameSegs) +{ + char *TempPtr; + char *NameString; + UINT32 SizeNeeded; + + ACPI_FUNCTION_TRACE (ExAllocateNameString); + + + /* + * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix. + * Also, one byte for the null terminator. + * This may actually be somewhat longer than needed. + */ + if (PrefixCount == ACPI_UINT32_MAX) + { + /* Special case for root */ + + SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; + } + else + { + SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; + } + + /* + * Allocate a buffer for the name. + * This buffer must be deleted by the caller! + */ + NameString = ACPI_ALLOCATE (SizeNeeded); + if (!NameString) + { + ACPI_ERROR ((AE_INFO, + "Could not allocate size %u", SizeNeeded)); + return_PTR (NULL); + } + + TempPtr = NameString; + + /* Set up Root or Parent prefixes if needed */ + + if (PrefixCount == ACPI_UINT32_MAX) + { + *TempPtr++ = AML_ROOT_PREFIX; + } + else + { + while (PrefixCount--) + { + *TempPtr++ = AML_PARENT_PREFIX; + } + } + + + /* Set up Dual or Multi prefixes if needed */ + + if (NumNameSegs > 2) + { + /* Set up multi prefixes */ + + *TempPtr++ = AML_MULTI_NAME_PREFIX_OP; + *TempPtr++ = (char) NumNameSegs; + } + else if (2 == NumNameSegs) + { + /* Set up dual prefixes */ + + *TempPtr++ = AML_DUAL_NAME_PREFIX; + } + + /* + * Terminate string following prefixes. AcpiExNameSegment() will + * append the segment(s) + */ + *TempPtr = 0; + + return_PTR (NameString); +} + +/******************************************************************************* + * + * FUNCTION: AcpiExNameSegment + * + * PARAMETERS: InAmlAddress - Pointer to the name in the AML code + * NameString - Where to return the name. The name is appended + * to any existing string to form a namepath + * + * RETURN: Status + * + * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExNameSegment ( + UINT8 **InAmlAddress, + char *NameString) +{ + char *AmlAddress = (void *) *InAmlAddress; + ACPI_STATUS Status = AE_OK; + UINT32 Index; + char CharBuf[5]; + + + ACPI_FUNCTION_TRACE (ExNameSegment); + + + /* + * If first character is a digit, then we know that we aren't looking at a + * valid name segment + */ + CharBuf[0] = *AmlAddress; + + if ('0' <= CharBuf[0] && CharBuf[0] <= '9') + { + ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0])); + return_ACPI_STATUS (AE_CTRL_PENDING); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); + + for (Index = 0; + (Index < ACPI_NAME_SIZE) && (AcpiUtValidAcpiChar (*AmlAddress, 0)); + Index++) + { + CharBuf[Index] = *AmlAddress++; + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index])); + } + + + /* Valid name segment */ + + if (Index == 4) + { + /* Found 4 valid characters */ + + CharBuf[4] = '\0'; + + if (NameString) + { + ACPI_STRCAT (NameString, CharBuf); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Appended to - %s\n", NameString)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "No Name string - %s\n", CharBuf)); + } + } + else if (Index == 0) + { + /* + * First character was not a valid name character, + * so we are looking at something other than a name. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Leading character is not alpha: %02Xh (not a name)\n", + CharBuf[0])); + Status = AE_CTRL_PENDING; + } + else + { + /* + * Segment started with one or more valid characters, but fewer than + * the required 4 + */ + Status = AE_AML_BAD_NAME; + ACPI_ERROR ((AE_INFO, + "Bad character 0x%02x in name, at %p", + *AmlAddress, AmlAddress)); + } + + *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExGetNameString + * + * PARAMETERS: DataType - Object type to be associated with this + * name + * InAmlAddress - Pointer to the namestring in the AML code + * OutNameString - Where the namestring is returned + * OutNameLength - Length of the returned string + * + * RETURN: Status, namestring and length + * + * DESCRIPTION: Extract a full namepath from the AML byte stream, + * including any prefixes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExGetNameString ( + ACPI_OBJECT_TYPE DataType, + UINT8 *InAmlAddress, + char **OutNameString, + UINT32 *OutNameLength) +{ + ACPI_STATUS Status = AE_OK; + UINT8 *AmlAddress = InAmlAddress; + char *NameString = NULL; + UINT32 NumSegments; + UINT32 PrefixCount = 0; + BOOLEAN HasPrefix = FALSE; + + + ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress); + + + if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType || + ACPI_TYPE_LOCAL_BANK_FIELD == DataType || + ACPI_TYPE_LOCAL_INDEX_FIELD == DataType) + { + /* Disallow prefixes for types associated with FieldUnit names */ + + NameString = AcpiExAllocateNameString (0, 1); + if (!NameString) + { + Status = AE_NO_MEMORY; + } + else + { + Status = AcpiExNameSegment (&AmlAddress, NameString); + } + } + else + { + /* + * DataType is not a field name. + * Examine first character of name for root or parent prefix operators + */ + switch (*AmlAddress) + { + case AML_ROOT_PREFIX: + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n", + AmlAddress)); + + /* + * Remember that we have a RootPrefix -- + * see comment in AcpiExAllocateNameString() + */ + AmlAddress++; + PrefixCount = ACPI_UINT32_MAX; + HasPrefix = TRUE; + break; + + + case AML_PARENT_PREFIX: + + /* Increment past possibly multiple parent prefixes */ + + do + { + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n", + AmlAddress)); + + AmlAddress++; + PrefixCount++; + + } while (*AmlAddress == AML_PARENT_PREFIX); + + HasPrefix = TRUE; + break; + + + default: + + /* Not a prefix character */ + + break; + } + + /* Examine first character of name for name segment prefix operator */ + + switch (*AmlAddress) + { + case AML_DUAL_NAME_PREFIX: + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n", + AmlAddress)); + + AmlAddress++; + NameString = AcpiExAllocateNameString (PrefixCount, 2); + if (!NameString) + { + Status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + + HasPrefix = TRUE; + + Status = AcpiExNameSegment (&AmlAddress, NameString); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiExNameSegment (&AmlAddress, NameString); + } + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n", + AmlAddress)); + + /* Fetch count of segments remaining in name path */ + + AmlAddress++; + NumSegments = *AmlAddress; + + NameString = AcpiExAllocateNameString (PrefixCount, NumSegments); + if (!NameString) + { + Status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + + AmlAddress++; + HasPrefix = TRUE; + + while (NumSegments && + (Status = AcpiExNameSegment (&AmlAddress, NameString)) == + AE_OK) + { + NumSegments--; + } + + break; + + + case 0: + + /* NullName valid as of 8-12-98 ASL/AML Grammar Update */ + + if (PrefixCount == ACPI_UINT32_MAX) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "NameSeg is \"\\\" followed by NULL\n")); + } + + /* Consume the NULL byte */ + + AmlAddress++; + NameString = AcpiExAllocateNameString (PrefixCount, 0); + if (!NameString) + { + Status = AE_NO_MEMORY; + break; + } + + break; + + + default: + + /* Name segment string */ + + NameString = AcpiExAllocateNameString (PrefixCount, 1); + if (!NameString) + { + Status = AE_NO_MEMORY; + break; + } + + Status = AcpiExNameSegment (&AmlAddress, NameString); + break; + } + } + + if (AE_CTRL_PENDING == Status && HasPrefix) + { + /* Ran out of segments after processing a prefix */ + + ACPI_ERROR ((AE_INFO, + "Malformed Name at %p", NameString)); + Status = AE_AML_BAD_NAME; + } + + if (ACPI_FAILURE (Status)) + { + if (NameString) + { + ACPI_FREE (NameString); + } + return_ACPI_STATUS (Status); + } + + *OutNameString = NameString; + *OutNameLength = (UINT32) (AmlAddress - InAmlAddress); + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exoparg1.c b/source/components/executer/exoparg1.c new file mode 100644 index 000000000000..9a6cd9fcab75 --- /dev/null +++ b/source/components/executer/exoparg1.c @@ -0,0 +1,1111 @@ + +/****************************************************************************** + * + * Module Name: exoparg1 - AML execution - opcodes with 1 argument + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXOPARG1_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exoparg1") + + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (0 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_0A_0T_1R + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute operator with no operands, one return value + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_0A_0T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the AML opcode */ + + switch (WalkState->Opcode) + { + case AML_TIMER_OP: /* Timer () */ + + /* Create a return object of type Integer */ + + ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ()); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + break; + + default: /* Unknown opcode */ + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + break; + } + +Cleanup: + + /* Delete return object on error */ + + if ((ACPI_FAILURE (Status)) || WalkState->ResultObj) + { + AcpiUtRemoveReference (ReturnDesc); + WalkState->ResultObj = NULL; + } + else + { + /* Save the return value */ + + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_1A_0T_0R + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on + * object stack + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_1A_0T_0R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the AML opcode */ + + switch (WalkState->Opcode) + { + case AML_RELEASE_OP: /* Release (MutexObject) */ + + Status = AcpiExReleaseMutex (Operand[0], WalkState); + break; + + + case AML_RESET_OP: /* Reset (EventObject) */ + + Status = AcpiExSystemResetEvent (Operand[0]); + break; + + + case AML_SIGNAL_OP: /* Signal (EventObject) */ + + Status = AcpiExSystemSignalEvent (Operand[0]); + break; + + + case AML_SLEEP_OP: /* Sleep (MsecTime) */ + + Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value); + break; + + + case AML_STALL_OP: /* Stall (UsecTime) */ + + Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value); + break; + + + case AML_UNLOAD_OP: /* Unload (Handle) */ + + Status = AcpiExUnloadTable (Operand[0]); + break; + + + default: /* Unknown opcode */ + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_1A_1T_0R + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, one target, and no + * return value. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_1A_1T_0R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the AML opcode */ + + switch (WalkState->Opcode) + { + case AML_LOAD_OP: + + Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); + break; + + default: /* Unknown opcode */ + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + +Cleanup: + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_1A_1T_1R + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, one target, and a + * return value. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_1A_1T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; + UINT32 Temp32; + UINT32 i; + UINT64 PowerOfTen; + UINT64 Digit; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the AML opcode */ + + switch (WalkState->Opcode) + { + case AML_BIT_NOT_OP: + case AML_FIND_SET_LEFT_BIT_OP: + case AML_FIND_SET_RIGHT_BIT_OP: + case AML_FROM_BCD_OP: + case AML_TO_BCD_OP: + case AML_COND_REF_OF_OP: + + /* Create a return object of type Integer for these opcodes */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + switch (WalkState->Opcode) + { + case AML_BIT_NOT_OP: /* Not (Operand, Result) */ + + ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value; + break; + + + case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */ + + ReturnDesc->Integer.Value = Operand[0]->Integer.Value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (Temp32 = 0; ReturnDesc->Integer.Value && + Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) + { + ReturnDesc->Integer.Value >>= 1; + } + + ReturnDesc->Integer.Value = Temp32; + break; + + + case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */ + + ReturnDesc->Integer.Value = Operand[0]->Integer.Value; + + /* + * The Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (Temp32 = 0; ReturnDesc->Integer.Value && + Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) + { + ReturnDesc->Integer.Value <<= 1; + } + + /* Since the bit position is one-based, subtract from 33 (65) */ + + ReturnDesc->Integer.Value = + Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32; + break; + + + case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ + + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD characters + * (if table is 32-bit, integer can hold 8 BCD characters) + * Convert each 4-bit BCD value + */ + PowerOfTen = 1; + ReturnDesc->Integer.Value = 0; + Digit = Operand[0]->Integer.Value; + + /* Convert each BCD digit (each is one nybble wide) */ + + for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) + { + /* Get the least significant 4-bit BCD digit */ + + Temp32 = ((UINT32) Digit) & 0xF; + + /* Check the range of the digit */ + + if (Temp32 > 9) + { + ACPI_ERROR ((AE_INFO, + "BCD digit too large (not decimal): 0x%X", + Temp32)); + + Status = AE_AML_NUMERIC_OVERFLOW; + goto Cleanup; + } + + /* Sum the digit into the result with the current power of 10 */ + + ReturnDesc->Integer.Value += + (((UINT64) Temp32) * PowerOfTen); + + /* Shift to next BCD digit */ + + Digit >>= 4; + + /* Next power of 10 */ + + PowerOfTen *= 10; + } + break; + + + case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ + + ReturnDesc->Integer.Value = 0; + Digit = Operand[0]->Integer.Value; + + /* Each BCD digit is one nybble wide */ + + for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) + { + (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32); + + /* + * Insert the BCD digit that resides in the + * remainder from above + */ + ReturnDesc->Integer.Value |= + (((UINT64) Temp32) << ACPI_MUL_4 (i)); + } + + /* Overflow if there is any data left in Digit */ + + if (Digit > 0) + { + ACPI_ERROR ((AE_INFO, + "Integer too large to convert to BCD: 0x%8.8X%8.8X", + ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value))); + Status = AE_AML_NUMERIC_OVERFLOW; + goto Cleanup; + } + break; + + + case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */ + + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode) + { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + ReturnDesc->Integer.Value = 0; + goto Cleanup; + } + + /* Get the object reference, store it, and remove our reference */ + + Status = AcpiExGetObjectReference (Operand[0], + &ReturnDesc2, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState); + AcpiUtRemoveReference (ReturnDesc2); + + /* The object exists in the namespace, return TRUE */ + + ReturnDesc->Integer.Value = ACPI_UINT64_MAX; + goto Cleanup; + + + default: + /* No other opcodes get here */ + break; + } + break; + + + case AML_STORE_OP: /* Store (Source, Target) */ + + /* + * A store operand is typically a number, string, buffer or lvalue + * Be careful about deleting the source object, + * since the object itself may have been stored. + */ + Status = AcpiExStore (Operand[0], Operand[1], WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* It is possible that the Store already produced a return object */ + + if (!WalkState->ResultObj) + { + /* + * Normally, we would remove a reference on the Operand[0] + * parameter; But since it is being used as the internal return + * object (meaning we would normally increment it), the two + * cancel out, and we simply don't do anything. + */ + WalkState->ResultObj = Operand[0]; + WalkState->Operands[0] = NULL; /* Prevent deletion */ + } + return_ACPI_STATUS (Status); + + + /* + * ACPI 2.0 Opcodes + */ + case AML_COPY_OP: /* Copy (Source, Target) */ + + Status = AcpiUtCopyIobjectToIobject (Operand[0], &ReturnDesc, + WalkState); + break; + + + case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */ + + Status = AcpiExConvertToString (Operand[0], &ReturnDesc, + ACPI_EXPLICIT_CONVERT_DECIMAL); + if (ReturnDesc == Operand[0]) + { + /* No conversion performed, add ref to handle return value */ + AcpiUtAddReference (ReturnDesc); + } + break; + + + case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */ + + Status = AcpiExConvertToString (Operand[0], &ReturnDesc, + ACPI_EXPLICIT_CONVERT_HEX); + if (ReturnDesc == Operand[0]) + { + /* No conversion performed, add ref to handle return value */ + AcpiUtAddReference (ReturnDesc); + } + break; + + + case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */ + + Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc); + if (ReturnDesc == Operand[0]) + { + /* No conversion performed, add ref to handle return value */ + AcpiUtAddReference (ReturnDesc); + } + break; + + + case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */ + + Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, + ACPI_ANY_BASE); + if (ReturnDesc == Operand[0]) + { + /* No conversion performed, add ref to handle return value */ + AcpiUtAddReference (ReturnDesc); + } + break; + + + case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */ + case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */ + + /* These are two obsolete opcodes */ + + ACPI_ERROR ((AE_INFO, + "%s is obsolete and not implemented", + AcpiPsGetOpcodeName (WalkState->Opcode))); + Status = AE_SUPPORT; + goto Cleanup; + + + default: /* Unknown opcode */ + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + if (ACPI_SUCCESS (Status)) + { + /* Store the return value computed above into the target object */ + + Status = AcpiExStore (ReturnDesc, Operand[1], WalkState); + } + + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + } + + /* Save return object on success */ + + else if (!WalkState->ResultObj) + { + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_1A_0T_1R + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, no target, and a return value + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_1A_0T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *TempDesc; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + ACPI_STATUS Status = AE_OK; + UINT32 Type; + UINT64 Value; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the AML opcode */ + + switch (WalkState->Opcode) + { + case AML_LNOT_OP: /* LNot (Operand) */ + + ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Set result to ONES (TRUE) if Value == 0. Note: + * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. + */ + if (!Operand[0]->Integer.Value) + { + ReturnDesc->Integer.Value = ACPI_UINT64_MAX; + } + break; + + + case AML_DECREMENT_OP: /* Decrement (Operand) */ + case AML_INCREMENT_OP: /* Increment (Operand) */ + + /* + * Create a new integer. Can't just get the base integer and + * increment it because it may be an Arg or Field. + */ + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Since we are expecting a Reference operand, it can be either a + * NS Node or an internal object. + */ + TempDesc = Operand[0]; + if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) + { + /* Internal reference object - prevent deletion */ + + AcpiUtAddReference (TempDesc); + } + + /* + * Convert the Reference operand to an Integer (This removes a + * reference on the Operand[0] object) + * + * NOTE: We use LNOT_OP here in order to force resolution of the + * reference operand to an actual integer. + */ + Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While resolving operands for [%s]", + AcpiPsGetOpcodeName (WalkState->Opcode))); + + goto Cleanup; + } + + /* + * TempDesc is now guaranteed to be an Integer object -- + * Perform the actual increment or decrement + */ + if (WalkState->Opcode == AML_INCREMENT_OP) + { + ReturnDesc->Integer.Value = TempDesc->Integer.Value +1; + } + else + { + ReturnDesc->Integer.Value = TempDesc->Integer.Value -1; + } + + /* Finished with this Integer object */ + + AcpiUtRemoveReference (TempDesc); + + /* + * Store the result back (indirectly) through the original + * Reference object + */ + Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); + break; + + + case AML_TYPE_OP: /* ObjectType (SourceObject) */ + + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. For example, we don't + * want to resolve a FieldUnit to its value, we want the actual + * FieldUnit object. + */ + + /* Get the type of the base object */ + + Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Allocate a descriptor to hold the type. */ + + ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + break; + + + case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ + + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. + */ + + /* Get the base object */ + + Status = AcpiExResolveMultiple (WalkState, + Operand[0], &Type, &TempDesc); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * The type of the base object must be integer, buffer, string, or + * package. All others are not supported. + * + * NOTE: Integer is not specifically supported by the ACPI spec, + * but is supported implicitly via implicit operand conversion. + * rather than bother with conversion, we just use the byte width + * global (4 or 8 bytes). + */ + switch (Type) + { + case ACPI_TYPE_INTEGER: + Value = AcpiGbl_IntegerByteWidth; + break; + + case ACPI_TYPE_STRING: + Value = TempDesc->String.Length; + break; + + case ACPI_TYPE_BUFFER: + + /* Buffer arguments may not be evaluated at this point */ + + Status = AcpiDsGetBufferArguments (TempDesc); + Value = TempDesc->Buffer.Length; + break; + + case ACPI_TYPE_PACKAGE: + + /* Package arguments may not be evaluated at this point */ + + Status = AcpiDsGetPackageArguments (TempDesc); + Value = TempDesc->Package.Count; + break; + + default: + ACPI_ERROR ((AE_INFO, + "Operand must be Buffer/Integer/String/Package - found type %s", + AcpiUtGetTypeName (Type))); + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * Now that we have the size of the object, create a result + * object to hold the value + */ + ReturnDesc = AcpiUtCreateIntegerObject (Value); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + break; + + + case AML_REF_OF_OP: /* RefOf (SourceObject) */ + + Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + break; + + + case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ + + /* Check for a method local or argument, or standalone String */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) + { + TempDesc = AcpiNsGetAttachedObject ( + (ACPI_NAMESPACE_NODE *) Operand[0]); + if (TempDesc && + ((TempDesc->Common.Type == ACPI_TYPE_STRING) || + (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) + { + Operand[0] = TempDesc; + AcpiUtAddReference (TempDesc); + } + else + { + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + } + else + { + switch ((Operand[0])->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * This is a DerefOf (LocalX | ArgX) + * + * Must resolve/dereference the local/arg reference first + */ + switch (Operand[0]->Reference.Class) + { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* Set Operand[0] to the value of the local/arg */ + + Status = AcpiDsMethodDataGetValue ( + Operand[0]->Reference.Class, + Operand[0]->Reference.Value, + WalkState, &TempDesc); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + AcpiUtRemoveReference (Operand[0]); + Operand[0] = TempDesc; + break; + + case ACPI_REFCLASS_REFOF: + + /* Get the object to which the reference refers */ + + TempDesc = Operand[0]->Reference.Object; + AcpiUtRemoveReference (Operand[0]); + Operand[0] = TempDesc; + break; + + default: + + /* Must be an Index op - handled below */ + break; + } + break; + + case ACPI_TYPE_STRING: + break; + + default: + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) + { + if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) + { + /* + * This is a DerefOf (String). The string is a reference + * to a named ACPI object. + * + * 1) Find the owning Node + * 2) Dereference the node to an actual object. Could be a + * Field, so we need to resolve the node to a value. + */ + Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node, + Operand[0]->String.Pointer, + ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR ( + ACPI_NAMESPACE_NODE, &ReturnDesc)); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Status = AcpiExResolveNodeToValue ( + ACPI_CAST_INDIRECT_PTR ( + ACPI_NAMESPACE_NODE, &ReturnDesc), + WalkState); + goto Cleanup; + } + } + + /* Operand[0] may have changed from the code above */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) + { + /* + * This is a DerefOf (ObjectReference) + * Get the actual object from the Node (This is the dereference). + * This case may only happen when a LocalX or ArgX is + * dereferenced above. + */ + ReturnDesc = AcpiNsGetAttachedObject ( + (ACPI_NAMESPACE_NODE *) Operand[0]); + AcpiUtAddReference (ReturnDesc); + } + else + { + /* + * This must be a reference object produced by either the + * Index() or RefOf() operator + */ + switch (Operand[0]->Reference.Class) + { + case ACPI_REFCLASS_INDEX: + + /* + * The target type for the Index operator must be + * either a Buffer or a Package + */ + switch (Operand[0]->Reference.TargetType) + { + case ACPI_TYPE_BUFFER_FIELD: + + TempDesc = Operand[0]->Reference.Object; + + /* + * Create a new object that contains one element of the + * buffer -- the element pointed to by the index. + * + * NOTE: index into a buffer is NOT a pointer to a + * sub-buffer of the main buffer, it is only a pointer to a + * single element (byte) of the buffer! + * + * Since we are returning the value of the buffer at the + * indexed location, we don't need to add an additional + * reference to the buffer itself. + */ + ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) + TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Return the referenced element of the package. We must + * add another reference to the referenced object, however. + */ + ReturnDesc = *(Operand[0]->Reference.Where); + if (ReturnDesc) + { + AcpiUtAddReference (ReturnDesc); + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown Index TargetType 0x%X in reference object %p", + Operand[0]->Reference.TargetType, Operand[0])); + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + break; + + + case ACPI_REFCLASS_REFOF: + + ReturnDesc = Operand[0]->Reference.Object; + + if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == + ACPI_DESC_TYPE_NAMED) + { + ReturnDesc = AcpiNsGetAttachedObject ( + (ACPI_NAMESPACE_NODE *) ReturnDesc); + } + + /* Add another reference to the object! */ + + AcpiUtAddReference (ReturnDesc); + break; + + + default: + ACPI_ERROR ((AE_INFO, + "Unknown class in reference(%p) - 0x%2.2X", + Operand[0], Operand[0]->Reference.Class)); + + Status = AE_TYPE; + goto Cleanup; + } + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + } + + /* Save return object on success */ + + else + { + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} + diff --git a/source/components/executer/exoparg2.c b/source/components/executer/exoparg2.c new file mode 100644 index 000000000000..b76da75c49d4 --- /dev/null +++ b/source/components/executer/exoparg2.c @@ -0,0 +1,642 @@ +/****************************************************************************** + * + * Module Name: exoparg2 - AML execution - opcodes with 2 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EXOPARG2_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exoparg2") + + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_2A_0T_0R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with two arguments, no target, and no return + * value. + * + * ALLOCATION: Deletes both operands + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_2A_0T_0R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_NAMESPACE_NODE *Node; + UINT32 Value; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Examine the opcode */ + + switch (WalkState->Opcode) + { + case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ + + /* The first operand is a namespace node */ + + Node = (ACPI_NAMESPACE_NODE *) Operand[0]; + + /* Second value is the notify value */ + + Value = (UINT32) Operand[1]->Integer.Value; + + /* Are notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + ACPI_ERROR ((AE_INFO, + "Unexpected notify object type [%s]", + AcpiUtGetTypeName (Node->Type))); + + Status = AE_AML_OPERAND_TYPE; + break; + } + + /* + * Dispatch the notify to the appropriate handler + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + Status = AcpiEvQueueNotifyRequest (Node, Value); + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_2A_2T_1R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets + * and one implicit return value. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_2A_2T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc1 = NULL; + ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Execute the opcode */ + + switch (WalkState->Opcode) + { + case AML_DIVIDE_OP: + + /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */ + + ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc1) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc2) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */ + + Status = AcpiUtDivide (Operand[0]->Integer.Value, + Operand[1]->Integer.Value, + &ReturnDesc1->Integer.Value, + &ReturnDesc2->Integer.Value); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + /* Store the results to the target reference operands */ + + Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + +Cleanup: + /* + * Since the remainder is not returned indirectly, remove a reference to + * it. Only the quotient is returned indirectly. + */ + AcpiUtRemoveReference (ReturnDesc2); + + if (ACPI_FAILURE (Status)) + { + /* Delete the return object */ + + AcpiUtRemoveReference (ReturnDesc1); + } + + /* Save return object (the remainder) on success */ + + else + { + WalkState->ResultObj = ReturnDesc1; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_2A_1T_1R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with two arguments, one target, and a return + * value. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_2A_1T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + UINT64 Index; + ACPI_STATUS Status = AE_OK; + ACPI_SIZE Length; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Execute the opcode */ + + if (WalkState->OpInfo->Flags & AML_MATH) + { + /* All simple math opcodes (add, etc.) */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode, + Operand[0]->Integer.Value, + Operand[1]->Integer.Value); + goto StoreResultToTarget; + } + + switch (WalkState->Opcode) + { + case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* ReturnDesc will contain the remainder */ + + Status = AcpiUtDivide (Operand[0]->Integer.Value, + Operand[1]->Integer.Value, + NULL, + &ReturnDesc->Integer.Value); + break; + + + case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ + + Status = AcpiExDoConcatenate (Operand[0], Operand[1], + &ReturnDesc, WalkState); + break; + + + case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */ + + /* + * Input object is guaranteed to be a buffer at this point (it may have + * been converted.) Copy the raw buffer data to a new object of + * type String. + */ + + /* + * Get the length of the new string. It is the smallest of: + * 1) Length of the input buffer + * 2) Max length as specified in the ToString operator + * 3) Length of input buffer up to a zero byte (null terminator) + * + * NOTE: A length of zero is ok, and will create a zero-length, null + * terminated string. + */ + Length = 0; + while ((Length < Operand[0]->Buffer.Length) && + (Length < Operand[1]->Integer.Value) && + (Operand[0]->Buffer.Pointer[Length])) + { + Length++; + } + + /* Allocate a new string object */ + + ReturnDesc = AcpiUtCreateStringObject (Length); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* + * Copy the raw buffer data with no transform. + * (NULL terminated already) + */ + ACPI_MEMCPY (ReturnDesc->String.Pointer, + Operand[0]->Buffer.Pointer, Length); + break; + + + case AML_CONCAT_RES_OP: + + /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */ + + Status = AcpiExConcatTemplate (Operand[0], Operand[1], + &ReturnDesc, WalkState); + break; + + + case AML_INDEX_OP: /* Index (Source Index Result) */ + + /* Create the internal return object */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Initialize the Index reference object */ + + Index = Operand[1]->Integer.Value; + ReturnDesc->Reference.Value = (UINT32) Index; + ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX; + + /* + * At this point, the Source operand is a String, Buffer, or Package. + * Verify that the index is within range. + */ + switch ((Operand[0])->Common.Type) + { + case ACPI_TYPE_STRING: + + if (Index >= Operand[0]->String.Length) + { + Status = AE_AML_STRING_LIMIT; + } + + ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_BUFFER: + + if (Index >= Operand[0]->Buffer.Length) + { + Status = AE_AML_BUFFER_LIMIT; + } + + ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_PACKAGE: + + if (Index >= Operand[0]->Package.Count) + { + Status = AE_AML_PACKAGE_LIMIT; + } + + ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; + ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index]; + break; + + default: + + Status = AE_AML_INTERNAL; + goto Cleanup; + } + + /* Failure means that the Index was beyond the end of the object */ + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Index (0x%8.8X%8.8X) is beyond end of object", + ACPI_FORMAT_UINT64 (Index))); + goto Cleanup; + } + + /* + * Save the target object and add a reference to it for the life + * of the index + */ + ReturnDesc->Reference.Object = Operand[0]; + AcpiUtAddReference (Operand[0]); + + /* Store the reference to the Target */ + + Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); + + /* Return the reference */ + + WalkState->ResultObj = ReturnDesc; + goto Cleanup; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + break; + } + + +StoreResultToTarget: + + if (ACPI_SUCCESS (Status)) + { + /* + * Store the result of the operation (which is now in ReturnDesc) into + * the Target descriptor. + */ + Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + if (!WalkState->ResultObj) + { + WalkState->ResultObj = ReturnDesc; + } + } + + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + WalkState->ResultObj = NULL; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_2A_0T_1R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_2A_0T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + ACPI_STATUS Status = AE_OK; + BOOLEAN LogicalResult = FALSE; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + /* Create the internal return object */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Execute the Opcode */ + + if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC) + { + /* LogicalOp (Operand0, Operand1) */ + + Status = AcpiExDoLogicalNumericOp (WalkState->Opcode, + Operand[0]->Integer.Value, Operand[1]->Integer.Value, + &LogicalResult); + goto StoreLogicalResult; + } + else if (WalkState->OpInfo->Flags & AML_LOGICAL) + { + /* LogicalOp (Operand0, Operand1) */ + + Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0], + Operand[1], &LogicalResult); + goto StoreLogicalResult; + } + + switch (WalkState->Opcode) + { + case AML_ACQUIRE_OP: /* Acquire (MutexObject, Timeout) */ + + Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState); + if (Status == AE_TIME) + { + LogicalResult = TRUE; /* TRUE = Acquire timed out */ + Status = AE_OK; + } + break; + + + case AML_WAIT_OP: /* Wait (EventObject, Timeout) */ + + Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]); + if (Status == AE_TIME) + { + LogicalResult = TRUE; /* TRUE, Wait timed out */ + Status = AE_OK; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + +StoreLogicalResult: + /* + * Set return value to according to LogicalResult. logical TRUE (all ones) + * Default is FALSE (zero) + */ + if (LogicalResult) + { + ReturnDesc->Integer.Value = ACPI_UINT64_MAX; + } + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + } + + /* Save return object on success */ + + else + { + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exoparg3.c b/source/components/executer/exoparg3.c new file mode 100644 index 000000000000..0edac68e60ab --- /dev/null +++ b/source/components/executer/exoparg3.c @@ -0,0 +1,304 @@ + +/****************************************************************************** + * + * Module Name: exoparg3 - AML execution - opcodes with 3 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXOPARG3_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acparser.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exoparg3") + + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_3A_0T_0R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute Triadic operator (3 operands) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_3A_0T_0R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_SIGNAL_FATAL_INFO *Fatal; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_0T_0R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + switch (WalkState->Opcode) + { + case AML_FATAL_OP: /* Fatal (FatalType FatalCode FatalArg) */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + (UINT32) Operand[0]->Integer.Value, + (UINT32) Operand[1]->Integer.Value, + (UINT32) Operand[2]->Integer.Value)); + + Fatal = ACPI_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO)); + if (Fatal) + { + Fatal->Type = (UINT32) Operand[0]->Integer.Value; + Fatal->Code = (UINT32) Operand[1]->Integer.Value; + Fatal->Argument = (UINT32) Operand[2]->Integer.Value; + } + + /* Always signal the OS! */ + + Status = AcpiOsSignal (ACPI_SIGNAL_FATAL, Fatal); + + /* Might return while OS is shutting down, just continue */ + + ACPI_FREE (Fatal); + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + +Cleanup: + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_3A_1T_1R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute Triadic operator (3 operands) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_3A_1T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + char *Buffer = NULL; + ACPI_STATUS Status = AE_OK; + UINT64 Index; + ACPI_SIZE Length; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_1T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + switch (WalkState->Opcode) + { + case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ + + /* + * Create the return object. The Source operand is guaranteed to be + * either a String or a Buffer, so just use its type. + */ + ReturnDesc = AcpiUtCreateInternalObject ( + (Operand[0])->Common.Type); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Get the Integer values from the objects */ + + Index = Operand[1]->Integer.Value; + Length = (ACPI_SIZE) Operand[2]->Integer.Value; + + /* + * If the index is beyond the length of the String/Buffer, or if the + * requested length is zero, return a zero-length String/Buffer + */ + if (Index >= Operand[0]->String.Length) + { + Length = 0; + } + + /* Truncate request if larger than the actual String/Buffer */ + + else if ((Index + Length) > Operand[0]->String.Length) + { + Length = (ACPI_SIZE) Operand[0]->String.Length - + (ACPI_SIZE) Index; + } + + /* Strings always have a sub-pointer, not so for buffers */ + + switch ((Operand[0])->Common.Type) + { + case ACPI_TYPE_STRING: + + /* Always allocate a new buffer for the String */ + + Buffer = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1); + if (!Buffer) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + break; + + case ACPI_TYPE_BUFFER: + + /* If the requested length is zero, don't allocate a buffer */ + + if (Length > 0) + { + /* Allocate a new buffer for the Buffer */ + + Buffer = ACPI_ALLOCATE_ZEROED (Length); + if (!Buffer) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + } + break; + + default: /* Should not happen */ + + Status = AE_AML_OPERAND_TYPE; + goto Cleanup; + } + + if (Buffer) + { + /* We have a buffer, copy the portion requested */ + + ACPI_MEMCPY (Buffer, Operand[0]->String.Pointer + Index, + Length); + } + + /* Set the length of the new String/Buffer */ + + ReturnDesc->String.Pointer = Buffer; + ReturnDesc->String.Length = (UINT32) Length; + + /* Mark buffer initialized */ + + ReturnDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + /* Store the result in the target */ + + Status = AcpiExStore (ReturnDesc, Operand[3], WalkState); + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status) || WalkState->ResultObj) + { + AcpiUtRemoveReference (ReturnDesc); + WalkState->ResultObj = NULL; + } + + /* Set the return object and exit */ + + else + { + WalkState->ResultObj = ReturnDesc; + } + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exoparg6.c b/source/components/executer/exoparg6.c new file mode 100644 index 000000000000..bfc6585301f6 --- /dev/null +++ b/source/components/executer/exoparg6.c @@ -0,0 +1,365 @@ + +/****************************************************************************** + * + * Module Name: exoparg6 - AML execution - opcodes with 6 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXOPARG6_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acparser.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exoparg6") + + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ + +/* Local prototypes */ + +static BOOLEAN +AcpiExDoMatch ( + UINT32 MatchOp, + ACPI_OPERAND_OBJECT *PackageObj, + ACPI_OPERAND_OBJECT *MatchObj); + + +/******************************************************************************* + * + * FUNCTION: AcpiExDoMatch + * + * PARAMETERS: MatchOp - The AML match operand + * PackageObj - Object from the target package + * MatchObj - Object to be matched + * + * RETURN: TRUE if the match is successful, FALSE otherwise + * + * DESCRIPTION: Implements the low-level match for the ASL Match operator. + * Package elements will be implicitly converted to the type of + * the match object (Integer/Buffer/String). + * + ******************************************************************************/ + +static BOOLEAN +AcpiExDoMatch ( + UINT32 MatchOp, + ACPI_OPERAND_OBJECT *PackageObj, + ACPI_OPERAND_OBJECT *MatchObj) +{ + BOOLEAN LogicalResult = TRUE; + ACPI_STATUS Status; + + + /* + * Note: Since the PackageObj/MatchObj ordering is opposite to that of + * the standard logical operators, we have to reverse them when we call + * DoLogicalOp in order to make the implicit conversion rules work + * correctly. However, this means we have to flip the entire equation + * also. A bit ugly perhaps, but overall, better than fussing the + * parameters around at runtime, over and over again. + * + * Below, P[i] refers to the package element, M refers to the Match object. + */ + switch (MatchOp) + { + case MATCH_MTR: + + /* Always true */ + + break; + + case MATCH_MEQ: + + /* + * True if equal: (P[i] == M) + * Change to: (M == P[i]) + */ + Status = AcpiExDoLogicalOp (AML_LEQUAL_OP, MatchObj, PackageObj, + &LogicalResult); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + break; + + case MATCH_MLE: + + /* + * True if less than or equal: (P[i] <= M) (P[i] NotGreater than M) + * Change to: (M >= P[i]) (M NotLess than P[i]) + */ + Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj, + &LogicalResult); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + LogicalResult = (BOOLEAN) !LogicalResult; + break; + + case MATCH_MLT: + + /* + * True if less than: (P[i] < M) + * Change to: (M > P[i]) + */ + Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj, + &LogicalResult); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + break; + + case MATCH_MGE: + + /* + * True if greater than or equal: (P[i] >= M) (P[i] NotLess than M) + * Change to: (M <= P[i]) (M NotGreater than P[i]) + */ + Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj, + &LogicalResult); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + LogicalResult = (BOOLEAN)!LogicalResult; + break; + + case MATCH_MGT: + + /* + * True if greater than: (P[i] > M) + * Change to: (M < P[i]) + */ + Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj, + &LogicalResult); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + break; + + default: + + /* Undefined */ + + return (FALSE); + } + + return LogicalResult; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExOpcode_6A_0T_1R + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExOpcode_6A_0T_1R ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; + ACPI_OPERAND_OBJECT *ReturnDesc = NULL; + ACPI_STATUS Status = AE_OK; + UINT64 Index; + ACPI_OPERAND_OBJECT *ThisElement; + + + ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + switch (WalkState->Opcode) + { + case AML_MATCH_OP: + /* + * Match (SearchPkg[0], MatchOp1[1], MatchObj1[2], + * MatchOp2[3], MatchObj2[4], StartIndex[5]) + */ + + /* Validate both Match Term Operators (MTR, MEQ, etc.) */ + + if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) || + (Operand[3]->Integer.Value > MAX_MATCH_OPERATOR)) + { + ACPI_ERROR ((AE_INFO, "Match operator out of range")); + Status = AE_AML_OPERAND_VALUE; + goto Cleanup; + } + + /* Get the package StartIndex, validate against the package length */ + + Index = Operand[5]->Integer.Value; + if (Index >= Operand[0]->Package.Count) + { + ACPI_ERROR ((AE_INFO, + "Index (0x%8.8X%8.8X) beyond package end (0x%X)", + ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count)); + Status = AE_AML_PACKAGE_LIMIT; + goto Cleanup; + } + + /* Create an integer for the return value */ + /* Default return value is ACPI_UINT64_MAX if no match found */ + + ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + + } + + /* + * Examine each element until a match is found. Both match conditions + * must be satisfied for a match to occur. Within the loop, + * "continue" signifies that the current element does not match + * and the next should be examined. + * + * Upon finding a match, the loop will terminate via "break" at + * the bottom. If it terminates "normally", MatchValue will be + * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no + * match was found. + */ + for ( ; Index < Operand[0]->Package.Count; Index++) + { + /* Get the current package element */ + + ThisElement = Operand[0]->Package.Elements[Index]; + + /* Treat any uninitialized (NULL) elements as non-matching */ + + if (!ThisElement) + { + continue; + } + + /* + * Both match conditions must be satisfied. Execution of a continue + * (proceed to next iteration of enclosing for loop) signifies a + * non-match. + */ + if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value, + ThisElement, Operand[2])) + { + continue; + } + + if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value, + ThisElement, Operand[4])) + { + continue; + } + + /* Match found: Index is the return value */ + + ReturnDesc->Integer.Value = Index; + break; + } + break; + + + case AML_LOAD_TABLE_OP: + + Status = AcpiExLoadTableOp (WalkState, &ReturnDesc); + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + Status = AE_AML_BAD_OPCODE; + goto Cleanup; + } + + +Cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + } + + /* Save return object on success */ + + else + { + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} diff --git a/source/components/executer/exprep.c b/source/components/executer/exprep.c new file mode 100644 index 000000000000..9ec78275bd6f --- /dev/null +++ b/source/components/executer/exprep.c @@ -0,0 +1,648 @@ + +/****************************************************************************** + * + * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXPREP_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exprep") + +/* Local prototypes */ + +static UINT32 +AcpiExDecodeFieldAccess ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 FieldFlags, + UINT32 *ReturnByteAlignment); + + +#ifdef ACPI_UNDER_DEVELOPMENT + +static UINT32 +AcpiExGenerateAccess ( + UINT32 FieldBitOffset, + UINT32 FieldBitLength, + UINT32 RegionLength); + +/******************************************************************************* + * + * FUNCTION: AcpiExGenerateAccess + * + * PARAMETERS: FieldBitOffset - Start of field within parent region/buffer + * FieldBitLength - Length of field in bits + * RegionLength - Length of parent in bytes + * + * RETURN: Field granularity (8, 16, 32 or 64) and + * ByteAlignment (1, 2, 3, or 4) + * + * DESCRIPTION: Generate an optimal access width for fields defined with the + * AnyAcc keyword. + * + * NOTE: Need to have the RegionLength in order to check for boundary + * conditions (end-of-region). However, the RegionLength is a deferred + * operation. Therefore, to complete this implementation, the generation + * of this access width must be deferred until the region length has + * been evaluated. + * + ******************************************************************************/ + +static UINT32 +AcpiExGenerateAccess ( + UINT32 FieldBitOffset, + UINT32 FieldBitLength, + UINT32 RegionLength) +{ + UINT32 FieldByteLength; + UINT32 FieldByteOffset; + UINT32 FieldByteEndOffset; + UINT32 AccessByteWidth; + UINT32 FieldStartOffset; + UINT32 FieldEndOffset; + UINT32 MinimumAccessWidth = 0xFFFFFFFF; + UINT32 MinimumAccesses = 0xFFFFFFFF; + UINT32 Accesses; + + + ACPI_FUNCTION_TRACE (ExGenerateAccess); + + + /* Round Field start offset and length to "minimal" byte boundaries */ + + FieldByteOffset = ACPI_DIV_8 (ACPI_ROUND_DOWN (FieldBitOffset, 8)); + FieldByteEndOffset = ACPI_DIV_8 (ACPI_ROUND_UP (FieldBitLength + + FieldBitOffset, 8)); + FieldByteLength = FieldByteEndOffset - FieldByteOffset; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Bit length %u, Bit offset %u\n", + FieldBitLength, FieldBitOffset)); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Byte Length %u, Byte Offset %u, End Offset %u\n", + FieldByteLength, FieldByteOffset, FieldByteEndOffset)); + + /* + * Iterative search for the maximum access width that is both aligned + * and does not go beyond the end of the region + * + * Start at ByteAcc and work upwards to QwordAcc max. (1,2,4,8 bytes) + */ + for (AccessByteWidth = 1; AccessByteWidth <= 8; AccessByteWidth <<= 1) + { + /* + * 1) Round end offset up to next access boundary and make sure that + * this does not go beyond the end of the parent region. + * 2) When the Access width is greater than the FieldByteLength, we + * are done. (This does not optimize for the perfectly aligned + * case yet). + */ + if (ACPI_ROUND_UP (FieldByteEndOffset, AccessByteWidth) <= RegionLength) + { + FieldStartOffset = + ACPI_ROUND_DOWN (FieldByteOffset, AccessByteWidth) / + AccessByteWidth; + + FieldEndOffset = + ACPI_ROUND_UP ((FieldByteLength + FieldByteOffset), + AccessByteWidth) / AccessByteWidth; + + Accesses = FieldEndOffset - FieldStartOffset; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "AccessWidth %u end is within region\n", AccessByteWidth)); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field Start %u, Field End %u -- requires %u accesses\n", + FieldStartOffset, FieldEndOffset, Accesses)); + + /* Single access is optimal */ + + if (Accesses <= 1) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Entire field can be accessed with one operation of size %u\n", + AccessByteWidth)); + return_VALUE (AccessByteWidth); + } + + /* + * Fits in the region, but requires more than one read/write. + * try the next wider access on next iteration + */ + if (Accesses < MinimumAccesses) + { + MinimumAccesses = Accesses; + MinimumAccessWidth = AccessByteWidth; + } + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "AccessWidth %u end is NOT within region\n", AccessByteWidth)); + if (AccessByteWidth == 1) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field goes beyond end-of-region!\n")); + + /* Field does not fit in the region at all */ + + return_VALUE (0); + } + + /* + * This width goes beyond the end-of-region, back off to + * previous access + */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Backing off to previous optimal access width of %u\n", + MinimumAccessWidth)); + return_VALUE (MinimumAccessWidth); + } + } + + /* + * Could not read/write field with one operation, + * just use max access width + */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Cannot access field in one operation, using width 8\n")); + return_VALUE (8); +} +#endif /* ACPI_UNDER_DEVELOPMENT */ + + +/******************************************************************************* + * + * FUNCTION: AcpiExDecodeFieldAccess + * + * PARAMETERS: ObjDesc - Field object + * FieldFlags - Encoded fieldflags (contains access bits) + * ReturnByteAlignment - Where the byte alignment is returned + * + * RETURN: Field granularity (8, 16, 32 or 64) and + * ByteAlignment (1, 2, 3, or 4) + * + * DESCRIPTION: Decode the AccessType bits of a field definition. + * + ******************************************************************************/ + +static UINT32 +AcpiExDecodeFieldAccess ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 FieldFlags, + UINT32 *ReturnByteAlignment) +{ + UINT32 Access; + UINT32 ByteAlignment; + UINT32 BitLength; + + + ACPI_FUNCTION_TRACE (ExDecodeFieldAccess); + + + Access = (FieldFlags & AML_FIELD_ACCESS_TYPE_MASK); + + switch (Access) + { + case AML_FIELD_ACCESS_ANY: + +#ifdef ACPI_UNDER_DEVELOPMENT + ByteAlignment = + AcpiExGenerateAccess (ObjDesc->CommonField.StartFieldBitOffset, + ObjDesc->CommonField.BitLength, + 0xFFFFFFFF /* Temp until we pass RegionLength as parameter */); + BitLength = ByteAlignment * 8; +#endif + + ByteAlignment = 1; + BitLength = 8; + break; + + case AML_FIELD_ACCESS_BYTE: + case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ + ByteAlignment = 1; + BitLength = 8; + break; + + case AML_FIELD_ACCESS_WORD: + ByteAlignment = 2; + BitLength = 16; + break; + + case AML_FIELD_ACCESS_DWORD: + ByteAlignment = 4; + BitLength = 32; + break; + + case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + ByteAlignment = 8; + BitLength = 64; + break; + + default: + /* Invalid field access type */ + + ACPI_ERROR ((AE_INFO, + "Unknown field access type 0x%X", + Access)); + return_UINT32 (0); + } + + if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) + { + /* + * BufferField access can be on any byte boundary, so the + * ByteAlignment is always 1 byte -- regardless of any ByteAlignment + * implied by the field access type. + */ + ByteAlignment = 1; + } + + *ReturnByteAlignment = ByteAlignment; + return_UINT32 (BitLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExPrepCommonFieldObject + * + * PARAMETERS: ObjDesc - The field object + * FieldFlags - Access, LockRule, and UpdateRule. + * The format of a FieldFlag is described + * in the ACPI specification + * FieldAttribute - Special attributes (not used) + * FieldBitPosition - Field start position + * FieldBitLength - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Initialize the areas of the field object that are common + * to the various types of fields. Note: This is very "sensitive" + * code because we are solving the general case for field + * alignment. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExPrepCommonFieldObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 FieldFlags, + UINT8 FieldAttribute, + UINT32 FieldBitPosition, + UINT32 FieldBitLength) +{ + UINT32 AccessBitWidth; + UINT32 ByteAlignment; + UINT32 NearestByteAddress; + + + ACPI_FUNCTION_TRACE (ExPrepCommonFieldObject); + + + /* + * Note: the structure being initialized is the + * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common + * area are initialized by this procedure. + */ + ObjDesc->CommonField.FieldFlags = FieldFlags; + ObjDesc->CommonField.Attribute = FieldAttribute; + ObjDesc->CommonField.BitLength = FieldBitLength; + + /* + * Decode the access type so we can compute offsets. The access type gives + * two pieces of information - the width of each field access and the + * necessary ByteAlignment (address granularity) of the access. + * + * For AnyAcc, the AccessBitWidth is the largest width that is both + * necessary and possible in an attempt to access the whole field in one + * I/O operation. However, for AnyAcc, the ByteAlignment is always one + * byte. + * + * For all Buffer Fields, the ByteAlignment is always one byte. + * + * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is + * the same (equivalent) as the ByteAlignment. + */ + AccessBitWidth = AcpiExDecodeFieldAccess (ObjDesc, FieldFlags, + &ByteAlignment); + if (!AccessBitWidth) + { + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */ + + ObjDesc->CommonField.AccessByteWidth = (UINT8) + ACPI_DIV_8 (AccessBitWidth); + + /* + * BaseByteOffset is the address of the start of the field within the + * region. It is the byte address of the first *datum* (field-width data + * unit) of the field. (i.e., the first datum that contains at least the + * first *bit* of the field.) + * + * Note: ByteAlignment is always either equal to the AccessBitWidth or 8 + * (Byte access), and it defines the addressing granularity of the parent + * region or buffer. + */ + NearestByteAddress = + ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition); + ObjDesc->CommonField.BaseByteOffset = (UINT32) + ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment); + + /* + * StartFieldBitOffset is the offset of the first bit of the field within + * a field datum. + */ + ObjDesc->CommonField.StartFieldBitOffset = (UINT8) + (FieldBitPosition - ACPI_MUL_8 (ObjDesc->CommonField.BaseByteOffset)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExPrepFieldValue + * + * PARAMETERS: Info - Contains all field creation info + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type DefField and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExPrepFieldValue ( + ACPI_CREATE_FIELD_INFO *Info) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *SecondDesc = NULL; + ACPI_STATUS Status; + UINT32 AccessByteWidth; + UINT32 Type; + + + ACPI_FUNCTION_TRACE (ExPrepFieldValue); + + + /* Parameter validation */ + + if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD) + { + if (!Info->RegionNode) + { + ACPI_ERROR ((AE_INFO, "Null RegionNode")); + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + Type = AcpiNsGetType (Info->RegionNode); + if (Type != ACPI_TYPE_REGION) + { + ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", + Type, AcpiUtGetTypeName (Type))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + } + + /* Allocate a new field object */ + + ObjDesc = AcpiUtCreateInternalObject (Info->FieldType); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize areas of the object that are common to all fields */ + + ObjDesc->CommonField.Node = Info->FieldNode; + Status = AcpiExPrepCommonFieldObject (ObjDesc, + Info->FieldFlags, Info->Attribute, + Info->FieldBitPosition, Info->FieldBitLength); + if (ACPI_FAILURE (Status)) + { + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (Status); + } + + /* Initialize areas of the object that are specific to the field type */ + + switch (Info->FieldType) + { + case ACPI_TYPE_LOCAL_REGION_FIELD: + + ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); + + /* Fields specific to GenericSerialBus fields */ + + ObjDesc->Field.AccessLength = Info->AccessLength; + + if (Info->ConnectionNode) + { + SecondDesc = Info->ConnectionNode->Object; + if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetBufferArguments (SecondDesc); + if (ACPI_FAILURE (Status)) + { + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (Status); + } + } + + ObjDesc->Field.ResourceBuffer = SecondDesc->Buffer.Pointer; + ObjDesc->Field.ResourceLength = (UINT16) SecondDesc->Buffer.Length; + } + else if (Info->ResourceBuffer) + { + ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer; + ObjDesc->Field.ResourceLength = Info->ResourceLength; + } + + /* Allow full data read from EC address space */ + + if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && + (ObjDesc->CommonField.BitLength > 8)) + { + AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->CommonField.BitLength); + + /* Maximum byte width supported is 255 */ + + if (AccessByteWidth < 256) + { + ObjDesc->CommonField.AccessByteWidth = (UINT8) AccessByteWidth; + } + } + + /* An additional reference for the container */ + + AcpiUtAddReference (ObjDesc->Field.RegionObj); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", + ObjDesc->Field.StartFieldBitOffset, ObjDesc->Field.BaseByteOffset, + ObjDesc->Field.AccessByteWidth, ObjDesc->Field.RegionObj)); + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ObjDesc->BankField.Value = Info->BankValue; + ObjDesc->BankField.RegionObj = + AcpiNsGetAttachedObject (Info->RegionNode); + ObjDesc->BankField.BankObj = + AcpiNsGetAttachedObject (Info->RegisterNode); + + /* An additional reference for the attached objects */ + + AcpiUtAddReference (ObjDesc->BankField.RegionObj); + AcpiUtAddReference (ObjDesc->BankField.BankObj); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", + ObjDesc->BankField.StartFieldBitOffset, + ObjDesc->BankField.BaseByteOffset, + ObjDesc->Field.AccessByteWidth, + ObjDesc->BankField.RegionObj, + ObjDesc->BankField.BankObj)); + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the BankValue + * operands must be evaluated. + */ + SecondDesc = ObjDesc->Common.NextObject; + SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, + Info->DataRegisterNode)->Named.Data; + SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, + Info->DataRegisterNode)->Named.Length; + + break; + + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* Get the Index and Data registers */ + + ObjDesc->IndexField.IndexObj = + AcpiNsGetAttachedObject (Info->RegisterNode); + ObjDesc->IndexField.DataObj = + AcpiNsGetAttachedObject (Info->DataRegisterNode); + + if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj) + { + ACPI_ERROR ((AE_INFO, "Null Index Object during field prep")); + AcpiUtDeleteObjectDesc (ObjDesc); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* An additional reference for the attached objects */ + + AcpiUtAddReference (ObjDesc->IndexField.DataObj); + AcpiUtAddReference (ObjDesc->IndexField.IndexObj); + + /* + * April 2006: Changed to match MS behavior + * + * The value written to the Index register is the byte offset of the + * target field in units of the granularity of the IndexField + * + * Previously, the value was calculated as an index in terms of the + * width of the Data register, as below: + * + * ObjDesc->IndexField.Value = (UINT32) + * (Info->FieldBitPosition / ACPI_MUL_8 ( + * ObjDesc->Field.AccessByteWidth)); + * + * February 2006: Tried value as a byte offset: + * ObjDesc->IndexField.Value = (UINT32) + * ACPI_DIV_8 (Info->FieldBitPosition); + */ + ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN ( + ACPI_DIV_8 (Info->FieldBitPosition), + ObjDesc->IndexField.AccessByteWidth); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", + ObjDesc->IndexField.StartFieldBitOffset, + ObjDesc->IndexField.BaseByteOffset, + ObjDesc->IndexField.Value, + ObjDesc->Field.AccessByteWidth, + ObjDesc->IndexField.IndexObj, + ObjDesc->IndexField.DataObj)); + break; + + default: + /* No other types should get here */ + break; + } + + /* + * Store the constructed descriptor (ObjDesc) into the parent Node, + * preserving the current type of that NamedObj. + */ + Status = AcpiNsAttachObject (Info->FieldNode, ObjDesc, + AcpiNsGetType (Info->FieldNode)); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", + Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/executer/exregion.c b/source/components/executer/exregion.c new file mode 100644 index 000000000000..8a40250794e7 --- /dev/null +++ b/source/components/executer/exregion.c @@ -0,0 +1,565 @@ + +/****************************************************************************** + * + * Module Name: exregion - ACPI default OpRegion (address space) handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __EXREGION_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exregion") + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemMemorySpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System Memory address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemMemorySpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_STATUS Status = AE_OK; + void *LogicalAddrPtr = NULL; + ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; + UINT32 Length; + ACPI_SIZE MapLength; + ACPI_SIZE PageBoundaryMapLength; +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED + UINT32 Remainder; +#endif + + + ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); + + + /* Validate and translate the bit width */ + + switch (BitWidth) + { + case 8: + Length = 1; + break; + + case 16: + Length = 2; + break; + + case 32: + Length = 4; + break; + + case 64: + Length = 8; + break; + + default: + ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u", + BitWidth)); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED + /* + * Hardware does not support non-aligned data transfers, we must verify + * the request. + */ + (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder); + if (Remainder != 0) + { + return_ACPI_STATUS (AE_AML_ALIGNMENT); + } +#endif + + /* + * Does the request fit into the cached memory mapping? + * Is 1) Address below the current mapping? OR + * 2) Address beyond the current mapping? + */ + if ((Address < MemInfo->MappedPhysicalAddress) || + (((UINT64) Address + Length) > + ((UINT64) + MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) + { + /* + * The request cannot be resolved by the current memory mapping; + * Delete the existing mapping and create a new one. + */ + if (MemInfo->MappedLength) + { + /* Valid mapping, delete it */ + + AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, + MemInfo->MappedLength); + } + + /* + * October 2009: Attempt to map from the requested address to the + * end of the region. However, we will never map more than one + * page, nor will we cross a page boundary. + */ + MapLength = (ACPI_SIZE) + ((MemInfo->Address + MemInfo->Length) - Address); + + /* + * If mapping the entire remaining portion of the region will cross + * a page boundary, just map up to the page boundary, do not cross. + * On some systems, crossing a page boundary while mapping regions + * can cause warnings if the pages have different attributes + * due to resource management. + * + * This has the added benefit of constraining a single mapping to + * one page, which is similar to the original code that used a 4k + * maximum window. + */ + PageBoundaryMapLength = + ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address; + if (PageBoundaryMapLength == 0) + { + PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE; + } + + if (MapLength > PageBoundaryMapLength) + { + MapLength = PageBoundaryMapLength; + } + + /* Create a new mapping starting at the address given */ + + MemInfo->MappedLogicalAddress = AcpiOsMapMemory ( + (ACPI_PHYSICAL_ADDRESS) Address, MapLength); + if (!MemInfo->MappedLogicalAddress) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X%8.8X, size %u", + ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) MapLength)); + MemInfo->MappedLength = 0; + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Save the physical address and mapping size */ + + MemInfo->MappedPhysicalAddress = Address; + MemInfo->MappedLength = MapLength; + } + + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + LogicalAddrPtr = MemInfo->MappedLogicalAddress + + ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", + BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address))); + + /* + * Perform the memory read or write + * + * Note: For machines that do not support non-aligned transfers, the target + * address was checked for alignment above. We do not attempt to break the + * transfer up into smaller (byte-size) chunks because the AML specifically + * asked for a transfer width that the hardware may require. + */ + switch (Function) + { + case ACPI_READ: + + *Value = 0; + switch (BitWidth) + { + case 8: + *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr); + break; + + case 16: + *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr); + break; + + case 32: + *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr); + break; + + case 64: + *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr); + break; + + default: + /* BitWidth was already validated */ + break; + } + break; + + case ACPI_WRITE: + + switch (BitWidth) + { + case 8: + ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value; + break; + + case 16: + ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value; + break; + + case 32: + ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value; + break; + + case 64: + ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value; + break; + + default: + /* BitWidth was already validated */ + break; + } + break; + + default: + Status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemIoSpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System IO address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemIoSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_STATUS Status = AE_OK; + UINT32 Value32; + + + ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", + BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address))); + + /* Decode the function parameter */ + + switch (Function) + { + case ACPI_READ: + + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address, + &Value32, BitWidth); + *Value = Value32; + break; + + case ACPI_WRITE: + + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address, + (UINT32) *Value, BitWidth); + break; + + default: + Status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExPciConfigSpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI Config address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExPciConfigSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PCI_ID *PciId; + UINT16 PciRegister; + + + ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler); + + + /* + * The arguments to AcpiOs(Read|Write)PciConfiguration are: + * + * PciSegment is the PCI bus segment range 0-31 + * PciBus is the PCI bus number range 0-255 + * PciDevice is the PCI device number range 0-31 + * PciFunction is the PCI device function number + * PciRegister is the Config space register range 0-255 bytes + * + * Value - input value for write, output address for read + * + */ + PciId = (ACPI_PCI_ID *) RegionContext; + PciRegister = (UINT16) (UINT32) Address; + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", + Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device, + PciId->Function, PciRegister)); + + switch (Function) + { + case ACPI_READ: + + *Value = 0; + Status = AcpiOsReadPciConfiguration (PciId, PciRegister, + Value, BitWidth); + break; + + case ACPI_WRITE: + + Status = AcpiOsWritePciConfiguration (PciId, PciRegister, + *Value, BitWidth); + break; + + default: + + Status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExCmosSpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the CMOS address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCmosSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExCmosSpaceHandler); + + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExPciBarSpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExPciBarSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler); + + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDataTableSpaceHandler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * BitWidth - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * HandlerContext - Pointer to Handler's context + * RegionContext - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the Data Table address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExDataTableSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler); + + + /* + * Perform the memory read or write. The BitWidth was already + * validated. + */ + switch (Function) + { + case ACPI_READ: + + ACPI_MEMCPY (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address), + ACPI_DIV_8 (BitWidth)); + break; + + case ACPI_WRITE: + + ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value), + ACPI_DIV_8 (BitWidth)); + break; + + default: + + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/executer/exresnte.c b/source/components/executer/exresnte.c new file mode 100644 index 000000000000..03962edf9705 --- /dev/null +++ b/source/components/executer/exresnte.c @@ -0,0 +1,302 @@ + +/****************************************************************************** + * + * Module Name: exresnte - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXRESNTE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exresnte") + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveNodeToValue + * + * PARAMETERS: ObjectPtr - Pointer to a location that contains + * a pointer to a NS node, and will receive a + * pointer to the resolved object. + * WalkState - Current state. Valid only if executing AML + * code. NULL if simply resolving an object + * + * RETURN: Status + * + * DESCRIPTION: Resolve a Namespace node to a valued object + * + * Note: for some of the data types, the pointer attached to the Node + * can be either a pointer to an actual internal object or a pointer into the + * AML stream itself. These types are currently: + * + * ACPI_TYPE_INTEGER + * ACPI_TYPE_STRING + * ACPI_TYPE_BUFFER + * ACPI_TYPE_MUTEX + * ACPI_TYPE_PACKAGE + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExResolveNodeToValue ( + ACPI_NAMESPACE_NODE **ObjectPtr, + ACPI_WALK_STATE *WalkState) + +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *SourceDesc; + ACPI_OPERAND_OBJECT *ObjDesc = NULL; + ACPI_NAMESPACE_NODE *Node; + ACPI_OBJECT_TYPE EntryType; + + + ACPI_FUNCTION_TRACE (ExResolveNodeToValue); + + + /* + * The stack pointer points to a ACPI_NAMESPACE_NODE (Node). Get the + * object that is attached to the Node. + */ + Node = *ObjectPtr; + SourceDesc = AcpiNsGetAttachedObject (Node); + EntryType = AcpiNsGetType ((ACPI_HANDLE) Node); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", + Node, SourceDesc, AcpiUtGetTypeName (EntryType))); + + if ((EntryType == ACPI_TYPE_LOCAL_ALIAS) || + (EntryType == ACPI_TYPE_LOCAL_METHOD_ALIAS)) + { + /* There is always exactly one level of indirection */ + + Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Node->Object); + SourceDesc = AcpiNsGetAttachedObject (Node); + EntryType = AcpiNsGetType ((ACPI_HANDLE) Node); + *ObjectPtr = Node; + } + + /* + * Several object types require no further processing: + * 1) Device/Thermal objects don't have a "real" subobject, return the Node + * 2) Method locals and arguments have a pseudo-Node + * 3) 10/2007: Added method type to assist with Package construction. + */ + if ((EntryType == ACPI_TYPE_DEVICE) || + (EntryType == ACPI_TYPE_THERMAL) || + (EntryType == ACPI_TYPE_METHOD) || + (Node->Flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) + { + return_ACPI_STATUS (AE_OK); + } + + if (!SourceDesc) + { + ACPI_ERROR ((AE_INFO, "No object attached to node %p", + Node)); + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + /* + * Action is based on the type of the Node, which indicates the type + * of the attached object or pointer + */ + switch (EntryType) + { + case ACPI_TYPE_PACKAGE: + + if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE) + { + ACPI_ERROR ((AE_INFO, "Object not a Package, type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + Status = AcpiDsGetPackageArguments (SourceDesc); + if (ACPI_SUCCESS (Status)) + { + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + } + break; + + + case ACPI_TYPE_BUFFER: + + if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) + { + ACPI_ERROR ((AE_INFO, "Object not a Buffer, type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + Status = AcpiDsGetBufferArguments (SourceDesc); + if (ACPI_SUCCESS (Status)) + { + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + } + break; + + + case ACPI_TYPE_STRING: + + if (SourceDesc->Common.Type != ACPI_TYPE_STRING) + { + ACPI_ERROR ((AE_INFO, "Object not a String, type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + break; + + + case ACPI_TYPE_INTEGER: + + if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "Object not a Integer, type %s", + AcpiUtGetObjectTypeName (SourceDesc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "FieldRead Node=%p SourceDesc=%p Type=%X\n", + Node, SourceDesc, EntryType)); + + Status = AcpiExReadDataFromField (WalkState, SourceDesc, &ObjDesc); + break; + + /* For these objects, just return the object attached to the Node */ + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + break; + + /* TYPE_ANY is untyped, and thus there is no object associated with it */ + + case ACPI_TYPE_ANY: + + ACPI_ERROR ((AE_INFO, + "Untyped entry %p, no attached object!", Node)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ + + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (SourceDesc->Reference.Class) + { + case ACPI_REFCLASS_TABLE: /* This is a DdbHandle */ + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_INDEX: + + /* Return an additional reference to the object */ + + ObjDesc = SourceDesc; + AcpiUtAddReference (ObjDesc); + break; + + default: + /* No named references are allowed here */ + + ACPI_ERROR ((AE_INFO, + "Unsupported Reference type 0x%X", + SourceDesc->Reference.Class)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + break; + + + default: + + /* Default case is for unknown types */ + + ACPI_ERROR ((AE_INFO, + "Node %p - Unknown object type 0x%X", + Node, EntryType)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + + } /* switch (EntryType) */ + + + /* Return the object descriptor */ + + *ObjectPtr = (void *) ObjDesc; + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exresolv.c b/source/components/executer/exresolv.c new file mode 100644 index 000000000000..e92fb2468e77 --- /dev/null +++ b/source/components/executer/exresolv.c @@ -0,0 +1,580 @@ + +/****************************************************************************** + * + * Module Name: exresolv - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXRESOLV_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exresolv") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExResolveObjectToValue ( + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveToValue + * + * PARAMETERS: **StackPtr - Points to entry on ObjStack, which can + * be either an (ACPI_OPERAND_OBJECT *) + * or an ACPI_HANDLE. + * WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert Reference objects to values + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExResolveToValue ( + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExResolveToValue, StackPtr); + + + if (!StackPtr || !*StackPtr) + { + ACPI_ERROR ((AE_INFO, "Internal - null pointer")); + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + /* + * The entity pointed to by the StackPtr can be either + * 1) A valid ACPI_OPERAND_OBJECT, or + * 2) A ACPI_NAMESPACE_NODE (NamedObj) + */ + if (ACPI_GET_DESCRIPTOR_TYPE (*StackPtr) == ACPI_DESC_TYPE_OPERAND) + { + Status = AcpiExResolveObjectToValue (StackPtr, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (!*StackPtr) + { + ACPI_ERROR ((AE_INFO, "Internal - null pointer")); + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + } + + /* + * Object on the stack may have changed if AcpiExResolveObjectToValue() + * was called (i.e., we can't use an _else_ here.) + */ + if (ACPI_GET_DESCRIPTOR_TYPE (*StackPtr) == ACPI_DESC_TYPE_NAMED) + { + Status = AcpiExResolveNodeToValue ( + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, StackPtr), + WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *StackPtr)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveObjectToValue + * + * PARAMETERS: StackPtr - Pointer to an internal object + * WalkState - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from an internal object. The Reference type + * uses the associated AML opcode to determine the value. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExResolveObjectToValue ( + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *StackDesc; + ACPI_OPERAND_OBJECT *ObjDesc = NULL; + UINT8 RefType; + + + ACPI_FUNCTION_TRACE (ExResolveObjectToValue); + + + StackDesc = *StackPtr; + + /* This is an ACPI_OPERAND_OBJECT */ + + switch (StackDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + + RefType = StackDesc->Reference.Class; + + switch (RefType) + { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* + * Get the local from the method's state info + * Note: this increments the local's object reference count + */ + Status = AcpiDsMethodDataGetValue (RefType, + StackDesc->Reference.Value, WalkState, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n", + StackDesc->Reference.Value, ObjDesc)); + + /* + * Now we can delete the original Reference Object and + * replace it with the resolved value + */ + AcpiUtRemoveReference (StackDesc); + *StackPtr = ObjDesc; + break; + + + case ACPI_REFCLASS_INDEX: + + switch (StackDesc->Reference.TargetType) + { + case ACPI_TYPE_BUFFER_FIELD: + + /* Just return - do not dereference */ + break; + + + case ACPI_TYPE_PACKAGE: + + /* If method call or CopyObject - do not dereference */ + + if ((WalkState->Opcode == AML_INT_METHODCALL_OP) || + (WalkState->Opcode == AML_COPY_OP)) + { + break; + } + + /* Otherwise, dereference the PackageIndex to a package element */ + + ObjDesc = *StackDesc->Reference.Where; + if (ObjDesc) + { + /* + * Valid object descriptor, copy pointer to return value + * (i.e., dereference the package index) + * Delete the ref object, increment the returned object + */ + AcpiUtRemoveReference (StackDesc); + AcpiUtAddReference (ObjDesc); + *StackPtr = ObjDesc; + } + else + { + /* + * A NULL object descriptor means an uninitialized element of + * the package, can't dereference it + */ + ACPI_ERROR ((AE_INFO, + "Attempt to dereference an Index to NULL package element Idx=%p", + StackDesc)); + Status = AE_AML_UNINITIALIZED_ELEMENT; + } + break; + + + default: + + /* Invalid reference object */ + + ACPI_ERROR ((AE_INFO, + "Unknown TargetType 0x%X in Index/Reference object %p", + StackDesc->Reference.TargetType, StackDesc)); + Status = AE_AML_INTERNAL; + break; + } + break; + + + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: + + /* Just leave the object as-is, do not dereference */ + + break; + + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + /* Dereference the name */ + + if ((StackDesc->Reference.Node->Type == ACPI_TYPE_DEVICE) || + (StackDesc->Reference.Node->Type == ACPI_TYPE_THERMAL)) + { + /* These node types do not have 'real' subobjects */ + + *StackPtr = (void *) StackDesc->Reference.Node; + } + else + { + /* Get the object pointed to by the namespace node */ + + *StackPtr = (StackDesc->Reference.Node)->Object; + AcpiUtAddReference (*StackPtr); + } + + AcpiUtRemoveReference (StackDesc); + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown Reference type 0x%X in %p", RefType, StackDesc)); + Status = AE_AML_INTERNAL; + break; + } + break; + + + case ACPI_TYPE_BUFFER: + + Status = AcpiDsGetBufferArguments (StackDesc); + break; + + + case ACPI_TYPE_PACKAGE: + + Status = AcpiDsGetPackageArguments (StackDesc); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "FieldRead SourceDesc=%p Type=%X\n", + StackDesc, StackDesc->Common.Type)); + + Status = AcpiExReadDataFromField (WalkState, StackDesc, &ObjDesc); + + /* Remove a reference to the original operand, then override */ + + AcpiUtRemoveReference (*StackPtr); + *StackPtr = (void *) ObjDesc; + break; + + default: + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveMultiple + * + * PARAMETERS: WalkState - Current state (contains AML opcode) + * Operand - Starting point for resolution + * ReturnType - Where the object type is returned + * ReturnDesc - Where the resolved object is returned + * + * RETURN: Status + * + * DESCRIPTION: Return the base object and type. Traverse a reference list if + * necessary to get to the base object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExResolveMultiple ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *Operand, + ACPI_OBJECT_TYPE *ReturnType, + ACPI_OPERAND_OBJECT **ReturnDesc) +{ + ACPI_OPERAND_OBJECT *ObjDesc = (void *) Operand; + ACPI_NAMESPACE_NODE *Node; + ACPI_OBJECT_TYPE Type; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiExResolveMultiple); + + + /* Operand can be either a namespace node or an operand descriptor */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) + { + case ACPI_DESC_TYPE_OPERAND: + Type = ObjDesc->Common.Type; + break; + + case ACPI_DESC_TYPE_NAMED: + Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; + ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); + + /* If we had an Alias node, use the attached object for type info */ + + if (Type == ACPI_TYPE_LOCAL_ALIAS) + { + Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; + ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); + } + break; + + default: + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* If type is anything other than a reference, we are done */ + + if (Type != ACPI_TYPE_LOCAL_REFERENCE) + { + goto Exit; + } + + /* + * For reference objects created via the RefOf, Index, or Load/LoadTable + * operators, we need to get to the base object (as per the ACPI + * specification of the ObjectType and SizeOf operators). This means + * traversing the list of possibly many nested references. + */ + while (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) + { + switch (ObjDesc->Reference.Class) + { + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_NAME: + + /* Dereference the reference pointer */ + + if (ObjDesc->Reference.Class == ACPI_REFCLASS_REFOF) + { + Node = ObjDesc->Reference.Object; + } + else /* AML_INT_NAMEPATH_OP */ + { + Node = ObjDesc->Reference.Node; + } + + /* All "References" point to a NS node */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + ACPI_ERROR ((AE_INFO, + "Not a namespace node %p [%s]", + Node, AcpiUtGetDescriptorName (Node))); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* Get the attached object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + /* No object, use the NS node type */ + + Type = AcpiNsGetType (Node); + goto Exit; + } + + /* Check for circular references */ + + if (ObjDesc == Operand) + { + return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE); + } + break; + + + case ACPI_REFCLASS_INDEX: + + /* Get the type of this reference (index into another object) */ + + Type = ObjDesc->Reference.TargetType; + if (Type != ACPI_TYPE_PACKAGE) + { + goto Exit; + } + + /* + * The main object is a package, we want to get the type + * of the individual package element that is referenced by + * the index. + * + * This could of course in turn be another reference object. + */ + ObjDesc = *(ObjDesc->Reference.Where); + if (!ObjDesc) + { + /* NULL package elements are allowed */ + + Type = 0; /* Uninitialized */ + goto Exit; + } + break; + + + case ACPI_REFCLASS_TABLE: + + Type = ACPI_TYPE_DDB_HANDLE; + goto Exit; + + + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + if (ReturnDesc) + { + Status = AcpiDsMethodDataGetValue (ObjDesc->Reference.Class, + ObjDesc->Reference.Value, WalkState, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + AcpiUtRemoveReference (ObjDesc); + } + else + { + Status = AcpiDsMethodDataGetNode (ObjDesc->Reference.Class, + ObjDesc->Reference.Value, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + Type = ACPI_TYPE_ANY; + goto Exit; + } + } + break; + + + case ACPI_REFCLASS_DEBUG: + + /* The Debug Object is of type "DebugObject" */ + + Type = ACPI_TYPE_DEBUG_OBJECT; + goto Exit; + + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown Reference Class 0x%2.2X", ObjDesc->Reference.Class)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + } + + /* + * Now we are guaranteed to have an object that has not been created + * via the RefOf or Index operators. + */ + Type = ObjDesc->Common.Type; + + +Exit: + /* Convert internal types to external types */ + + switch (Type) + { + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + Type = ACPI_TYPE_FIELD_UNIT; + break; + + case ACPI_TYPE_LOCAL_SCOPE: + + /* Per ACPI Specification, Scope is untyped */ + + Type = ACPI_TYPE_ANY; + break; + + default: + /* No change to Type required */ + break; + } + + *ReturnType = Type; + if (ReturnDesc) + { + *ReturnDesc = ObjDesc; + } + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/executer/exresop.c b/source/components/executer/exresop.c new file mode 100644 index 000000000000..1bcba690333b --- /dev/null +++ b/source/components/executer/exresop.c @@ -0,0 +1,738 @@ + +/****************************************************************************** + * + * Module Name: exresop - AML Interpreter operand/object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXRESOP_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exresop") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExCheckObjectType ( + ACPI_OBJECT_TYPE TypeNeeded, + ACPI_OBJECT_TYPE ThisType, + void *Object); + + +/******************************************************************************* + * + * FUNCTION: AcpiExCheckObjectType + * + * PARAMETERS: TypeNeeded Object type needed + * ThisType Actual object type + * Object Object pointer + * + * RETURN: Status + * + * DESCRIPTION: Check required type against actual type + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExCheckObjectType ( + ACPI_OBJECT_TYPE TypeNeeded, + ACPI_OBJECT_TYPE ThisType, + void *Object) +{ + ACPI_FUNCTION_ENTRY (); + + + if (TypeNeeded == ACPI_TYPE_ANY) + { + /* All types OK, so we don't perform any typechecks */ + + return (AE_OK); + } + + if (TypeNeeded == ACPI_TYPE_LOCAL_REFERENCE) + { + /* + * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference + * objects and thus allow them to be targets. (As per the ACPI + * specification, a store to a constant is a noop.) + */ + if ((ThisType == ACPI_TYPE_INTEGER) && + (((ACPI_OPERAND_OBJECT *) Object)->Common.Flags & AOPOBJ_AML_CONSTANT)) + { + return (AE_OK); + } + } + + if (TypeNeeded != ThisType) + { + ACPI_ERROR ((AE_INFO, + "Needed type [%s], found [%s] %p", + AcpiUtGetTypeName (TypeNeeded), + AcpiUtGetTypeName (ThisType), Object)); + + return (AE_AML_OPERAND_TYPE); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveOperands + * + * PARAMETERS: Opcode - Opcode being interpreted + * StackPtr - Pointer to the operand stack to be + * resolved + * WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Convert multiple input operands to the types required by the + * target operator. + * + * Each 5-bit group in ArgTypes represents one required + * operand and indicates the required Type. The corresponding operand + * will be converted to the required type if possible, otherwise we + * abort with an exception. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExResolveOperands ( + UINT16 Opcode, + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status = AE_OK; + UINT8 ObjectType; + UINT32 ArgTypes; + const ACPI_OPCODE_INFO *OpInfo; + UINT32 ThisArgType; + ACPI_OBJECT_TYPE TypeNeeded; + UINT16 TargetOp = 0; + + + ACPI_FUNCTION_TRACE_U32 (ExResolveOperands, Opcode); + + + OpInfo = AcpiPsGetOpcodeInfo (Opcode); + if (OpInfo->Class == AML_CLASS_UNKNOWN) + { + return_ACPI_STATUS (AE_AML_BAD_OPCODE); + } + + ArgTypes = OpInfo->RuntimeArgs; + if (ArgTypes == ARGI_INVALID_OPCODE) + { + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + Opcode)); + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", + Opcode, OpInfo->Name, ArgTypes)); + + /* + * Normal exit is with (ArgTypes == 0) at end of argument list. + * Function will return an exception from within the loop upon + * finding an entry which is not (or cannot be converted + * to) the required type; if stack underflows; or upon + * finding a NULL stack entry (which should not happen). + */ + while (GET_CURRENT_ARG_TYPE (ArgTypes)) + { + if (!StackPtr || !*StackPtr) + { + ACPI_ERROR ((AE_INFO, "Null stack entry at %p", + StackPtr)); + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* Extract useful items */ + + ObjDesc = *StackPtr; + + /* Decode the descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) + { + case ACPI_DESC_TYPE_NAMED: + + /* Namespace Node */ + + ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; + + /* + * Resolve an alias object. The construction of these objects + * guarantees that there is only one level of alias indirection; + * thus, the attached object is always the aliased namespace node + */ + if (ObjectType == ACPI_TYPE_LOCAL_ALIAS) + { + ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); + *StackPtr = ObjDesc; + ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; + } + break; + + + case ACPI_DESC_TYPE_OPERAND: + + /* ACPI internal object */ + + ObjectType = ObjDesc->Common.Type; + + /* Check for bad ACPI_OBJECT_TYPE */ + + if (!AcpiUtValidObjectType (ObjectType)) + { + ACPI_ERROR ((AE_INFO, + "Bad operand object type [0x%X]", ObjectType)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + if (ObjectType == (UINT8) ACPI_TYPE_LOCAL_REFERENCE) + { + /* Validate the Reference */ + + switch (ObjDesc->Reference.Class) + { + case ACPI_REFCLASS_DEBUG: + + TargetOp = AML_DEBUG_OP; + + /*lint -fallthrough */ + + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_INDEX: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_TABLE: /* DdbHandle from LOAD_OP or LOAD_TABLE_OP */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Operand is a Reference, Class [%s] %2.2X\n", + AcpiUtGetReferenceName (ObjDesc), + ObjDesc->Reference.Class)); + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Unknown Reference Class 0x%2.2X in %p", + ObjDesc->Reference.Class, ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + } + break; + + + default: + + /* Invalid descriptor */ + + ACPI_ERROR ((AE_INFO, "Invalid descriptor %p [%s]", + ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Get one argument type, point to the next */ + + ThisArgType = GET_CURRENT_ARG_TYPE (ArgTypes); + INCREMENT_ARG_LIST (ArgTypes); + + /* + * Handle cases where the object does not need to be + * resolved to a value + */ + switch (ThisArgType) + { + case ARGI_REF_OR_STRING: /* Can be a String or Reference */ + + if ((ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) && + (ObjDesc->Common.Type == ACPI_TYPE_STRING)) + { + /* + * String found - the string references a named object and + * must be resolved to a node + */ + goto NextOperand; + } + + /* + * Else not a string - fall through to the normal Reference + * case below + */ + /*lint -fallthrough */ + + case ARGI_REFERENCE: /* References: */ + case ARGI_INTEGER_REF: + case ARGI_OBJECT_REF: + case ARGI_DEVICE_REF: + case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ + case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ + case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ + + /* + * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE + * A Namespace Node is OK as-is + */ + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) + { + goto NextOperand; + } + + Status = AcpiExCheckObjectType (ACPI_TYPE_LOCAL_REFERENCE, + ObjectType, ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + goto NextOperand; + + + case ARGI_DATAREFOBJ: /* Store operator only */ + + /* + * We don't want to resolve IndexOp reference objects during + * a store because this would be an implicit DeRefOf operation. + * Instead, we just want to store the reference object. + * -- All others must be resolved below. + */ + if ((Opcode == AML_STORE_OP) && + ((*StackPtr)->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + ((*StackPtr)->Reference.Class == ACPI_REFCLASS_INDEX)) + { + goto NextOperand; + } + break; + + default: + /* All cases covered above */ + break; + } + + /* + * Resolve this object to a value + */ + Status = AcpiExResolveToValue (StackPtr, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the resolved object */ + + ObjDesc = *StackPtr; + + /* + * Check the resulting object (value) type + */ + switch (ThisArgType) + { + /* + * For the simple cases, only one type of resolved object + * is allowed + */ + case ARGI_MUTEX: + + /* Need an operand of type ACPI_TYPE_MUTEX */ + + TypeNeeded = ACPI_TYPE_MUTEX; + break; + + case ARGI_EVENT: + + /* Need an operand of type ACPI_TYPE_EVENT */ + + TypeNeeded = ACPI_TYPE_EVENT; + break; + + case ARGI_PACKAGE: /* Package */ + + /* Need an operand of type ACPI_TYPE_PACKAGE */ + + TypeNeeded = ACPI_TYPE_PACKAGE; + break; + + case ARGI_ANYTYPE: + + /* Any operand type will do */ + + TypeNeeded = ACPI_TYPE_ANY; + break; + + case ARGI_DDBHANDLE: + + /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ + + TypeNeeded = ACPI_TYPE_LOCAL_REFERENCE; + break; + + + /* + * The more complex cases allow multiple resolved object types + */ + case ARGI_INTEGER: + + /* + * Need an operand of type ACPI_TYPE_INTEGER, + * But we can implicitly convert from a STRING or BUFFER + * Aka - "Implicit Source Operand Conversion" + */ + Status = AcpiExConvertToInteger (ObjDesc, StackPtr, 16); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_TYPE) + { + ACPI_ERROR ((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS (Status); + } + + if (ObjDesc != *StackPtr) + { + AcpiUtRemoveReference (ObjDesc); + } + goto NextOperand; + + + case ARGI_BUFFER: + + /* + * Need an operand of type ACPI_TYPE_BUFFER, + * But we can implicitly convert from a STRING or INTEGER + * Aka - "Implicit Source Operand Conversion" + */ + Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_TYPE) + { + ACPI_ERROR ((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS (Status); + } + + if (ObjDesc != *StackPtr) + { + AcpiUtRemoveReference (ObjDesc); + } + goto NextOperand; + + + case ARGI_STRING: + + /* + * Need an operand of type ACPI_TYPE_STRING, + * But we can implicitly convert from a BUFFER or INTEGER + * Aka - "Implicit Source Operand Conversion" + */ + Status = AcpiExConvertToString (ObjDesc, StackPtr, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_TYPE) + { + ACPI_ERROR ((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS (Status); + } + + if (ObjDesc != *StackPtr) + { + AcpiUtRemoveReference (ObjDesc); + } + goto NextOperand; + + + case ARGI_COMPUTEDATA: + + /* Need an operand of type INTEGER, STRING or BUFFER */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_ERROR ((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + case ARGI_BUFFER_OR_STRING: + + /* Need an operand of type STRING or BUFFER */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + case ACPI_TYPE_INTEGER: + + /* Highest priority conversion is to type Buffer */ + + Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (ObjDesc != *StackPtr) + { + AcpiUtRemoveReference (ObjDesc); + } + break; + + default: + ACPI_ERROR ((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + case ARGI_DATAOBJECT: + /* + * ARGI_DATAOBJECT is only used by the SizeOf operator. + * Need a buffer, string, package, or RefOf reference. + * + * The only reference allowed here is a direct reference to + * a namespace node. + */ + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_LOCAL_REFERENCE: + + /* Valid operand */ + break; + + default: + ACPI_ERROR ((AE_INFO, + "Needed [Buffer/String/Package/Reference], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + case ARGI_COMPLEXOBJ: + + /* Need a buffer or package or (ACPI 2.0) String */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_ERROR ((AE_INFO, + "Needed [Buffer/String/Package], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ + + /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_REGION: + + /* Valid operand */ + break; + + default: + ACPI_ERROR ((AE_INFO, + "Needed [Region/Buffer], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + case ARGI_DATAREFOBJ: + + /* Used by the Store() operator only */ + + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REFERENCE: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + case ACPI_TYPE_DDB_HANDLE: + + /* Valid operand */ + break; + + default: + + if (AcpiGbl_EnableInterpreterSlack) + { + /* + * Enable original behavior of Store(), allowing any and all + * objects as the source operand. The ACPI spec does not + * allow this, however. + */ + break; + } + + if (TargetOp == AML_DEBUG_OP) + { + /* Allow store of any object to the Debug object */ + + break; + } + + ACPI_ERROR ((AE_INFO, + "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", + AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + goto NextOperand; + + + default: + + /* Unknown type */ + + ACPI_ERROR ((AE_INFO, + "Internal - Unknown ARGI (required operand) type 0x%X", + ThisArgType)); + + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Make sure that the original object was resolved to the + * required object type (Simple cases only). + */ + Status = AcpiExCheckObjectType (TypeNeeded, + (*StackPtr)->Common.Type, *StackPtr); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + +NextOperand: + /* + * If more operands needed, decrement StackPtr to point + * to next operand on stack + */ + if (GET_CURRENT_ARG_TYPE (ArgTypes)) + { + StackPtr--; + } + } + + ACPI_DUMP_OPERANDS (WalkState->Operands, + AcpiPsGetOpcodeName (Opcode), WalkState->NumOperands); + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exstore.c b/source/components/executer/exstore.c new file mode 100644 index 000000000000..656b64947862 --- /dev/null +++ b/source/components/executer/exstore.c @@ -0,0 +1,531 @@ +/****************************************************************************** + * + * Module Name: exstore - AML Interpreter object store support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXSTORE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exstore") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExStoreObjectToIndex ( + ACPI_OPERAND_OBJECT *ValDesc, + ACPI_OPERAND_OBJECT *DestDesc, + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiExStore + * + * PARAMETERS: *SourceDesc - Value to be stored + * *DestDesc - Where to store it. Must be an NS node + * or an ACPI_OPERAND_OBJECT of type + * Reference; + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store the value described by SourceDesc into the location + * described by DestDesc. Called by various interpreter + * functions to store the result of an operation into + * the destination operand -- not just simply the actual "Store" + * ASL operator. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExStore ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *RefDesc = DestDesc; + + + ACPI_FUNCTION_TRACE_PTR (ExStore, DestDesc); + + + /* Validate parameters */ + + if (!SourceDesc || !DestDesc) + { + ACPI_ERROR ((AE_INFO, "Null parameter")); + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + /* DestDesc can be either a namespace node or an ACPI object */ + + if (ACPI_GET_DESCRIPTOR_TYPE (DestDesc) == ACPI_DESC_TYPE_NAMED) + { + /* + * Dest is a namespace node, + * Storing an object into a Named node. + */ + Status = AcpiExStoreObjectToNode (SourceDesc, + (ACPI_NAMESPACE_NODE *) DestDesc, WalkState, + ACPI_IMPLICIT_CONVERSION); + + return_ACPI_STATUS (Status); + } + + /* Destination object must be a Reference or a Constant object */ + + switch (DestDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + break; + + case ACPI_TYPE_INTEGER: + + /* Allow stores to Constants -- a Noop as per ACPI spec */ + + if (DestDesc->Common.Flags & AOPOBJ_AML_CONSTANT) + { + return_ACPI_STATUS (AE_OK); + } + + /*lint -fallthrough */ + + default: + + /* Destination is not a Reference object */ + + ACPI_ERROR ((AE_INFO, + "Target is not a Reference or Constant object - %s [%p]", + AcpiUtGetObjectTypeName (DestDesc), DestDesc)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * Examine the Reference class. These cases are handled: + * + * 1) Store to Name (Change the object associated with a name) + * 2) Store to an indexed area of a Buffer or Package + * 3) Store to a Method Local or Arg + * 4) Store to the debug object + */ + switch (RefDesc->Reference.Class) + { + case ACPI_REFCLASS_REFOF: + + /* Storing an object into a Name "container" */ + + Status = AcpiExStoreObjectToNode (SourceDesc, + RefDesc->Reference.Object, + WalkState, ACPI_IMPLICIT_CONVERSION); + break; + + + case ACPI_REFCLASS_INDEX: + + /* Storing to an Index (pointer into a packager or buffer) */ + + Status = AcpiExStoreObjectToIndex (SourceDesc, RefDesc, WalkState); + break; + + + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* Store to a method local/arg */ + + Status = AcpiDsStoreObjectToLocal (RefDesc->Reference.Class, + RefDesc->Reference.Value, SourceDesc, WalkState); + break; + + + case ACPI_REFCLASS_DEBUG: + + /* + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see ACPI Specification + */ + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "**** Write to Debug Object: Object %p %s ****:\n\n", + SourceDesc, AcpiUtGetObjectTypeName (SourceDesc))); + + ACPI_DEBUG_OBJECT (SourceDesc, 0, 0); + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", + RefDesc->Reference.Class)); + ACPI_DUMP_ENTRY (RefDesc, ACPI_LV_INFO); + + Status = AE_AML_INTERNAL; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreObjectToIndex + * + * PARAMETERS: *SourceDesc - Value to be stored + * *DestDesc - Named object to receive the value + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store the object to indexed Buffer or Package element + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExStoreObjectToIndex ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *IndexDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *NewDesc; + UINT8 Value = 0; + UINT32 i; + + + ACPI_FUNCTION_TRACE (ExStoreObjectToIndex); + + + /* + * Destination must be a reference pointer, and + * must point to either a buffer or a package + */ + switch (IndexDesc->Reference.TargetType) + { + case ACPI_TYPE_PACKAGE: + /* + * Storing to a package element. Copy the object and replace + * any existing object with the new object. No implicit + * conversion is performed. + * + * The object at *(IndexDesc->Reference.Where) is the + * element within the package that is to be modified. + * The parent package object is at IndexDesc->Reference.Object + */ + ObjDesc = *(IndexDesc->Reference.Where); + + if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE && + SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) + { + /* This is a DDBHandle, just add a reference to it */ + + AcpiUtAddReference (SourceDesc); + NewDesc = SourceDesc; + } + else + { + /* Normal object, copy it */ + + Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (ObjDesc) + { + /* Decrement reference count by the ref count of the parent package */ + + for (i = 0; + i < ((ACPI_OPERAND_OBJECT *) + IndexDesc->Reference.Object)->Common.ReferenceCount; + i++) + { + AcpiUtRemoveReference (ObjDesc); + } + } + + *(IndexDesc->Reference.Where) = NewDesc; + + /* Increment ref count by the ref count of the parent package-1 */ + + for (i = 1; + i < ((ACPI_OPERAND_OBJECT *) + IndexDesc->Reference.Object)->Common.ReferenceCount; + i++) + { + AcpiUtAddReference (NewDesc); + } + + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + /* + * Store into a Buffer or String (not actually a real BufferField) + * at a location defined by an Index. + * + * The first 8-bit element of the source object is written to the + * 8-bit Buffer location defined by the Index destination object, + * according to the ACPI 2.0 specification. + */ + + /* + * Make sure the target is a Buffer or String. An error should + * not happen here, since the ReferenceObject was constructed + * by the INDEX_OP code. + */ + ObjDesc = IndexDesc->Reference.Object; + if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) && + (ObjDesc->Common.Type != ACPI_TYPE_STRING)) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * The assignment of the individual elements will be slightly + * different for each source type. + */ + switch (SourceDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* Use the least-significant byte of the integer */ + + Value = (UINT8) (SourceDesc->Integer.Value); + break; + + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + + /* Note: Takes advantage of common string/buffer fields */ + + Value = SourceDesc->Buffer.Pointer[0]; + break; + + default: + + /* All other types are invalid */ + + ACPI_ERROR ((AE_INFO, + "Source must be Integer/Buffer/String type, not %s", + AcpiUtGetObjectTypeName (SourceDesc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Store the source value into the target buffer byte */ + + ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value; + break; + + + default: + ACPI_ERROR ((AE_INFO, + "Target is not a Package or BufferField")); + Status = AE_AML_OPERAND_TYPE; + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreObjectToNode + * + * PARAMETERS: SourceDesc - Value to be stored + * Node - Named object to receive the value + * WalkState - Current walk state + * ImplicitConversion - Perform implicit conversion (yes/no) + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The value passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * Assumes parameters are already validated. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExStoreObjectToNode ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node, + ACPI_WALK_STATE *WalkState, + UINT8 ImplicitConversion) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *TargetDesc; + ACPI_OPERAND_OBJECT *NewDesc; + ACPI_OBJECT_TYPE TargetType; + + + ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc); + + + /* Get current type of the node, and object attached to Node */ + + TargetType = AcpiNsGetType (Node); + TargetDesc = AcpiNsGetAttachedObject (Node); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), + Node, AcpiUtGetTypeName (TargetType))); + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* If no implicit conversion, drop into the default case below */ + + if ((!ImplicitConversion) || + ((WalkState->Opcode == AML_COPY_OP) && + (TargetType != ACPI_TYPE_LOCAL_REGION_FIELD) && + (TargetType != ACPI_TYPE_LOCAL_BANK_FIELD) && + (TargetType != ACPI_TYPE_LOCAL_INDEX_FIELD))) + { + /* + * Force execution of default (no implicit conversion). Note: + * CopyObject does not perform an implicit conversion, as per the ACPI + * spec -- except in case of region/bank/index fields -- because these + * objects must retain their original type permanently. + */ + TargetType = ACPI_TYPE_ANY; + } + + /* Do the actual store operation */ + + switch (TargetType) + { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* For fields, copy the source data to the target field. */ + + Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, + &WalkState->ResultObj); + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These target types are all of type Integer/String/Buffer, and + * therefore support implicit conversion before the store. + * + * Copy and/or convert the source object to a new target object + */ + Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc, + &NewDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (NewDesc != TargetDesc) + { + /* + * Store the new NewDesc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * SourceDesc reference count is incremented by AttachObject. + * + * Note: This may change the type of the node if an explicit store + * has been performed such that the node/object type has been + * changed. + */ + Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Store %s into %s via Convert/Attach\n", + AcpiUtGetObjectTypeName (SourceDesc), + AcpiUtGetObjectTypeName (NewDesc))); + } + break; + + + default: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Storing %s (%p) directly into node (%p) with no implicit conversion\n", + AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, Node)); + + /* No conversions for all other types. Just attach the source object */ + + Status = AcpiNsAttachObject (Node, SourceDesc, + SourceDesc->Common.Type); + break; + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exstoren.c b/source/components/executer/exstoren.c new file mode 100644 index 000000000000..464d6b106504 --- /dev/null +++ b/source/components/executer/exstoren.c @@ -0,0 +1,314 @@ + +/****************************************************************************** + * + * Module Name: exstoren - AML Interpreter object store support, + * Store to Node (namespace object) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXSTOREN_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exstoren") + + +/******************************************************************************* + * + * FUNCTION: AcpiExResolveObject + * + * PARAMETERS: SourceDescPtr - Pointer to the source object + * TargetType - Current type of the target + * WalkState - Current walk state + * + * RETURN: Status, resolved object in SourceDescPtr. + * + * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * it and return the actual object in the SourceDescPtr. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExResolveObject ( + ACPI_OPERAND_OBJECT **SourceDescPtr, + ACPI_OBJECT_TYPE TargetType, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *SourceDesc = *SourceDescPtr; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExResolveObject); + + + /* Ensure we have a Target that can be stored to */ + + switch (TargetType) + { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) + */ + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * Stores into a Field/Region or into a Integer/Buffer/String + * are all essentially the same. This case handles the + * "interchangeable" types Integer, String, and Buffer. + */ + if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) + { + /* Resolve a reference object first */ + + Status = AcpiExResolveToValue (SourceDescPtr, WalkState); + if (ACPI_FAILURE (Status)) + { + break; + } + } + + /* For CopyObject, no further validation necessary */ + + if (WalkState->Opcode == AML_COPY_OP) + { + break; + } + + /* Must have a Integer, Buffer, or String */ + + if ((SourceDesc->Common.Type != ACPI_TYPE_INTEGER) && + (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) && + (SourceDesc->Common.Type != ACPI_TYPE_STRING) && + !((SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + (SourceDesc->Reference.Class== ACPI_REFCLASS_TABLE))) + { + /* Conversion successful but still not a valid type */ + + ACPI_ERROR ((AE_INFO, + "Cannot assign type %s to %s (must be type Int/Str/Buf)", + AcpiUtGetObjectTypeName (SourceDesc), + AcpiUtGetTypeName (TargetType))); + Status = AE_AML_OPERAND_TYPE; + } + break; + + + case ACPI_TYPE_LOCAL_ALIAS: + case ACPI_TYPE_LOCAL_METHOD_ALIAS: + + /* + * All aliases should have been resolved earlier, during the + * operand resolution phase. + */ + ACPI_ERROR ((AE_INFO, "Store into an unresolved Alias object")); + Status = AE_AML_INTERNAL; + break; + + + case ACPI_TYPE_PACKAGE: + default: + + /* + * All other types than Alias and the various Fields come here, + * including the untyped case - ACPI_TYPE_ANY. + */ + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreObjectToObject + * + * PARAMETERS: SourceDesc - Object to store + * DestDesc - Object to receive a copy of the source + * NewDesc - New object if DestDesc is obsoleted + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object to another object. This may include + * converting the source type to the target type (implicit + * conversion), and a copy of the value of the source to + * the target. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The Source passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * Buffer, and Package. + * + * Assumes parameters are already validated. NOTE: SourceDesc + * resolution (from a reference object) must be performed by + * the caller if necessary. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExStoreObjectToObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc, + ACPI_OPERAND_OBJECT **NewDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *ActualSrcDesc; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToObject, SourceDesc); + + + ActualSrcDesc = SourceDesc; + if (!DestDesc) + { + /* + * There is no destination object (An uninitialized node or + * package element), so we can simply copy the source object + * creating a new destination object + */ + Status = AcpiUtCopyIobjectToIobject (ActualSrcDesc, NewDesc, WalkState); + return_ACPI_STATUS (Status); + } + + if (SourceDesc->Common.Type != DestDesc->Common.Type) + { + /* + * The source type does not match the type of the destination. + * Perform the "implicit conversion" of the source to the current type + * of the target as per the ACPI specification. + * + * If no conversion performed, ActualSrcDesc = SourceDesc. + * Otherwise, ActualSrcDesc is a temporary object to hold the + * converted object. + */ + Status = AcpiExConvertToTargetType (DestDesc->Common.Type, + SourceDesc, &ActualSrcDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (SourceDesc == ActualSrcDesc) + { + /* + * No conversion was performed. Return the SourceDesc as the + * new object. + */ + *NewDesc = SourceDesc; + return_ACPI_STATUS (AE_OK); + } + } + + /* + * We now have two objects of identical types, and we can perform a + * copy of the *value* of the source object. + */ + switch (DestDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + DestDesc->Integer.Value = ActualSrcDesc->Integer.Value; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + AcpiExTruncateFor32bitTable (DestDesc); + break; + + case ACPI_TYPE_STRING: + + Status = AcpiExStoreStringToString (ActualSrcDesc, DestDesc); + break; + + case ACPI_TYPE_BUFFER: + + Status = AcpiExStoreBufferToBuffer (ActualSrcDesc, DestDesc); + break; + + case ACPI_TYPE_PACKAGE: + + Status = AcpiUtCopyIobjectToIobject (ActualSrcDesc, &DestDesc, + WalkState); + break; + + default: + /* + * All other types come here. + */ + ACPI_WARNING ((AE_INFO, "Store into type %s not implemented", + AcpiUtGetObjectTypeName (DestDesc))); + + Status = AE_NOT_IMPLEMENTED; + break; + } + + if (ActualSrcDesc != SourceDesc) + { + /* Delete the intermediate (temporary) source object */ + + AcpiUtRemoveReference (ActualSrcDesc); + } + + *NewDesc = DestDesc; + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/executer/exstorob.c b/source/components/executer/exstorob.c new file mode 100644 index 000000000000..e74d5b3485fc --- /dev/null +++ b/source/components/executer/exstorob.c @@ -0,0 +1,244 @@ + +/****************************************************************************** + * + * Module Name: exstorob - AML Interpreter object store support, store to object + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXSTOROB_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exstorob") + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreBufferToBuffer + * + * PARAMETERS: SourceDesc - Source object to copy + * TargetDesc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a buffer object to another buffer object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExStoreBufferToBuffer ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc) +{ + UINT32 Length; + UINT8 *Buffer; + + + ACPI_FUNCTION_TRACE_PTR (ExStoreBufferToBuffer, SourceDesc); + + + /* If Source and Target are the same, just return */ + + if (SourceDesc == TargetDesc) + { + return_ACPI_STATUS (AE_OK); + } + + /* We know that SourceDesc is a buffer by now */ + + Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->Buffer.Pointer); + Length = SourceDesc->Buffer.Length; + + /* + * If target is a buffer of length zero or is a static buffer, + * allocate a new buffer of the proper length + */ + if ((TargetDesc->Buffer.Length == 0) || + (TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)) + { + TargetDesc->Buffer.Pointer = ACPI_ALLOCATE (Length); + if (!TargetDesc->Buffer.Pointer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + TargetDesc->Buffer.Length = Length; + } + + /* Copy source buffer to target buffer */ + + if (Length <= TargetDesc->Buffer.Length) + { + /* Clear existing buffer and copy in the new one */ + + ACPI_MEMSET (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length); + ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer, Length); + +#ifdef ACPI_OBSOLETE_BEHAVIOR + /* + * NOTE: ACPI versions up to 3.0 specified that the buffer must be + * truncated if the string is smaller than the buffer. However, "other" + * implementations of ACPI never did this and thus became the defacto + * standard. ACPI 3.0A changes this behavior such that the buffer + * is no longer truncated. + */ + + /* + * OBSOLETE BEHAVIOR: + * If the original source was a string, we must truncate the buffer, + * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer + * copy must not truncate the original buffer. + */ + if (OriginalSrcType == ACPI_TYPE_STRING) + { + /* Set the new length of the target */ + + TargetDesc->Buffer.Length = Length; + } +#endif + } + else + { + /* Truncate the source, copy only what will fit */ + + ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer, + TargetDesc->Buffer.Length); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Truncating source buffer from %X to %X\n", + Length, TargetDesc->Buffer.Length)); + } + + /* Copy flags */ + + TargetDesc->Buffer.Flags = SourceDesc->Buffer.Flags; + TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreStringToString + * + * PARAMETERS: SourceDesc - Source object to copy + * TargetDesc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a String object to another String object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExStoreStringToString ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc) +{ + UINT32 Length; + UINT8 *Buffer; + + + ACPI_FUNCTION_TRACE_PTR (ExStoreStringToString, SourceDesc); + + + /* If Source and Target are the same, just return */ + + if (SourceDesc == TargetDesc) + { + return_ACPI_STATUS (AE_OK); + } + + /* We know that SourceDesc is a string by now */ + + Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->String.Pointer); + Length = SourceDesc->String.Length; + + /* + * Replace existing string value if it will fit and the string + * pointer is not a static pointer (part of an ACPI table) + */ + if ((Length < TargetDesc->String.Length) && + (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER))) + { + /* + * String will fit in existing non-static buffer. + * Clear old string and copy in the new one + */ + ACPI_MEMSET (TargetDesc->String.Pointer, 0, + (ACPI_SIZE) TargetDesc->String.Length + 1); + ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length); + } + else + { + /* + * Free the current buffer, then allocate a new buffer + * large enough to hold the value + */ + if (TargetDesc->String.Pointer && + (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER))) + { + /* Only free if not a pointer into the DSDT */ + + ACPI_FREE (TargetDesc->String.Pointer); + } + + TargetDesc->String.Pointer = ACPI_ALLOCATE_ZEROED ( + (ACPI_SIZE) Length + 1); + if (!TargetDesc->String.Pointer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; + ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length); + } + + /* Set the new target length */ + + TargetDesc->String.Length = Length; + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/executer/exsystem.c b/source/components/executer/exsystem.c new file mode 100644 index 000000000000..37f5b234a373 --- /dev/null +++ b/source/components/executer/exsystem.c @@ -0,0 +1,355 @@ + +/****************************************************************************** + * + * Module Name: exsystem - Interface to OS services + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXSYSTEM_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exsystem") + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemWaitSemaphore + * + * PARAMETERS: Semaphore - Semaphore to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a semaphore wait with a check to see if the + * semaphore is available immediately. If it is not, the + * interpreter is released before waiting. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemWaitSemaphore ( + ACPI_SEMAPHORE Semaphore, + UINT16 Timeout) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExSystemWaitSemaphore); + + + Status = AcpiOsWaitSemaphore (Semaphore, 1, ACPI_DO_NOT_WAIT); + if (ACPI_SUCCESS (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Status == AE_TIME) + { + /* We must wait, so unlock the interpreter */ + + AcpiExRelinquishInterpreter (); + + Status = AcpiOsWaitSemaphore (Semaphore, 1, Timeout); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + AcpiFormatException (Status))); + + /* Reacquire the interpreter */ + + AcpiExReacquireInterpreter (); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemWaitMutex + * + * PARAMETERS: Mutex - Mutex to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a mutex wait with a check to see if the + * mutex is available immediately. If it is not, the + * interpreter is released before waiting. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemWaitMutex ( + ACPI_MUTEX Mutex, + UINT16 Timeout) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExSystemWaitMutex); + + + Status = AcpiOsAcquireMutex (Mutex, ACPI_DO_NOT_WAIT); + if (ACPI_SUCCESS (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Status == AE_TIME) + { + /* We must wait, so unlock the interpreter */ + + AcpiExRelinquishInterpreter (); + + Status = AcpiOsAcquireMutex (Mutex, Timeout); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + AcpiFormatException (Status))); + + /* Reacquire the interpreter */ + + AcpiExReacquireInterpreter (); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemDoStall + * + * PARAMETERS: HowLong - The amount of time to stall, + * in microseconds + * + * RETURN: Status + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * Note: ACPI specification requires that Stall() does not + * relinquish the processor, and delays longer than 100 usec + * should use Sleep() instead. We allow stalls up to 255 usec + * for compatibility with other interpreters and existing BIOSs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemDoStall ( + UINT32 HowLong) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_ENTRY (); + + + if (HowLong > 255) /* 255 microseconds */ + { + /* + * Longer than 255 usec, this is an error + * + * (ACPI specifies 100 usec as max, but this gives some slack in + * order to support existing BIOSs) + */ + ACPI_ERROR ((AE_INFO, "Time parameter is too large (%u)", + HowLong)); + Status = AE_AML_OPERAND_VALUE; + } + else + { + AcpiOsStall (HowLong); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemDoSleep + * + * PARAMETERS: HowLong - The amount of time to sleep, + * in milliseconds + * + * RETURN: None + * + * DESCRIPTION: Sleep the running thread for specified amount of time. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemDoSleep ( + UINT64 HowLong) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Since this thread will sleep, we must release the interpreter */ + + AcpiExRelinquishInterpreter (); + + /* + * For compatibility with other ACPI implementations and to prevent + * accidental deep sleeps, limit the sleep time to something reasonable. + */ + if (HowLong > ACPI_MAX_SLEEP) + { + HowLong = ACPI_MAX_SLEEP; + } + + AcpiOsSleep (HowLong); + + /* And now we must get the interpreter again */ + + AcpiExReacquireInterpreter (); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemSignalEvent + * + * PARAMETERS: ObjDesc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemSignalEvent ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExSystemSignalEvent); + + + if (ObjDesc) + { + Status = AcpiOsSignalSemaphore (ObjDesc->Event.OsSemaphore, 1); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemWaitEvent + * + * PARAMETERS: TimeDesc - The 'time to delay' object descriptor + * ObjDesc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to wait for an + * event. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemWaitEvent ( + ACPI_OPERAND_OBJECT *TimeDesc, + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (ExSystemWaitEvent); + + + if (ObjDesc) + { + Status = AcpiExSystemWaitSemaphore (ObjDesc->Event.OsSemaphore, + (UINT16) TimeDesc->Integer.Value); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemResetEvent + * + * PARAMETERS: ObjDesc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Reset an event to a known state. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemResetEvent ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status = AE_OK; + ACPI_SEMAPHORE TempSemaphore; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * We are going to simply delete the existing semaphore and + * create a new one! + */ + Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, &TempSemaphore); + if (ACPI_SUCCESS (Status)) + { + (void) AcpiOsDeleteSemaphore (ObjDesc->Event.OsSemaphore); + ObjDesc->Event.OsSemaphore = TempSemaphore; + } + + return (Status); +} + diff --git a/source/components/executer/exutils.c b/source/components/executer/exutils.c new file mode 100644 index 000000000000..b5eca064a20b --- /dev/null +++ b/source/components/executer/exutils.c @@ -0,0 +1,532 @@ + +/****************************************************************************** + * + * Module Name: exutils - interpreter/scanner utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __EXUTILS_C__ + +/* + * DEFINE_AML_GLOBALS is tested in amlcode.h + * to determine whether certain global names should be "defined" or only + * "declared" in the current compilation. This enhances maintainability + * by enabling a single header file to embody all knowledge of the names + * in question. + * + * Exactly one module of any executable should #define DEFINE_GLOBALS + * before #including the header files which use this convention. The + * names in question will be defined and initialized in that module, + * and declared as extern in all other modules which #include those + * header files. + */ + +#define DEFINE_AML_GLOBALS + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exutils") + +/* Local prototypes */ + +static UINT32 +AcpiExDigitsNeeded ( + UINT64 Value, + UINT32 Base); + + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: AcpiExEnterInterpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error. Used in + * conjunction with ExitInterpreter. + * + ******************************************************************************/ + +void +AcpiExEnterInterpreter ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExEnterInterpreter); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not acquire AML Interpreter mutex")); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReacquireInterpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Reacquire the interpreter execution region from within the + * interpreter code. Failure to enter the interpreter region is a + * fatal system error. Used in conjuction with + * RelinquishInterpreter + * + ******************************************************************************/ + +void +AcpiExReacquireInterpreter ( + void) +{ + ACPI_FUNCTION_TRACE (ExReacquireInterpreter); + + + /* + * If the global serialized flag is set, do not release the interpreter, + * since it was not actually released by AcpiExRelinquishInterpreter. + * This forces the interpreter to be single threaded. + */ + if (!AcpiGbl_AllMethodsSerialized) + { + AcpiExEnterInterpreter (); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExExitInterpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Exit the interpreter execution region. This is the top level + * routine used to exit the interpreter when all processing has + * been completed. + * + ******************************************************************************/ + +void +AcpiExExitInterpreter ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExExitInterpreter); + + + Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex")); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExRelinquishInterpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Exit the interpreter execution region, from within the + * interpreter - before attempting an operation that will possibly + * block the running thread. + * + * Cases where the interpreter is unlocked internally + * 1) Method to be blocked on a Sleep() AML opcode + * 2) Method to be blocked on an Acquire() AML opcode + * 3) Method to be blocked on a Wait() AML opcode + * 4) Method to be blocked to acquire the global lock + * 5) Method to be blocked waiting to execute a serialized control method + * that is currently executing + * 6) About to invoke a user-installed opregion handler + * + ******************************************************************************/ + +void +AcpiExRelinquishInterpreter ( + void) +{ + ACPI_FUNCTION_TRACE (ExRelinquishInterpreter); + + + /* + * If the global serialized flag is set, do not release the interpreter. + * This forces the interpreter to be single threaded. + */ + if (!AcpiGbl_AllMethodsSerialized) + { + AcpiExExitInterpreter (); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExTruncateFor32bitTable + * + * PARAMETERS: ObjDesc - Object to be truncated + * + * RETURN: none + * + * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is + * 32-bit, as determined by the revision of the DSDT. + * + ******************************************************************************/ + +void +AcpiExTruncateFor32bitTable ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* + * Object must be a valid number and we must be executing + * a control method. NS node could be there for AML_INT_NAMEPATH_OP. + */ + if ((!ObjDesc) || + (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) || + (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) + { + return; + } + + if (AcpiGbl_IntegerByteWidth == 4) + { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper 32-bit field + */ + ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExAcquireGlobalLock + * + * PARAMETERS: FieldFlags - Flags with Lock rule: + * AlwaysLock or NeverLock + * + * RETURN: None + * + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. + * + ******************************************************************************/ + +void +AcpiExAcquireGlobalLock ( + UINT32 FieldFlags) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExAcquireGlobalLock); + + + /* Only use the lock if the AlwaysLock bit is set */ + + if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK)) + { + return_VOID; + } + + /* Attempt to get the global lock, wait forever */ + + Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER, + AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not acquire Global Lock")); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReleaseGlobalLock + * + * PARAMETERS: FieldFlags - Flags with Lock rule: + * AlwaysLock or NeverLock + * + * RETURN: None + * + * DESCRIPTION: Release the ACPI hardware Global Lock + * + ******************************************************************************/ + +void +AcpiExReleaseGlobalLock ( + UINT32 FieldFlags) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExReleaseGlobalLock); + + + /* Only use the lock if the AlwaysLock bit is set */ + + if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK)) + { + return_VOID; + } + + /* Release the global lock */ + + Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); + if (ACPI_FAILURE (Status)) + { + /* Report the error, but there isn't much else we can do */ + + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not release Global Lock")); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExDigitsNeeded + * + * PARAMETERS: Value - Value to be represented + * Base - Base of representation + * + * RETURN: The number of digits. + * + * DESCRIPTION: Calculate the number of digits needed to represent the Value + * in the given Base (Radix) + * + ******************************************************************************/ + +static UINT32 +AcpiExDigitsNeeded ( + UINT64 Value, + UINT32 Base) +{ + UINT32 NumDigits; + UINT64 CurrentValue; + + + ACPI_FUNCTION_TRACE (ExDigitsNeeded); + + + /* UINT64 is unsigned, so we don't worry about a '-' prefix */ + + if (Value == 0) + { + return_UINT32 (1); + } + + CurrentValue = Value; + NumDigits = 0; + + /* Count the digits in the requested base */ + + while (CurrentValue) + { + (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL); + NumDigits++; + } + + return_UINT32 (NumDigits); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExEisaIdToString + * + * PARAMETERS: CompressedId - EISAID to be converted + * OutString - Where to put the converted string (8 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert a numeric EISAID to string representation. Return + * buffer must be large enough to hold the string. The string + * returned is always exactly of length ACPI_EISAID_STRING_SIZE + * (includes null terminator). The EISAID is always 32 bits. + * + ******************************************************************************/ + +void +AcpiExEisaIdToString ( + char *OutString, + UINT64 CompressedId) +{ + UINT32 SwappedId; + + + ACPI_FUNCTION_ENTRY (); + + + /* The EISAID should be a 32-bit integer */ + + if (CompressedId > ACPI_UINT32_MAX) + { + ACPI_WARNING ((AE_INFO, + "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating", + ACPI_FORMAT_UINT64 (CompressedId))); + } + + /* Swap ID to big-endian to get contiguous bits */ + + SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId); + + /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */ + + OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F)); + OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F)); + OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F)); + OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12); + OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8); + OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4); + OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0); + OutString[7] = 0; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExIntegerToString + * + * PARAMETERS: OutString - Where to put the converted string. At least + * 21 bytes are needed to hold the largest + * possible 64-bit integer. + * Value - Value to be converted + * + * RETURN: None, string + * + * DESCRIPTION: Convert a 64-bit integer to decimal string representation. + * Assumes string buffer is large enough to hold the string. The + * largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1). + * + ******************************************************************************/ + +void +AcpiExIntegerToString ( + char *OutString, + UINT64 Value) +{ + UINT32 Count; + UINT32 DigitsNeeded; + UINT32 Remainder; + + + ACPI_FUNCTION_ENTRY (); + + + DigitsNeeded = AcpiExDigitsNeeded (Value, 10); + OutString[DigitsNeeded] = 0; + + for (Count = DigitsNeeded; Count > 0; Count--) + { + (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder); + OutString[Count-1] = (char) ('0' + Remainder);\ + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiIsValidSpaceId + * + * PARAMETERS: SpaceId - ID to be validated + * + * RETURN: TRUE if valid/supported ID. + * + * DESCRIPTION: Validate an operation region SpaceID. + * + ******************************************************************************/ + +BOOLEAN +AcpiIsValidSpaceId ( + UINT8 SpaceId) +{ + + if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) && + (SpaceId < ACPI_USER_REGION_BEGIN) && + (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) && + (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE)) + { + return (FALSE); + } + + return (TRUE); +} + + +#endif diff --git a/source/components/hardware/hwacpi.c b/source/components/hardware/hwacpi.c new file mode 100644 index 000000000000..d9f16ef9d767 --- /dev/null +++ b/source/components/hardware/hwacpi.c @@ -0,0 +1,209 @@ + +/****************************************************************************** + * + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __HWACPI_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwacpi") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/****************************************************************************** + * + * FUNCTION: AcpiHwSetMode + * + * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * RETURN: Status + * + * DESCRIPTION: Transitions the system into the requested mode. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwSetMode ( + UINT32 Mode) +{ + + ACPI_STATUS Status; + UINT32 Retry; + + + ACPI_FUNCTION_TRACE (HwSetMode); + + /* + * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, + * system does not support mode transition. + */ + if (!AcpiGbl_FADT.SmiCommand) + { + ACPI_ERROR ((AE_INFO, "No SMI_CMD in FADT, mode transition failed")); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); + } + + /* + * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE + * in FADT: If it is zero, enabling or disabling is not supported. + * As old systems may have used zero for mode transition, + * we make sure both the numbers are zero to determine these + * transitions are not supported. + */ + if (!AcpiGbl_FADT.AcpiEnable && !AcpiGbl_FADT.AcpiDisable) + { + ACPI_ERROR ((AE_INFO, + "No ACPI mode transition supported in this system " + "(enable/disable both zero)")); + return_ACPI_STATUS (AE_OK); + } + + switch (Mode) + { + case ACPI_SYS_MODE_ACPI: + + /* BIOS should have disabled ALL fixed and GP events */ + + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, + (UINT32) AcpiGbl_FADT.AcpiEnable, 8); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); + break; + + case ACPI_SYS_MODE_LEGACY: + + /* + * BIOS should clear all fixed status bits and restore fixed event + * enable bits to default + */ + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, + (UINT32) AcpiGbl_FADT.AcpiDisable, 8); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Attempting to enable Legacy (non-ACPI) mode\n")); + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not write ACPI mode change")); + return_ACPI_STATUS (Status); + } + + /* + * Some hardware takes a LONG time to switch modes. Give them 3 sec to + * do so, but allow faster systems to proceed more quickly. + */ + Retry = 3000; + while (Retry) + { + if (AcpiHwGetMode() == Mode) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", + Mode)); + return_ACPI_STATUS (AE_OK); + } + AcpiOsStall(1000); + Retry--; + } + + ACPI_ERROR ((AE_INFO, "Hardware did not change modes")); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwGetMode + * + * PARAMETERS: none + * + * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * DESCRIPTION: Return current operating state of system. Determined by + * querying the SCI_EN bit. + * + ******************************************************************************/ + +UINT32 +AcpiHwGetMode ( + void) +{ + ACPI_STATUS Status; + UINT32 Value; + + + ACPI_FUNCTION_TRACE (HwGetMode); + + + /* + * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, + * system does not support mode transition. + */ + if (!AcpiGbl_FADT.SmiCommand) + { + return_UINT32 (ACPI_SYS_MODE_ACPI); + } + + Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value); + if (ACPI_FAILURE (Status)) + { + return_UINT32 (ACPI_SYS_MODE_LEGACY); + } + + if (Value) + { + return_UINT32 (ACPI_SYS_MODE_ACPI); + } + else + { + return_UINT32 (ACPI_SYS_MODE_LEGACY); + } +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/hardware/hwesleep.c b/source/components/hardware/hwesleep.c new file mode 100644 index 000000000000..e95647e5cd19 --- /dev/null +++ b/source/components/hardware/hwesleep.c @@ -0,0 +1,263 @@ +/****************************************************************************** + * + * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the + * extended FADT-V5 sleep registers. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwesleep") + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExecuteSleepMethod + * + * PARAMETERS: MethodName - Pathname of method to execute + * IntegerArgument - Argument to pass to the method + * + * RETURN: None + * + * DESCRIPTION: Execute a sleep/wake related method with one integer argument + * and no return value. + * + ******************************************************************************/ + +void +AcpiHwExecuteSleepMethod ( + char *MethodName, + UINT32 IntegerArgument) +{ + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwExecuteSleepMethod); + + + /* One argument, IntegerArgument; No return value expected */ + + ArgList.Count = 1; + ArgList.Pointer = &Arg; + Arg.Type = ACPI_TYPE_INTEGER; + Arg.Integer.Value = (UINT64) IntegerArgument; + + Status = AcpiEvaluateObject (NULL, MethodName, &ArgList, NULL); + if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s", + MethodName)); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedSleep + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state via the extended FADT sleep + * registers (V5 FADT). + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedSleep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + UINT8 SleepTypeValue; + UINT64 SleepStatus; + + + ACPI_FUNCTION_TRACE (HwExtendedSleep); + + + /* Extended sleep registers must be valid */ + + if (!AcpiGbl_FADT.SleepControl.Address || + !AcpiGbl_FADT.SleepStatus.Address) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Clear wake status (WAK_STS) */ + + Status = AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiGbl_SystemAwakeAndRunning = FALSE; + + /* Execute the _GTS method (Going To Sleep) */ + + AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState); + + /* Flush caches, as per ACPI specification */ + + ACPI_FLUSH_CPU_CACHE (); + + /* + * Set the SLP_TYP and SLP_EN bits. + * + * Note: We only use the first value returned by the \_Sx method + * (AcpiGbl_SleepTypeA) - As per ACPI specification. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "Entering sleep state [S%u]\n", SleepState)); + + SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + Status = AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE), + &AcpiGbl_FADT.SleepControl); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Wait for transition back to Working State */ + + do + { + Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedWakePrep + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after + * a sleep. Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedWakePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + UINT8 SleepTypeValue; + + + ACPI_FUNCTION_TRACE (HwExtendedWakePrep); + + + Status = AcpiGetSleepTypeData (ACPI_STATE_S0, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_SUCCESS (Status)) + { + SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + (void) AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE), + &AcpiGbl_FADT.SleepControl); + } + + AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedWake + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedWake ( + UINT8 SleepState) +{ + ACPI_FUNCTION_TRACE (HwExtendedWake); + + + /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */ + + AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID; + + /* Execute the wake methods */ + + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING); + AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState); + + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void) AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); + AcpiGbl_SystemAwakeAndRunning = TRUE; + + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS (AE_OK); +} diff --git a/source/components/hardware/hwgpe.c b/source/components/hardware/hwgpe.c new file mode 100644 index 000000000000..c94f17be260e --- /dev/null +++ b/source/components/hardware/hwgpe.c @@ -0,0 +1,543 @@ + +/****************************************************************************** + * + * Module Name: hwgpe - Low level GPE enable/disable/clear functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwgpe") + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwEnableWakeupGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + + +/****************************************************************************** + * + * FUNCTION: AcpiHwGetGpeRegisterBit + * + * PARAMETERS: GpeEventInfo - Info block for the GPE + * GpeRegisterInfo - Info block for the GPE register + * + * RETURN: Register mask with a one in the GPE bit position + * + * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the + * correct position for the input GPE. + * + ******************************************************************************/ + +UINT32 +AcpiHwGetGpeRegisterBit ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) +{ + + return ((UINT32) 1 << + (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwLowSetGpe + * + * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled + * Action - Enable or disable + * + * RETURN: Status + * + * DESCRIPTION: Enable or disable a single GPE in the parent enable register. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLowSetGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 Action) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_STATUS Status; + UINT32 EnableMask; + UINT32 RegisterBit; + + + ACPI_FUNCTION_ENTRY (); + + + /* Get the info block for the entire GPE register */ + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + if (!GpeRegisterInfo) + { + return (AE_NOT_EXIST); + } + + /* Get current value of the enable register that contains this GPE */ + + Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Set or clear just the bit that corresponds to this GPE */ + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); + switch (Action) + { + case ACPI_GPE_CONDITIONAL_ENABLE: + + /* Only enable if the EnableForRun bit is set */ + + if (!(RegisterBit & GpeRegisterInfo->EnableForRun)) + { + return (AE_BAD_PARAMETER); + } + + /*lint -fallthrough */ + + case ACPI_GPE_ENABLE: + ACPI_SET_BIT (EnableMask, RegisterBit); + break; + + case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT (EnableMask, RegisterBit); + break; + + default: + ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action)); + return (AE_BAD_PARAMETER); + } + + /* Write the updated enable mask */ + + Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwClearGpe + * + * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared + * + * RETURN: Status + * + * DESCRIPTION: Clear the status bit for a single GPE. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwClearGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_STATUS Status; + UINT32 RegisterBit; + + + ACPI_FUNCTION_ENTRY (); + + /* Get the info block for the entire GPE register */ + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + if (!GpeRegisterInfo) + { + return (AE_NOT_EXIST); + } + + /* + * Write a one to the appropriate bit in the status register to + * clear this GPE. + */ + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); + + Status = AcpiHwWrite (RegisterBit, + &GpeRegisterInfo->StatusAddress); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwGetGpeStatus + * + * PARAMETERS: GpeEventInfo - Info block for the GPE to queried + * EventStatus - Where the GPE status is returned + * + * RETURN: Status + * + * DESCRIPTION: Return the status of a single GPE. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwGetGpeStatus ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + ACPI_EVENT_STATUS *EventStatus) +{ + UINT32 InByte; + UINT32 RegisterBit; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_EVENT_STATUS LocalEventStatus = 0; + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!EventStatus) + { + return (AE_BAD_PARAMETER); + } + + /* Get the info block for the entire GPE register */ + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + + /* Get the register bitmask for this GPE */ + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); + + /* GPE currently enabled? (enabled for runtime?) */ + + if (RegisterBit & GpeRegisterInfo->EnableForRun) + { + LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; + } + + /* GPE enabled for wake? */ + + if (RegisterBit & GpeRegisterInfo->EnableForWake) + { + LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; + } + + /* GPE currently active (status bit == 1)? */ + + Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (RegisterBit & InByte) + { + LocalEventStatus |= ACPI_EVENT_FLAG_SET; + } + + /* Set return value */ + + (*EventStatus) = LocalEventStatus; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwDisableGpeBlock + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Disable all GPEs within a single GPE block + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwDisableGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + UINT32 i; + ACPI_STATUS Status; + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Disable all GPEs in this register */ + + Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwClearGpeBlock + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Clear status bits for all GPEs within a single GPE block + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwClearGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + UINT32 i; + ACPI_STATUS Status; + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Clear status on all GPEs in this register */ + + Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwEnableRuntimeGpeBlock + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes + * combination wake/run GPEs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwEnableRuntimeGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + UINT32 i; + ACPI_STATUS Status; + + + /* NOTE: assumes that all GPEs are currently disabled */ + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + if (!GpeBlock->RegisterInfo[i].EnableForRun) + { + continue; + } + + /* Enable all "runtime" GPEs in this register */ + + Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun, + &GpeBlock->RegisterInfo[i].EnableAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwEnableWakeupGpeBlock + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes + * combination wake/run GPEs. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwEnableWakeupGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + UINT32 i; + ACPI_STATUS Status; + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + if (!GpeBlock->RegisterInfo[i].EnableForWake) + { + continue; + } + + /* Enable all "wake" GPEs in this register */ + + Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake, + &GpeBlock->RegisterInfo[i].EnableAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwDisableAllGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Disable and clear all GPEs in all GPE blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwDisableAllGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwDisableAllGpes); + + + Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); + Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwEnableAllRuntimeGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwEnableAllRuntimeGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); + + + Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwEnableAllWakeupGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwEnableAllWakeupGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); + + + Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/hardware/hwpci.c b/source/components/hardware/hwpci.c new file mode 100644 index 000000000000..065e42d95eb6 --- /dev/null +++ b/source/components/hardware/hwpci.c @@ -0,0 +1,459 @@ +/******************************************************************************* + * + * Module Name: hwpci - Obtain PCI bus, device, and function numbers + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __HWPCI_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("hwpci") + + +/* PCI configuration space values */ + +#define PCI_CFG_HEADER_TYPE_REG 0x0E +#define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18 +#define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19 + +/* PCI header values */ + +#define PCI_HEADER_TYPE_MASK 0x7F +#define PCI_TYPE_BRIDGE 0x01 +#define PCI_TYPE_CARDBUS_BRIDGE 0x02 + +typedef struct acpi_pci_device +{ + ACPI_HANDLE Device; + struct acpi_pci_device *Next; + +} ACPI_PCI_DEVICE; + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwBuildPciList ( + ACPI_HANDLE RootPciDevice, + ACPI_HANDLE PciRegion, + ACPI_PCI_DEVICE **ReturnListHead); + +static ACPI_STATUS +AcpiHwProcessPciList ( + ACPI_PCI_ID *PciId, + ACPI_PCI_DEVICE *ListHead); + +static void +AcpiHwDeletePciList ( + ACPI_PCI_DEVICE *ListHead); + +static ACPI_STATUS +AcpiHwGetPciDeviceInfo ( + ACPI_PCI_ID *PciId, + ACPI_HANDLE PciDevice, + UINT16 *BusNumber, + BOOLEAN *IsBridge); + + +/******************************************************************************* + * + * FUNCTION: AcpiHwDerivePciId + * + * PARAMETERS: PciId - Initial values for the PCI ID. May be + * modified by this function. + * RootPciDevice - A handle to a PCI device object. This + * object must be a PCI Root Bridge having a + * _HID value of either PNP0A03 or PNP0A08 + * PciRegion - A handle to a PCI configuration space + * Operation Region being initialized + * + * RETURN: Status + * + * DESCRIPTION: This function derives a full PCI ID for a PCI device, + * consisting of a Segment number, Bus number, Device number, + * and function code. + * + * The PCI hardware dynamically configures PCI bus numbers + * depending on the bus topology discovered during system + * initialization. This function is invoked during configuration + * of a PCI_Config Operation Region in order to (possibly) update + * the Bus/Device/Function numbers in the PciId with the actual + * values as determined by the hardware and operating system + * configuration. + * + * The PciId parameter is initially populated during the Operation + * Region initialization. This function is then called, and is + * will make any necessary modifications to the Bus, Device, or + * Function number PCI ID subfields as appropriate for the + * current hardware and OS configuration. + * + * NOTE: Created 08/2010. Replaces the previous OSL AcpiOsDerivePciId + * interface since this feature is OS-independent. This module + * specifically avoids any use of recursion by building a local + * temporary device list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwDerivePciId ( + ACPI_PCI_ID *PciId, + ACPI_HANDLE RootPciDevice, + ACPI_HANDLE PciRegion) +{ + ACPI_STATUS Status; + ACPI_PCI_DEVICE *ListHead = NULL; + + + ACPI_FUNCTION_TRACE (HwDerivePciId); + + + if (!PciId) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Build a list of PCI devices, from PciRegion up to RootPciDevice */ + + Status = AcpiHwBuildPciList (RootPciDevice, PciRegion, &ListHead); + if (ACPI_SUCCESS (Status)) + { + /* Walk the list, updating the PCI device/function/bus numbers */ + + Status = AcpiHwProcessPciList (PciId, ListHead); + } + + /* Always delete the list */ + + AcpiHwDeletePciList (ListHead); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwBuildPciList + * + * PARAMETERS: RootPciDevice - A handle to a PCI device object. This + * object is guaranteed to be a PCI Root + * Bridge having a _HID value of either + * PNP0A03 or PNP0A08 + * PciRegion - A handle to the PCI configuration space + * Operation Region + * ReturnListHead - Where the PCI device list is returned + * + * RETURN: Status + * + * DESCRIPTION: Builds a list of devices from the input PCI region up to the + * Root PCI device for this namespace subtree. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwBuildPciList ( + ACPI_HANDLE RootPciDevice, + ACPI_HANDLE PciRegion, + ACPI_PCI_DEVICE **ReturnListHead) +{ + ACPI_HANDLE CurrentDevice; + ACPI_HANDLE ParentDevice; + ACPI_STATUS Status; + ACPI_PCI_DEVICE *ListElement; + ACPI_PCI_DEVICE *ListHead = NULL; + + + /* + * Ascend namespace branch until the RootPciDevice is reached, building + * a list of device nodes. Loop will exit when either the PCI device is + * found, or the root of the namespace is reached. + */ + CurrentDevice = PciRegion; + while (1) + { + Status = AcpiGetParent (CurrentDevice, &ParentDevice); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ + + if (ParentDevice == RootPciDevice) + { + *ReturnListHead = ListHead; + return (AE_OK); + } + + ListElement = ACPI_ALLOCATE (sizeof (ACPI_PCI_DEVICE)); + if (!ListElement) + { + return (AE_NO_MEMORY); + } + + /* Put new element at the head of the list */ + + ListElement->Next = ListHead; + ListElement->Device = ParentDevice; + ListHead = ListElement; + + CurrentDevice = ParentDevice; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwProcessPciList + * + * PARAMETERS: PciId - Initial values for the PCI ID. May be + * modified by this function. + * ListHead - Device list created by + * AcpiHwBuildPciList + * + * RETURN: Status + * + * DESCRIPTION: Walk downward through the PCI device list, getting the device + * info for each, via the PCI configuration space and updating + * the PCI ID as necessary. Deletes the list during traversal. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwProcessPciList ( + ACPI_PCI_ID *PciId, + ACPI_PCI_DEVICE *ListHead) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PCI_DEVICE *Info; + UINT16 BusNumber; + BOOLEAN IsBridge = TRUE; + + + ACPI_FUNCTION_NAME (HwProcessPciList); + + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", + PciId->Segment, PciId->Bus, PciId->Device, PciId->Function)); + + BusNumber = PciId->Bus; + + /* + * Descend down the namespace tree, collecting PCI device, function, + * and bus numbers. BusNumber is only important for PCI bridges. + * Algorithm: As we descend the tree, use the last valid PCI device, + * function, and bus numbers that are discovered, and assign them + * to the PCI ID for the target device. + */ + Info = ListHead; + while (Info) + { + Status = AcpiHwGetPciDeviceInfo (PciId, Info->Device, + &BusNumber, &IsBridge); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Info = Info->Next; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " + "Status %X BusNumber %X IsBridge %X\n", + PciId->Segment, PciId->Bus, PciId->Device, PciId->Function, + Status, BusNumber, IsBridge)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwDeletePciList + * + * PARAMETERS: ListHead - Device list created by + * AcpiHwBuildPciList + * + * RETURN: None + * + * DESCRIPTION: Free the entire PCI list. + * + ******************************************************************************/ + +static void +AcpiHwDeletePciList ( + ACPI_PCI_DEVICE *ListHead) +{ + ACPI_PCI_DEVICE *Next; + ACPI_PCI_DEVICE *Previous; + + + Next = ListHead; + while (Next) + { + Previous = Next; + Next = Previous->Next; + ACPI_FREE (Previous); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwGetPciDeviceInfo + * + * PARAMETERS: PciId - Initial values for the PCI ID. May be + * modified by this function. + * PciDevice - Handle for the PCI device object + * BusNumber - Where a PCI bridge bus number is returned + * IsBridge - Return value, indicates if this PCI + * device is a PCI bridge + * + * RETURN: Status + * + * DESCRIPTION: Get the device info for a single PCI device object. Get the + * _ADR (contains PCI device and function numbers), and for PCI + * bridge devices, get the bus number from PCI configuration + * space. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwGetPciDeviceInfo ( + ACPI_PCI_ID *PciId, + ACPI_HANDLE PciDevice, + UINT16 *BusNumber, + BOOLEAN *IsBridge) +{ + ACPI_STATUS Status; + ACPI_OBJECT_TYPE ObjectType; + UINT64 ReturnValue; + UINT64 PciValue; + + + /* We only care about objects of type Device */ + + Status = AcpiGetType (PciDevice, &ObjectType); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (ObjectType != ACPI_TYPE_DEVICE) + { + return (AE_OK); + } + + /* We need an _ADR. Ignore device if not present */ + + Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, + PciDevice, &ReturnValue); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + /* + * From _ADR, get the PCI Device and Function and + * update the PCI ID. + */ + PciId->Device = ACPI_HIWORD (ACPI_LODWORD (ReturnValue)); + PciId->Function = ACPI_LOWORD (ACPI_LODWORD (ReturnValue)); + + /* + * If the previous device was a bridge, use the previous + * device bus number + */ + if (*IsBridge) + { + PciId->Bus = *BusNumber; + } + + /* + * Get the bus numbers from PCI Config space: + * + * First, get the PCI HeaderType + */ + *IsBridge = FALSE; + Status = AcpiOsReadPciConfiguration (PciId, + PCI_CFG_HEADER_TYPE_REG, &PciValue, 8); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* We only care about bridges (1=PciBridge, 2=CardBusBridge) */ + + PciValue &= PCI_HEADER_TYPE_MASK; + + if ((PciValue != PCI_TYPE_BRIDGE) && + (PciValue != PCI_TYPE_CARDBUS_BRIDGE)) + { + return (AE_OK); + } + + /* Bridge: Get the Primary BusNumber */ + + Status = AcpiOsReadPciConfiguration (PciId, + PCI_CFG_PRIMARY_BUS_NUMBER_REG, &PciValue, 8); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *IsBridge = TRUE; + PciId->Bus = (UINT16) PciValue; + + /* Bridge: Get the Secondary BusNumber */ + + Status = AcpiOsReadPciConfiguration (PciId, + PCI_CFG_SECONDARY_BUS_NUMBER_REG, &PciValue, 8); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *BusNumber = (UINT16) PciValue; + return (AE_OK); +} diff --git a/source/components/hardware/hwregs.c b/source/components/hardware/hwregs.c new file mode 100644 index 000000000000..6d89883179f4 --- /dev/null +++ b/source/components/hardware/hwregs.c @@ -0,0 +1,741 @@ + +/******************************************************************************* + * + * Module Name: hwregs - Read/write access functions for the various ACPI + * control and status registers. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __HWREGS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwregs") + + +#if (!ACPI_REDUCED_HARDWARE) + +/* Local Prototypes */ + +static ACPI_STATUS +AcpiHwReadMultiple ( + UINT32 *Value, + ACPI_GENERIC_ADDRESS *RegisterA, + ACPI_GENERIC_ADDRESS *RegisterB); + +static ACPI_STATUS +AcpiHwWriteMultiple ( + UINT32 Value, + ACPI_GENERIC_ADDRESS *RegisterA, + ACPI_GENERIC_ADDRESS *RegisterB); + +#endif /* !ACPI_REDUCED_HARDWARE */ + +/****************************************************************************** + * + * FUNCTION: AcpiHwValidateRegister + * + * PARAMETERS: Reg - GAS register structure + * MaxBitWidth - Max BitWidth supported (32 or 64) + * Address - Pointer to where the gas->address + * is returned + * + * RETURN: Status + * + * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS + * pointer, Address, SpaceId, BitWidth, and BitOffset. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwValidateRegister ( + ACPI_GENERIC_ADDRESS *Reg, + UINT8 MaxBitWidth, + UINT64 *Address) +{ + + /* Must have a valid pointer to a GAS structure */ + + if (!Reg) + { + return (AE_BAD_PARAMETER); + } + + /* + * Copy the target address. This handles possible alignment issues. + * Address must not be null. A null address also indicates an optional + * ACPI register that is not supported, so no error message. + */ + ACPI_MOVE_64_TO_64 (Address, &Reg->Address); + if (!(*Address)) + { + return (AE_BAD_ADDRESS); + } + + /* Validate the SpaceID */ + + if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + ACPI_ERROR ((AE_INFO, + "Unsupported address space: 0x%X", Reg->SpaceId)); + return (AE_SUPPORT); + } + + /* Validate the BitWidth */ + + if ((Reg->BitWidth != 8) && + (Reg->BitWidth != 16) && + (Reg->BitWidth != 32) && + (Reg->BitWidth != MaxBitWidth)) + { + ACPI_ERROR ((AE_INFO, + "Unsupported register bit width: 0x%X", Reg->BitWidth)); + return (AE_SUPPORT); + } + + /* Validate the BitOffset. Just a warning for now. */ + + if (Reg->BitOffset != 0) + { + ACPI_WARNING ((AE_INFO, + "Unsupported register bit offset: 0x%X", Reg->BitOffset)); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwRead + * + * PARAMETERS: Value - Where the value is returned + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max + * version of AcpiRead, used internally since the overhead of + * 64-bit values is not needed. + * + * LIMITATIONS: + * BitWidth must be exactly 8, 16, or 32. + * SpaceID must be SystemMemory or SystemIO. + * BitOffset and AccessWidth are currently ignored, as there has + * not been a need to implement these. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwRead ( + UINT32 *Value, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT64 Address; + UINT64 Value64; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (HwRead); + + + /* Validate contents of the GAS register */ + + Status = AcpiHwValidateRegister (Reg, 32, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Initialize entire 32-bit return value to zero */ + + *Value = 0; + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) + Address, &Value64, Reg->BitWidth); + + *Value = (UINT32) Value64; + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) + Address, Value, Reg->BitWidth); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", + *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), + AcpiUtGetRegionName (Reg->SpaceId))); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwWrite + * + * PARAMETERS: Value - Value to be written + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max + * version of AcpiWrite, used internally since the overhead of + * 64-bit values is not needed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwWrite ( + UINT32 Value, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT64 Address; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (HwWrite); + + + /* Validate contents of the GAS register */ + + Status = AcpiHwValidateRegister (Reg, 32, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) + Address, (UINT64) Value, Reg->BitWidth); + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) + Address, Value, Reg->BitWidth); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", + Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), + AcpiUtGetRegionName (Reg->SpaceId))); + + return (Status); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiHwClearAcpiStatus + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Clears all fixed and general purpose status bits + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwClearAcpiStatus ( + void) +{ + ACPI_STATUS Status; + ACPI_CPU_FLAGS LockFlags = 0; + + + ACPI_FUNCTION_TRACE (HwClearAcpiStatus); + + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", + ACPI_BITMASK_ALL_FIXED_STATUS, + ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); + + LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); + + /* Clear the fixed events in PM1 A/B */ + + Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, + ACPI_BITMASK_ALL_FIXED_STATUS); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* Clear the GPE Bits in all GPE registers in all GPE blocks */ + + Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwGetBitRegisterInfo + * + * PARAMETERS: RegisterId - Index of ACPI Register to access + * + * RETURN: The bitmask to be used when accessing the register + * + * DESCRIPTION: Map RegisterId into a register bitmask. + * + ******************************************************************************/ + +ACPI_BIT_REGISTER_INFO * +AcpiHwGetBitRegisterInfo ( + UINT32 RegisterId) +{ + ACPI_FUNCTION_ENTRY (); + + + if (RegisterId > ACPI_BITREG_MAX) + { + ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId)); + return (NULL); + } + + return (&AcpiGbl_BitRegisterInfo[RegisterId]); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwWritePm1Control + * + * PARAMETERS: Pm1aControl - Value to be written to PM1A control + * Pm1bControl - Value to be written to PM1B control + * + * RETURN: Status + * + * DESCRIPTION: Write the PM1 A/B control registers. These registers are + * different than than the PM1 A/B status and enable registers + * in that different values can be written to the A/B registers. + * Most notably, the SLP_TYP bits can be different, as per the + * values returned from the _Sx predefined methods. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwWritePm1Control ( + UINT32 Pm1aControl, + UINT32 Pm1bControl) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwWritePm1Control); + + + Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (AcpiGbl_FADT.XPm1bControlBlock.Address) + { + Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); + } + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwRegisterRead + * + * PARAMETERS: RegisterId - ACPI Register ID + * ReturnValue - Where the register value is returned + * + * RETURN: Status and the value read. + * + * DESCRIPTION: Read from the specified ACPI register + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwRegisterRead ( + UINT32 RegisterId, + UINT32 *ReturnValue) +{ + UINT32 Value = 0; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwRegisterRead); + + + switch (RegisterId) + { + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ + + Status = AcpiHwReadMultiple (&Value, + &AcpiGbl_XPm1aStatus, + &AcpiGbl_XPm1bStatus); + break; + + + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ + + Status = AcpiHwReadMultiple (&Value, + &AcpiGbl_XPm1aEnable, + &AcpiGbl_XPm1bEnable); + break; + + + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ + + Status = AcpiHwReadMultiple (&Value, + &AcpiGbl_FADT.XPm1aControlBlock, + &AcpiGbl_FADT.XPm1bControlBlock); + + /* + * Zero the write-only bits. From the ACPI specification, "Hardware + * Write-Only Bits": "Upon reads to registers with write-only bits, + * software masks out all write-only bits." + */ + Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; + break; + + + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + + Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock); + break; + + + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ + + Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock); + break; + + + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ + + Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); + break; + + + default: + ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", + RegisterId)); + Status = AE_BAD_PARAMETER; + break; + } + + if (ACPI_SUCCESS (Status)) + { + *ReturnValue = Value; + } + + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwRegisterWrite + * + * PARAMETERS: RegisterId - ACPI Register ID + * Value - The value to write + * + * RETURN: Status + * + * DESCRIPTION: Write to the specified ACPI register + * + * NOTE: In accordance with the ACPI specification, this function automatically + * preserves the value of the following bits, meaning that these bits cannot be + * changed via this interface: + * + * PM1_CONTROL[0] = SCI_EN + * PM1_CONTROL[9] + * PM1_STATUS[11] + * + * ACPI References: + * 1) Hardware Ignored Bits: When software writes to a register with ignored + * bit fields, it preserves the ignored bit fields + * 2) SCI_EN: OSPM always preserves this bit position + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwRegisterWrite ( + UINT32 RegisterId, + UINT32 Value) +{ + ACPI_STATUS Status; + UINT32 ReadValue; + + + ACPI_FUNCTION_TRACE (HwRegisterWrite); + + + switch (RegisterId) + { + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ + /* + * Handle the "ignored" bit in PM1 Status. According to the ACPI + * specification, ignored bits are to be preserved when writing. + * Normally, this would mean a read/modify/write sequence. However, + * preserving a bit in the status register is different. Writing a + * one clears the status, and writing a zero preserves the status. + * Therefore, we must always write zero to the ignored bit. + * + * This behavior is clarified in the ACPI 4.0 specification. + */ + Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; + + Status = AcpiHwWriteMultiple (Value, + &AcpiGbl_XPm1aStatus, + &AcpiGbl_XPm1bStatus); + break; + + + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ + + Status = AcpiHwWriteMultiple (Value, + &AcpiGbl_XPm1aEnable, + &AcpiGbl_XPm1bEnable); + break; + + + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ + + /* + * Perform a read first to preserve certain bits (per ACPI spec) + * Note: This includes SCI_EN, we never want to change this bit + */ + Status = AcpiHwReadMultiple (&ReadValue, + &AcpiGbl_FADT.XPm1aControlBlock, + &AcpiGbl_FADT.XPm1bControlBlock); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Insert the bits to be preserved */ + + ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); + + /* Now we can write the data */ + + Status = AcpiHwWriteMultiple (Value, + &AcpiGbl_FADT.XPm1aControlBlock, + &AcpiGbl_FADT.XPm1bControlBlock); + break; + + + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + + /* + * For control registers, all reserved bits must be preserved, + * as per the ACPI spec. + */ + Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Insert the bits to be preserved */ + + ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); + + Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); + break; + + + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ + + Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); + break; + + + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ + + /* SMI_CMD is currently always in IO space */ + + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); + break; + + + default: + ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", + RegisterId)); + Status = AE_BAD_PARAMETER; + break; + } + +Exit: + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwReadMultiple + * + * PARAMETERS: Value - Where the register value is returned + * RegisterA - First ACPI register (required) + * RegisterB - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwReadMultiple ( + UINT32 *Value, + ACPI_GENERIC_ADDRESS *RegisterA, + ACPI_GENERIC_ADDRESS *RegisterB) +{ + UINT32 ValueA = 0; + UINT32 ValueB = 0; + ACPI_STATUS Status; + + + /* The first register is always required */ + + Status = AcpiHwRead (&ValueA, RegisterA); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Second register is optional */ + + if (RegisterB->Address) + { + Status = AcpiHwRead (&ValueB, RegisterB); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + /* + * OR the two return values together. No shifting or masking is necessary, + * because of how the PM1 registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ + *Value = (ValueA | ValueB); + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwWriteMultiple + * + * PARAMETERS: Value - The value to write + * RegisterA - First ACPI register (required) + * RegisterB - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwWriteMultiple ( + UINT32 Value, + ACPI_GENERIC_ADDRESS *RegisterA, + ACPI_GENERIC_ADDRESS *RegisterB) +{ + ACPI_STATUS Status; + + + /* The first register is always required */ + + Status = AcpiHwWrite (Value, RegisterA); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Second register is optional + * + * No bit shifting or clearing is necessary, because of how the PM1 + * registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ + if (RegisterB->Address) + { + Status = AcpiHwWrite (Value, RegisterB); + } + + return (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/hardware/hwsleep.c b/source/components/hardware/hwsleep.c new file mode 100644 index 000000000000..0d311435555a --- /dev/null +++ b/source/components/hardware/hwsleep.c @@ -0,0 +1,384 @@ +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the + * original/legacy sleep/PM registers. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwsleep") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/******************************************************************************* + * + * FUNCTION: AcpiHwLegacySleep + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLegacySleep ( + UINT8 SleepState) +{ + ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo; + ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo; + UINT32 Pm1aControl; + UINT32 Pm1bControl; + UINT32 InValue; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwLegacySleep); + + + SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE); + SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE); + + /* Clear wake status */ + + Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Clear all fixed and general purpose status bits */ + + Status = AcpiHwClearAcpiStatus (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (SleepState != ACPI_STATE_S5) + { + /* + * Disable BM arbitration. This feature is contained within an + * optional register (PM2 Control), so ignore a BAD_ADDRESS + * exception. + */ + Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1); + if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + Status = AcpiHwDisableAllGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + AcpiGbl_SystemAwakeAndRunning = FALSE; + + Status = AcpiHwEnableAllWakeupGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Execute the _GTS method (Going To Sleep) */ + + AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState); + + /* Get current value of PM1A control */ + + Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL, + &Pm1aControl); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "Entering sleep state [S%u]\n", SleepState)); + + /* Clear the SLP_EN and SLP_TYP fields */ + + Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask | + SleepEnableRegInfo->AccessBitMask); + Pm1bControl = Pm1aControl; + + /* Insert the SLP_TYP bits */ + + Pm1aControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition); + Pm1bControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition); + + /* + * We split the writes of SLP_TYP and SLP_EN to workaround + * poorly implemented hardware. + */ + + /* Write #1: write the SLP_TYP data to the PM1 Control registers */ + + Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Insert the sleep enable (SLP_EN) bit */ + + Pm1aControl |= SleepEnableRegInfo->AccessBitMask; + Pm1bControl |= SleepEnableRegInfo->AccessBitMask; + + /* Flush caches, as per ACPI specification */ + + ACPI_FLUSH_CPU_CACHE (); + + /* Write #2: Write both SLP_TYP + SLP_EN */ + + Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (SleepState > ACPI_STATE_S3) + { + /* + * We wanted to sleep > S3, but it didn't happen (by virtue of the + * fact that we are still executing!) + * + * Wait ten seconds, then try again. This is to get S4/S5 to work on + * all machines. + * + * We wait so long to allow chipsets that poll this reg very slowly + * to still read the right value. Ideally, this block would go + * away entirely. + */ + AcpiOsStall (10000000); + + Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL, + SleepEnableRegInfo->AccessBitMask); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Wait for transition back to Working State */ + + do + { + Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + } while (!InValue); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwLegacyWakePrep + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLegacyWakePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo; + ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo; + UINT32 Pm1aControl; + UINT32 Pm1bControl; + + + ACPI_FUNCTION_TRACE (HwLegacyWakePrep); + + /* + * Set SLP_TYPE and SLP_EN to state S0. + * This is unclear from the ACPI Spec, but it is required + * by some machines. + */ + Status = AcpiGetSleepTypeData (ACPI_STATE_S0, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_SUCCESS (Status)) + { + SleepTypeRegInfo = + AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE); + SleepEnableRegInfo = + AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE); + + /* Get current value of PM1A control */ + + Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL, + &Pm1aControl); + if (ACPI_SUCCESS (Status)) + { + /* Clear the SLP_EN and SLP_TYP fields */ + + Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask | + SleepEnableRegInfo->AccessBitMask); + Pm1bControl = Pm1aControl; + + /* Insert the SLP_TYP bits */ + + Pm1aControl |= (AcpiGbl_SleepTypeA << + SleepTypeRegInfo->BitPosition); + Pm1bControl |= (AcpiGbl_SleepTypeB << + SleepTypeRegInfo->BitPosition); + + /* Write the control registers and ignore any errors */ + + (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl); + } + } + + AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwLegacyWake + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLegacyWake ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwLegacyWake); + + + /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */ + + AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID; + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING); + + /* + * GPEs must be enabled before _WAK is called as GPEs + * might get fired there + * + * Restore the GPEs: + * 1) Disable/Clear all GPEs + * 2) Enable all runtime GPEs + */ + Status = AcpiHwDisableAllGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwEnableAllRuntimeGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Now we can execute _WAK, etc. Some machines require that the GPEs + * are enabled before the wake methods are executed. + */ + AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState); + + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void) AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + AcpiGbl_SystemAwakeAndRunning = TRUE; + + /* Enable power button */ + + (void) AcpiWriteBitRegister( + AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId, + ACPI_ENABLE_EVENT); + + (void) AcpiWriteBitRegister( + AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId, + ACPI_CLEAR_STATUS); + + /* + * Enable BM arbitration. This feature is contained within an + * optional register (PM2 Control), so ignore a BAD_ADDRESS + * exception. + */ + Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0); + if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS)) + { + return_ACPI_STATUS (Status); + } + + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/hardware/hwtimer.c b/source/components/hardware/hwtimer.c new file mode 100644 index 000000000000..15dc58f0bffe --- /dev/null +++ b/source/components/hardware/hwtimer.c @@ -0,0 +1,218 @@ + +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwtimer") + + +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/****************************************************************************** + * + * FUNCTION: AcpiGetTimerResolution + * + * PARAMETERS: Resolution - Where the resolution is returned + * + * RETURN: Status and timer resolution + * + * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTimerResolution ( + UINT32 *Resolution) +{ + ACPI_FUNCTION_TRACE (AcpiGetTimerResolution); + + + if (!Resolution) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) + { + *Resolution = 24; + } + else + { + *Resolution = 32; + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTimerResolution) + + +/****************************************************************************** + * + * FUNCTION: AcpiGetTimer + * + * PARAMETERS: Ticks - Where the timer value is returned + * + * RETURN: Status and current timer value (ticks) + * + * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTimer ( + UINT32 *Ticks) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetTimer); + + + if (!Ticks) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTimer) + + +/****************************************************************************** + * + * FUNCTION: AcpiGetTimerDuration + * + * PARAMETERS: StartTicks - Starting timestamp + * EndTicks - End timestamp + * TimeElapsed - Where the elapsed time is returned + * + * RETURN: Status and TimeElapsed + * + * DESCRIPTION: Computes the time elapsed (in microseconds) between two + * PM Timer time stamps, taking into account the possibility of + * rollovers, the timer resolution, and timer frequency. + * + * The PM Timer's clock ticks at roughly 3.6 times per + * _microsecond_, and its clock continues through Cx state + * transitions (unlike many CPU timestamp counters) -- making it + * a versatile and accurate timer. + * + * Note that this function accommodates only a single timer + * rollover. Thus for 24-bit timers, this function should only + * be used for calculating durations less than ~4.6 seconds + * (~20 minutes for 32-bit timers) -- calculations below: + * + * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec + * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTimerDuration ( + UINT32 StartTicks, + UINT32 EndTicks, + UINT32 *TimeElapsed) +{ + ACPI_STATUS Status; + UINT32 DeltaTicks; + UINT64 Quotient; + + + ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); + + + if (!TimeElapsed) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Compute Tick Delta: + * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. + */ + if (StartTicks < EndTicks) + { + DeltaTicks = EndTicks - StartTicks; + } + else if (StartTicks > EndTicks) + { + if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) + { + /* 24-bit Timer */ + + DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF); + } + else + { + /* 32-bit Timer */ + + DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks; + } + } + else /* StartTicks == EndTicks */ + { + *TimeElapsed = 0; + return_ACPI_STATUS (AE_OK); + } + + /* + * Compute Duration (Requires a 64-bit multiply and divide): + * + * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY; + */ + Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000, + PM_TIMER_FREQUENCY, &Quotient, NULL); + + *TimeElapsed = (UINT32) Quotient; + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/hardware/hwvalid.c b/source/components/hardware/hwvalid.c new file mode 100644 index 000000000000..4462434bbfe6 --- /dev/null +++ b/source/components/hardware/hwvalid.c @@ -0,0 +1,368 @@ + +/****************************************************************************** + * + * Module Name: hwvalid - I/O request validation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __HWVALID_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwvalid") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwValidateIoRequest ( + ACPI_IO_ADDRESS Address, + UINT32 BitWidth); + + +/* + * Protected I/O ports. Some ports are always illegal, and some are + * conditionally illegal. This table must remain ordered by port address. + * + * The table is used to implement the Microsoft port access rules that + * first appeared in Windows XP. Some ports are always illegal, and some + * ports are only illegal if the BIOS calls _OSI with a WinXP string or + * later (meaning that the BIOS itelf is post-XP.) + * + * This provides ACPICA with the desired port protections and + * Microsoft compatibility. + * + * Description of port entries: + * DMA: DMA controller + * PIC0: Programmable Interrupt Controller (8259A) + * PIT1: System Timer 1 + * PIT2: System Timer 2 failsafe + * RTC: Real-time clock + * CMOS: Extended CMOS + * DMA1: DMA 1 page registers + * DMA1L: DMA 1 Ch 0 low page + * DMA2: DMA 2 page registers + * DMA2L: DMA 2 low page refresh + * ARBC: Arbitration control + * SETUP: Reserved system board setup + * POS: POS channel select + * PIC1: Cascaded PIC + * IDMA: ISA DMA + * ELCR: PIC edge/level registers + * PCI: PCI configuration space + */ +static const ACPI_PORT_INFO AcpiProtectedPorts[] = +{ + {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, + {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, + {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, + {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, + {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, + {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, + {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, + {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, + {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP}, + {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, + {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, + {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, + {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, + {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, + {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, + {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, + {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP} +}; + +#define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (AcpiProtectedPorts) + + +/****************************************************************************** + * + * FUNCTION: AcpiHwValidateIoRequest + * + * PARAMETERS: Address Address of I/O port/register + * BitWidth Number of bits (8,16,32) + * + * RETURN: Status + * + * DESCRIPTION: Validates an I/O request (address/length). Certain ports are + * always illegal and some ports are only illegal depending on + * the requests the BIOS AML code makes to the predefined + * _OSI method. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwValidateIoRequest ( + ACPI_IO_ADDRESS Address, + UINT32 BitWidth) +{ + UINT32 i; + UINT32 ByteWidth; + ACPI_IO_ADDRESS LastAddress; + const ACPI_PORT_INFO *PortInfo; + + + ACPI_FUNCTION_TRACE (HwValidateIoRequest); + + + /* Supported widths are 8/16/32 */ + + if ((BitWidth != 8) && + (BitWidth != 16) && + (BitWidth != 32)) + { + ACPI_ERROR ((AE_INFO, + "Bad BitWidth parameter: %8.8X", BitWidth)); + return (AE_BAD_PARAMETER); + } + + PortInfo = AcpiProtectedPorts; + ByteWidth = ACPI_DIV_8 (BitWidth); + LastAddress = Address + ByteWidth - 1; + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %p LastAddress %p Length %X", + ACPI_CAST_PTR (void, Address), ACPI_CAST_PTR (void, LastAddress), + ByteWidth)); + + /* Maximum 16-bit address in I/O space */ + + if (LastAddress > ACPI_UINT16_MAX) + { + ACPI_ERROR ((AE_INFO, + "Illegal I/O port address/length above 64K: %p/0x%X", + ACPI_CAST_PTR (void, Address), ByteWidth)); + return_ACPI_STATUS (AE_LIMIT); + } + + /* Exit if requested address is not within the protected port table */ + + if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End) + { + return_ACPI_STATUS (AE_OK); + } + + /* Check request against the list of protected I/O ports */ + + for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++) + { + /* + * Check if the requested address range will write to a reserved + * port. Four cases to consider: + * + * 1) Address range is contained completely in the port address range + * 2) Address range overlaps port range at the port range start + * 3) Address range overlaps port range at the port range end + * 4) Address range completely encompasses the port range + */ + if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start)) + { + /* Port illegality may depend on the _OSI calls made by the BIOS */ + + if (AcpiGbl_OsiData >= PortInfo->OsiDependency) + { + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", + ACPI_CAST_PTR (void, Address), ByteWidth, PortInfo->Name, + PortInfo->Start, PortInfo->End)); + + return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS); + } + } + + /* Finished if address range ends before the end of this port */ + + if (LastAddress <= PortInfo->End) + { + break; + } + } + + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwReadPort + * + * PARAMETERS: Address Address of I/O port/register to read + * Value Where value is placed + * Width Number of bits + * + * RETURN: Status and value read from port + * + * DESCRIPTION: Read data from an I/O port or register. This is a front-end + * to AcpiOsReadPort that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiHwReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + ACPI_STATUS Status; + UINT32 OneByte; + UINT32 i; + + + /* Truncate address to 16 bits if requested */ + + if (AcpiGbl_TruncateIoAddresses) + { + Address &= ACPI_UINT16_MAX; + } + + /* Validate the entire request and perform the I/O */ + + Status = AcpiHwValidateIoRequest (Address, Width); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiOsReadPort (Address, Value, Width); + return (Status); + } + + if (Status != AE_AML_ILLEGAL_ADDRESS) + { + return (Status); + } + + /* + * There has been a protection violation within the request. Fall + * back to byte granularity port I/O and ignore the failing bytes. + * This provides Windows compatibility. + */ + for (i = 0, *Value = 0; i < Width; i += 8) + { + /* Validate and read one byte */ + + if (AcpiHwValidateIoRequest (Address, 8) == AE_OK) + { + Status = AcpiOsReadPort (Address, &OneByte, 8); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + *Value |= (OneByte << i); + } + + Address++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwWritePort + * + * PARAMETERS: Address Address of I/O port/register to write + * Value Value to write + * Width Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Write data to an I/O port or register. This is a front-end + * to AcpiOsWritePort that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiHwWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + ACPI_STATUS Status; + UINT32 i; + + + /* Truncate address to 16 bits if requested */ + + if (AcpiGbl_TruncateIoAddresses) + { + Address &= ACPI_UINT16_MAX; + } + + /* Validate the entire request and perform the I/O */ + + Status = AcpiHwValidateIoRequest (Address, Width); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiOsWritePort (Address, Value, Width); + return (Status); + } + + if (Status != AE_AML_ILLEGAL_ADDRESS) + { + return (Status); + } + + /* + * There has been a protection violation within the request. Fall + * back to byte granularity port I/O and ignore the failing bytes. + * This provides Windows compatibility. + */ + for (i = 0; i < Width; i += 8) + { + /* Validate and write one byte */ + + if (AcpiHwValidateIoRequest (Address, 8) == AE_OK) + { + Status = AcpiOsWritePort (Address, (Value >> i) & 0xFF, 8); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + Address++; + } + + return (AE_OK); +} + + diff --git a/source/components/hardware/hwxface.c b/source/components/hardware/hwxface.c new file mode 100644 index 000000000000..3fec9b566f05 --- /dev/null +++ b/source/components/hardware/hwxface.c @@ -0,0 +1,617 @@ + +/****************************************************************************** + * + * Module Name: hwxface - Public ACPICA hardware interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwxface") + + +/****************************************************************************** + * + * FUNCTION: AcpiReset + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Set reset register in memory or IO space. Note: Does not + * support reset register in PCI config space, this must be + * handled separately. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReset ( + void) +{ + ACPI_GENERIC_ADDRESS *ResetReg; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiReset); + + + ResetReg = &AcpiGbl_FADT.ResetRegister; + + /* Check if the reset register is supported */ + + if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || + !ResetReg->Address) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) + { + /* + * For I/O space, write directly to the OSL. This bypasses the port + * validation mechanism, which may block a valid write to the reset + * register. + */ + Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, + AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); + } + else + { + /* Write the reset value to the reset register */ + + Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiReset) + + +/****************************************************************************** + * + * FUNCTION: AcpiRead + * + * PARAMETERS: Value - Where the value is returned + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Read from either memory or IO space. + * + * LIMITATIONS: + * BitWidth must be exactly 8, 16, 32, or 64. + * SpaceID must be SystemMemory or SystemIO. + * BitOffset and AccessWidth are currently ignored, as there has + * not been a need to implement these. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRead ( + UINT64 *ReturnValue, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT32 Value; + UINT32 Width; + UINT64 Address; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (AcpiRead); + + + if (!ReturnValue) + { + return (AE_BAD_PARAMETER); + } + + /* Validate contents of the GAS register. Allow 64-bit transfers */ + + Status = AcpiHwValidateRegister (Reg, 64, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Initialize entire 64-bit return value to zero */ + + *ReturnValue = 0; + Value = 0; + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) + Address, ReturnValue, Reg->BitWidth); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Width = Reg->BitWidth; + if (Width == 64) + { + Width = 32; /* Break into two 32-bit transfers */ + } + + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) + Address, &Value, Width); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + *ReturnValue = Value; + + if (Reg->BitWidth == 64) + { + /* Read the top 32 bits */ + + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) + (Address + 4), &Value, 32); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + *ReturnValue |= ((UINT64) Value << 32); + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, + ACPI_FORMAT_UINT64 (Address), + AcpiUtGetRegionName (Reg->SpaceId))); + + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRead) + + +/****************************************************************************** + * + * FUNCTION: AcpiWrite + * + * PARAMETERS: Value - Value to be written + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Write to either memory or IO space. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiWrite ( + UINT64 Value, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT32 Width; + UINT64 Address; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (AcpiWrite); + + + /* Validate contents of the GAS register. Allow 64-bit transfers */ + + Status = AcpiHwValidateRegister (Reg, 64, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) + Address, Value, Reg->BitWidth); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Width = Reg->BitWidth; + if (Width == 64) + { + Width = 32; /* Break into two 32-bit transfers */ + } + + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) + Address, ACPI_LODWORD (Value), Width); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (Reg->BitWidth == 64) + { + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) + (Address + 4), ACPI_HIDWORD (Value), 32); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64 (Value), Reg->BitWidth, + ACPI_FORMAT_UINT64 (Address), + AcpiUtGetRegionName (Reg->SpaceId))); + + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWrite) + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiReadBitRegister + * + * PARAMETERS: RegisterId - ID of ACPI Bit Register to access + * ReturnValue - Value that was read from the register, + * normalized to bit position zero. + * + * RETURN: Status and the value read from the specified Register. Value + * returned is normalized to bit0 (is shifted all the way right) + * + * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. + * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. + * + * Note: The hardware lock is not required when reading the ACPI bit registers + * since almost all of them are single bit and it does not matter that + * the parent hardware register can be split across two physical + * registers. The only multi-bit field is SLP_TYP in the PM1 control + * register, but this field does not cross an 8-bit boundary (nor does + * it make much sense to actually read this field.) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReadBitRegister ( + UINT32 RegisterId, + UINT32 *ReturnValue) +{ + ACPI_BIT_REGISTER_INFO *BitRegInfo; + UINT32 RegisterValue; + UINT32 Value; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId); + + + /* Get the info structure corresponding to the requested ACPI Register */ + + BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); + if (!BitRegInfo) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Read the entire parent register */ + + Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, + &RegisterValue); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Normalize the value that was read, mask off other bits */ + + Value = ((RegisterValue & BitRegInfo->AccessBitMask) + >> BitRegInfo->BitPosition); + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", + RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value)); + + *ReturnValue = Value; + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiReadBitRegister) + + +/******************************************************************************* + * + * FUNCTION: AcpiWriteBitRegister + * + * PARAMETERS: RegisterId - ID of ACPI Bit Register to access + * Value - Value to write to the register, in bit + * position zero. The bit is automaticallly + * shifted to the correct position. + * + * RETURN: Status + * + * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock + * since most operations require a read/modify/write sequence. + * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. + * + * Note that at this level, the fact that there may be actually two + * hardware registers (A and B - and B may not exist) is abstracted. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiWriteBitRegister ( + UINT32 RegisterId, + UINT32 Value) +{ + ACPI_BIT_REGISTER_INFO *BitRegInfo; + ACPI_CPU_FLAGS LockFlags; + UINT32 RegisterValue; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId); + + + /* Get the info structure corresponding to the requested ACPI Register */ + + BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); + if (!BitRegInfo) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); + + /* + * At this point, we know that the parent register is one of the + * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control + */ + if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS) + { + /* + * 1) Case for PM1 Enable, PM1 Control, and PM2 Control + * + * Perform a register read to preserve the bits that we are not + * interested in + */ + Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, + &RegisterValue); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* + * Insert the input bit into the value that was just read + * and write the register + */ + ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, + BitRegInfo->AccessBitMask, Value); + + Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister, + RegisterValue); + } + else + { + /* + * 2) Case for PM1 Status + * + * The Status register is different from the rest. Clear an event + * by writing 1, writing 0 has no effect. So, the only relevant + * information is the single bit we're interested in, all others + * should be written as 0 so they will be left unchanged. + */ + RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value, + BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); + + /* No need to write the register if value is all zeros */ + + if (RegisterValue) + { + Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, + RegisterValue); + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", + RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue)); + + +UnlockAndExit: + + AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) + +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiGetSleepTypeData + * + * PARAMETERS: SleepState - Numeric sleep state + * *SleepTypeA - Where SLP_TYPa is returned + * *SleepTypeB - Where SLP_TYPb is returned + * + * RETURN: Status - ACPI status + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep + * state. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetSleepTypeData ( + UINT8 SleepState, + UINT8 *SleepTypeA, + UINT8 *SleepTypeB) +{ + ACPI_STATUS Status = AE_OK; + ACPI_EVALUATE_INFO *Info; + + + ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); + + + /* Validate parameters */ + + if ((SleepState > ACPI_S_STATES_MAX) || + !SleepTypeA || + !SleepTypeB) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); + + /* Evaluate the namespace object containing the values for this state */ + + Status = AcpiNsEvaluate (Info); + if (ACPI_FAILURE (Status)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%s while evaluating SleepState [%s]\n", + AcpiFormatException (Status), Info->Pathname)); + + goto Cleanup; + } + + /* Must have a return object */ + + if (!Info->ReturnObject) + { + ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", + Info->Pathname)); + Status = AE_NOT_EXIST; + } + + /* It must be of type Package */ + + else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) + { + ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); + Status = AE_AML_OPERAND_TYPE; + } + + /* + * The package must have at least two elements. NOTE (March 2005): This + * goes against the current ACPI spec which defines this object as a + * package with one encoded DWORD element. However, existing practice + * by BIOS vendors seems to be to have 2 or more elements, at least + * one per sleep type (A/B). + */ + else if (Info->ReturnObject->Package.Count < 2) + { + ACPI_ERROR ((AE_INFO, + "Sleep State return package does not have at least two elements")); + Status = AE_AML_NO_OPERAND; + } + + /* The first two elements must both be of type Integer */ + + else if (((Info->ReturnObject->Package.Elements[0])->Common.Type + != ACPI_TYPE_INTEGER) || + ((Info->ReturnObject->Package.Elements[1])->Common.Type + != ACPI_TYPE_INTEGER)) + { + ACPI_ERROR ((AE_INFO, + "Sleep State return package elements are not both Integers " + "(%s, %s)", + AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), + AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); + Status = AE_AML_OPERAND_TYPE; + } + else + { + /* Valid _Sx_ package size, type, and value */ + + *SleepTypeA = (UINT8) + (Info->ReturnObject->Package.Elements[0])->Integer.Value; + *SleepTypeB = (UINT8) + (Info->ReturnObject->Package.Elements[1])->Integer.Value; + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While evaluating SleepState [%s], bad Sleep object %p type %s", + Info->Pathname, Info->ReturnObject, + AcpiUtGetObjectTypeName (Info->ReturnObject))); + } + + AcpiUtRemoveReference (Info->ReturnObject); + +Cleanup: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) diff --git a/source/components/hardware/hwxfsleep.c b/source/components/hardware/hwxfsleep.c new file mode 100644 index 000000000000..39bf122a072e --- /dev/null +++ b/source/components/hardware/hwxfsleep.c @@ -0,0 +1,474 @@ +/****************************************************************************** + * + * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwxfsleep") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwSleepDispatch ( + UINT8 SleepState, + UINT32 FunctionId); + +/* + * Dispatch table used to efficiently branch to the various sleep + * functions. + */ +#define ACPI_SLEEP_FUNCTION_ID 0 +#define ACPI_WAKE_PREP_FUNCTION_ID 1 +#define ACPI_WAKE_FUNCTION_ID 2 + +/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */ + +static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] = +{ + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep), AcpiHwExtendedSleep}, + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep), AcpiHwExtendedWakePrep}, + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake), AcpiHwExtendedWake} +}; + + +/* + * These functions are removed for the ACPI_REDUCED_HARDWARE case: + * AcpiSetFirmwareWakingVector + * AcpiSetFirmwareWakingVector64 + * AcpiEnterSleepStateS4bios + */ + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiSetFirmwareWakingVector + * + * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetFirmwareWakingVector ( + UINT32 PhysicalAddress) +{ + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); + + + /* Set the 32-bit vector */ + + AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; + + /* Clear the 64-bit vector if it exists */ + + if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1)) + { + AcpiGbl_FACS->XFirmwareWakingVector = 0; + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) + + +#if ACPI_MACHINE_WIDTH == 64 +/******************************************************************************* + * + * FUNCTION: AcpiSetFirmwareWakingVector64 + * + * PARAMETERS: PhysicalAddress - 64-bit physical address of ACPI protected + * mode entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if + * it exists in the table. This function is intended for use with + * 64-bit host operating systems. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetFirmwareWakingVector64 ( + UINT64 PhysicalAddress) +{ + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64); + + + /* Determine if the 64-bit vector actually exists */ + + if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1)) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Clear 32-bit vector, set the 64-bit X_ vector */ + + AcpiGbl_FACS->FirmwareWakingVector = 0; + AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress; + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64) +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepStateS4bios + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a S4 bios request. + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepStateS4bios ( + void) +{ + UINT32 InValue; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios); + + + /* Clear the wake status bit (PM1) */ + + Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwClearAcpiStatus (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + Status = AcpiHwDisableAllGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + AcpiGbl_SystemAwakeAndRunning = FALSE; + + Status = AcpiHwEnableAllWakeupGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_FLUSH_CPU_CACHE (); + + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, + (UINT32) AcpiGbl_FADT.S4BiosRequest, 8); + + do { + AcpiOsStall(1000); + Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } while (!InValue); + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios) + +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiHwSleepDispatch + * + * PARAMETERS: SleepState - Which sleep state to enter/exit + * FunctionId - Sleep, WakePrep, or Wake + * + * RETURN: Status from the invoked sleep handling function. + * + * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling + * function. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwSleepDispatch ( + UINT8 SleepState, + UINT32 FunctionId) +{ + ACPI_STATUS Status; + ACPI_SLEEP_FUNCTIONS *SleepFunctions = &AcpiSleepDispatch[FunctionId]; + + +#if (!ACPI_REDUCED_HARDWARE) + + /* + * If the Hardware Reduced flag is set (from the FADT), we must + * use the extended sleep registers + */ + if (AcpiGbl_ReducedHardware || + AcpiGbl_FADT.SleepControl.Address) + { + Status = SleepFunctions->ExtendedFunction (SleepState); + } + else + { + /* Legacy sleep */ + + Status = SleepFunctions->LegacyFunction (SleepState); + } + + return (Status); + +#else + /* + * For the case where reduced-hardware-only code is being generated, + * we know that only the extended sleep registers are available + */ + Status = SleepFunctions->ExtendedFunction (SleepState); + return (Status); + +#endif /* !ACPI_REDUCED_HARDWARE */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepStatePrep + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Prepare to enter a system sleep state. + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepStatePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg; + UINT32 SstValue; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep); + + + /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ + + Status = AcpiGetSleepTypeData (SleepState, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Execute the _PTS method (Prepare To Sleep) */ + + ArgList.Count = 1; + ArgList.Pointer = &Arg; + Arg.Type = ACPI_TYPE_INTEGER; + Arg.Integer.Value = SleepState; + + Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL); + if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) + { + return_ACPI_STATUS (Status); + } + + /* Setup the argument to the _SST method (System STatus) */ + + switch (SleepState) + { + case ACPI_STATE_S0: + SstValue = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + SstValue = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + SstValue = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + SstValue = ACPI_SST_INDICATOR_OFF; /* Default is off */ + break; + } + + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, SstValue); + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepState + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepState ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepState); + + + if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) || + (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX)) + { + ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", + AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB)); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + Status = AcpiHwSleepDispatch (SleepState, ACPI_SLEEP_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepState) + + +/******************************************************************************* + * + * FUNCTION: AcpiLeaveSleepStatePrep + * + * PARAMETERS: SleepState - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. Called with interrupts DISABLED. + * We break wake/resume into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLeaveSleepStatePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLeaveSleepStatePrep); + + + Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_PREP_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLeaveSleepStatePrep) + + +/******************************************************************************* + * + * FUNCTION: AcpiLeaveSleepState + * + * PARAMETERS: SleepState - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLeaveSleepState ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLeaveSleepState); + + + Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState) diff --git a/source/components/namespace/nsaccess.c b/source/components/namespace/nsaccess.c new file mode 100644 index 000000000000..9dfa76fb0850 --- /dev/null +++ b/source/components/namespace/nsaccess.c @@ -0,0 +1,700 @@ +/******************************************************************************* + * + * Module Name: nsaccess - Top-level functions for accessing ACPI namespace + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSACCESS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsaccess") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRootInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Allocate and initialize the default root named objects + * + * MUTEX: Locks namespace for entire execution + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsRootInitialize ( + void) +{ + ACPI_STATUS Status; + const ACPI_PREDEFINED_NAMES *InitVal = NULL; + ACPI_NAMESPACE_NODE *NewNode; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STRING Val = NULL; + + + ACPI_FUNCTION_TRACE (NsRootInitialize); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * The global root ptr is initially NULL, so a non-NULL value indicates + * that AcpiNsRootInitialize() has already been called; just return. + */ + if (AcpiGbl_RootNode) + { + Status = AE_OK; + goto UnlockAndExit; + } + + /* + * Tell the rest of the subsystem that the root is initialized + * (This is OK because the namespace is locked) + */ + AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct; + + /* Enter the pre-defined names in the name table */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Entering predefined entries into namespace\n")); + + for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) + { + /* _OSI is optional for now, will be permanent later */ + + if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) + { + continue; + } + + Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type, + ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, + NULL, &NewNode); + + if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */ + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not create predefined name %s", + InitVal->Name)); + } + + /* + * Name entered successfully. If entry in PreDefinedNames[] specifies + * an initial value, create the initial value. + */ + if (InitVal->Val) + { + Status = AcpiOsPredefinedOverride (InitVal, &Val); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not override predefined %s", + InitVal->Name)); + } + + if (!Val) + { + Val = InitVal->Val; + } + + /* + * Entry requests an initial value, allocate a + * descriptor for it. + */ + ObjDesc = AcpiUtCreateInternalObject (InitVal->Type); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* + * Convert value string from table entry to + * internal representation. Only types actually + * used for initial values are implemented here. + */ + switch (InitVal->Type) + { + case ACPI_TYPE_METHOD: + ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val); + ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; + +#if defined (ACPI_ASL_COMPILER) + + /* Save the parameter count for the iASL compiler */ + + NewNode->Value = ObjDesc->Method.ParamCount; +#else + /* Mark this as a very SPECIAL method */ + + ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY; + ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation; +#endif + break; + + case ACPI_TYPE_INTEGER: + + ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val); + break; + + + case ACPI_TYPE_STRING: + + /* Build an object around the static string */ + + ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val); + ObjDesc->String.Pointer = Val; + ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; + break; + + + case ACPI_TYPE_MUTEX: + + ObjDesc->Mutex.Node = NewNode; + ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1); + + /* Create a mutex */ + + Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ObjDesc); + goto UnlockAndExit; + } + + /* Special case for ACPI Global Lock */ + + if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0) + { + AcpiGbl_GlobalLockMutex = ObjDesc; + + /* Create additional counting semaphore for global lock */ + + Status = AcpiOsCreateSemaphore ( + 1, 0, &AcpiGbl_GlobalLockSemaphore); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ObjDesc); + goto UnlockAndExit; + } + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X", + InitVal->Type)); + AcpiUtRemoveReference (ObjDesc); + ObjDesc = NULL; + continue; + } + + /* Store pointer to value descriptor in the Node */ + + Status = AcpiNsAttachObject (NewNode, ObjDesc, + ObjDesc->Common.Type); + + /* Remove local reference to the object */ + + AcpiUtRemoveReference (ObjDesc); + } + } + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + /* Save a handle to "_GPE", it is always present */ + + if (ACPI_SUCCESS (Status)) + { + Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, + &AcpiGbl_FadtGpeDevice); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsLookup + * + * PARAMETERS: ScopeInfo - Current scope info block + * Pathname - Search pathname, in internal format + * (as represented in the AML stream) + * Type - Type associated with name + * InterpreterMode - IMODE_LOAD_PASS2 => add name if not found + * Flags - Flags describing the search restrictions + * WalkState - Current state of the walk + * ReturnNode - Where the Node is placed (if found + * or created successfully) + * + * RETURN: Status + * + * DESCRIPTION: Find or enter the passed name in the name space. + * Log an error if name not found in Exec mode. + * + * MUTEX: Assumes namespace is locked. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsLookup ( + ACPI_GENERIC_STATE *ScopeInfo, + char *Pathname, + ACPI_OBJECT_TYPE Type, + ACPI_INTERPRETER_MODE InterpreterMode, + UINT32 Flags, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_STATUS Status; + char *Path = Pathname; + ACPI_NAMESPACE_NODE *PrefixNode; + ACPI_NAMESPACE_NODE *CurrentNode = NULL; + ACPI_NAMESPACE_NODE *ThisNode = NULL; + UINT32 NumSegments; + UINT32 NumCarats; + ACPI_NAME SimpleName; + ACPI_OBJECT_TYPE TypeToCheckFor; + ACPI_OBJECT_TYPE ThisSearchType; + UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; + UINT32 LocalFlags; + + + ACPI_FUNCTION_TRACE (NsLookup); + + + if (!ReturnNode) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); + *ReturnNode = ACPI_ENTRY_NOT_FOUND; + AcpiGbl_NsLookupCount++; + + if (!AcpiGbl_RootNode) + { + return_ACPI_STATUS (AE_NO_NAMESPACE); + } + + /* Get the prefix scope. A null scope means use the root scope */ + + if ((!ScopeInfo) || + (!ScopeInfo->Scope.Node)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Null scope prefix, using root node (%p)\n", + AcpiGbl_RootNode)); + + PrefixNode = AcpiGbl_RootNode; + } + else + { + PrefixNode = ScopeInfo->Scope.Node; + if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) + { + ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", + PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) + { + /* + * This node might not be a actual "scope" node (such as a + * Device/Method, etc.) It could be a Package or other object + * node. Backup up the tree to find the containing scope node. + */ + while (!AcpiNsOpensScope (PrefixNode->Type) && + PrefixNode->Type != ACPI_TYPE_ANY) + { + PrefixNode = PrefixNode->Parent; + } + } + } + + /* Save type. TBD: may be no longer necessary */ + + TypeToCheckFor = Type; + + /* + * Begin examination of the actual pathname + */ + if (!Pathname) + { + /* A Null NamePath is allowed and refers to the root */ + + NumSegments = 0; + ThisNode = AcpiGbl_RootNode; + Path = ""; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Null Pathname (Zero segments), Flags=%X\n", Flags)); + } + else + { + /* + * Name pointer is valid (and must be in internal name format) + * + * Check for scope prefixes: + * + * As represented in the AML stream, a namepath consists of an + * optional scope prefix followed by a name segment part. + * + * If present, the scope prefix is either a Root Prefix (in + * which case the name is fully qualified), or one or more + * Parent Prefixes (in which case the name's scope is relative + * to the current scope). + */ + if (*Path == (UINT8) AML_ROOT_PREFIX) + { + /* Pathname is fully qualified, start from the root */ + + ThisNode = AcpiGbl_RootNode; + SearchParentFlag = ACPI_NS_NO_UPSEARCH; + + /* Point to name segment part */ + + Path++; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Path is absolute from root [%p]\n", ThisNode)); + } + else + { + /* Pathname is relative to current scope, start there */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Searching relative to prefix scope [%4.4s] (%p)\n", + AcpiUtGetNodeName (PrefixNode), PrefixNode)); + + /* + * Handle multiple Parent Prefixes (carat) by just getting + * the parent node for each prefix instance. + */ + ThisNode = PrefixNode; + NumCarats = 0; + while (*Path == (UINT8) AML_PARENT_PREFIX) + { + /* Name is fully qualified, no search rules apply */ + + SearchParentFlag = ACPI_NS_NO_UPSEARCH; + + /* + * Point past this prefix to the name segment + * part or the next Parent Prefix + */ + Path++; + + /* Backup to the parent node */ + + NumCarats++; + ThisNode = ThisNode->Parent; + if (!ThisNode) + { + /* Current scope has no parent scope */ + + ACPI_ERROR ((AE_INFO, + "ACPI path has too many parent prefixes (^) " + "- reached beyond root node")); + return_ACPI_STATUS (AE_NOT_FOUND); + } + } + + if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Search scope is [%4.4s], path has %u carat(s)\n", + AcpiUtGetNodeName (ThisNode), NumCarats)); + } + } + + /* + * Determine the number of ACPI name segments in this pathname. + * + * The segment part consists of either: + * - A Null name segment (0) + * - A DualNamePrefix followed by two 4-byte name segments + * - A MultiNamePrefix followed by a byte indicating the + * number of segments and the segments themselves. + * - A single 4-byte name segment + * + * Examine the name prefix opcode, if any, to determine the number of + * segments. + */ + switch (*Path) + { + case 0: + /* + * Null name after a root or parent prefixes. We already + * have the correct target node and there are no name segments. + */ + NumSegments = 0; + Type = ThisNode->Type; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Prefix-only Pathname (Zero name segments), Flags=%X\n", + Flags)); + break; + + case AML_DUAL_NAME_PREFIX: + + /* More than one NameSeg, search rules do not apply */ + + SearchParentFlag = ACPI_NS_NO_UPSEARCH; + + /* Two segments, point to first name segment */ + + NumSegments = 2; + Path++; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Dual Pathname (2 segments, Flags=%X)\n", Flags)); + break; + + case AML_MULTI_NAME_PREFIX_OP: + + /* More than one NameSeg, search rules do not apply */ + + SearchParentFlag = ACPI_NS_NO_UPSEARCH; + + /* Extract segment count, point to first name segment */ + + Path++; + NumSegments = (UINT32) (UINT8) *Path; + Path++; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Multi Pathname (%u Segments, Flags=%X)\n", + NumSegments, Flags)); + break; + + default: + /* + * Not a Null name, no Dual or Multi prefix, hence there is + * only one name segment and Pathname is already pointing to it. + */ + NumSegments = 1; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Simple Pathname (1 segment, Flags=%X)\n", Flags)); + break; + } + + ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); + } + + + /* + * Search namespace for each segment of the name. Loop through and + * verify (or add to the namespace) each name segment. + * + * The object type is significant only at the last name + * segment. (We don't care about the types along the path, only + * the type of the final target object.) + */ + ThisSearchType = ACPI_TYPE_ANY; + CurrentNode = ThisNode; + while (NumSegments && CurrentNode) + { + NumSegments--; + if (!NumSegments) + { + /* This is the last segment, enable typechecking */ + + ThisSearchType = Type; + + /* + * Only allow automatic parent search (search rules) if the caller + * requested it AND we have a single, non-fully-qualified NameSeg + */ + if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && + (Flags & ACPI_NS_SEARCH_PARENT)) + { + LocalFlags |= ACPI_NS_SEARCH_PARENT; + } + + /* Set error flag according to caller */ + + if (Flags & ACPI_NS_ERROR_IF_FOUND) + { + LocalFlags |= ACPI_NS_ERROR_IF_FOUND; + } + } + + /* Extract one ACPI name from the front of the pathname */ + + ACPI_MOVE_32_TO_32 (&SimpleName, Path); + + /* Try to find the single (4 character) ACPI name */ + + Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, + InterpreterMode, ThisSearchType, LocalFlags, &ThisNode); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + /* Name not found in ACPI namespace */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name [%4.4s] not found in scope [%4.4s] %p\n", + (char *) &SimpleName, (char *) &CurrentNode->Name, + CurrentNode)); + } + + *ReturnNode = ThisNode; + return_ACPI_STATUS (Status); + } + + /* More segments to follow? */ + + if (NumSegments > 0) + { + /* + * If we have an alias to an object that opens a scope (such as a + * device or processor), we need to dereference the alias here so + * that we can access any children of the original node (via the + * remaining segments). + */ + if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) + { + if (!ThisNode->Object) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) + ThisNode->Object)->Type)) + { + ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; + } + } + } + + /* Special handling for the last segment (NumSegments == 0) */ + + else + { + /* + * Sanity typecheck of the target object: + * + * If 1) This is the last segment (NumSegments == 0) + * 2) And we are looking for a specific type + * (Not checking for TYPE_ANY) + * 3) Which is not an alias + * 4) Which is not a local type (TYPE_SCOPE) + * 5) And the type of target object is known (not TYPE_ANY) + * 6) And target object does not match what we are looking for + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((TypeToCheckFor != ACPI_TYPE_ANY) && + (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && + (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && + (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && + (ThisNode->Type != ACPI_TYPE_ANY) && + (ThisNode->Type != TypeToCheckFor)) + { + /* Complain about a type mismatch */ + + ACPI_WARNING ((AE_INFO, + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", + ACPI_CAST_PTR (char, &SimpleName), + AcpiUtGetTypeName (ThisNode->Type), + AcpiUtGetTypeName (TypeToCheckFor))); + } + + /* + * If this is the last name segment and we are not looking for a + * specific type, but the type of found object is known, use that + * type to (later) see if it opens a scope. + */ + if (Type == ACPI_TYPE_ANY) + { + Type = ThisNode->Type; + } + } + + /* Point to next name segment and make this node current */ + + Path += ACPI_NAME_SIZE; + CurrentNode = ThisNode; + } + + /* Always check if we need to open a new scope */ + + if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState)) + { + /* + * If entry is a type which opens a scope, push the new scope on the + * scope stack. + */ + if (AcpiNsOpensScope (Type)) + { + Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + + *ReturnNode = ThisNode; + return_ACPI_STATUS (AE_OK); +} + diff --git a/source/components/namespace/nsalloc.c b/source/components/namespace/nsalloc.c new file mode 100644 index 000000000000..c7e83e0eb49c --- /dev/null +++ b/source/components/namespace/nsalloc.c @@ -0,0 +1,588 @@ +/******************************************************************************* + * + * Module Name: nsalloc - Namespace allocation and deletion utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSALLOC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsalloc") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCreateNode + * + * PARAMETERS: Name - Name of the new node (4 char ACPI name) + * + * RETURN: New namespace node (Null on failure) + * + * DESCRIPTION: Create a namespace node + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiNsCreateNode ( + UINT32 Name) +{ + ACPI_NAMESPACE_NODE *Node; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + UINT32 Temp; +#endif + + + ACPI_FUNCTION_TRACE (NsCreateNode); + + + Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache); + if (!Node) + { + return_PTR (NULL); + } + + ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + Temp = AcpiGbl_NsNodeList->TotalAllocated - + AcpiGbl_NsNodeList->TotalFreed; + if (Temp > AcpiGbl_NsNodeList->MaxOccupied) + { + AcpiGbl_NsNodeList->MaxOccupied = Temp; + } +#endif + + Node->Name.Integer = Name; + ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED); + return_PTR (Node); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDeleteNode + * + * PARAMETERS: Node - Node to be deleted + * + * RETURN: None + * + * DESCRIPTION: Delete a namespace node. All node deletions must come through + * here. Detaches any attached objects, including any attached + * data. If a handler is associated with attached data, it is + * invoked before the node is deleted. + * + ******************************************************************************/ + +void +AcpiNsDeleteNode ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_NAME (NsDeleteNode); + + + /* Detach an object if there is one */ + + AcpiNsDetachObject (Node); + + /* + * Delete an attached data object if present (an object that was created + * and attached via AcpiAttachData). Note: After any normal object is + * detached above, the only possible remaining object is a data object. + */ + ObjDesc = Node->Object; + if (ObjDesc && + (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) + { + /* Invoke the attached data deletion handler if present */ + + if (ObjDesc->Data.Handler) + { + ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer); + } + + AcpiUtRemoveReference (ObjDesc); + } + + /* Now we can delete the node */ + + (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node); + + ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", + Node, AcpiGbl_CurrentNodeCount)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRemoveNode + * + * PARAMETERS: Node - Node to be removed/deleted + * + * RETURN: None + * + * DESCRIPTION: Remove (unlink) and delete a namespace node + * + ******************************************************************************/ + +void +AcpiNsRemoveNode ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_NAMESPACE_NODE *PrevNode; + ACPI_NAMESPACE_NODE *NextNode; + + + ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node); + + + ParentNode = Node->Parent; + + PrevNode = NULL; + NextNode = ParentNode->Child; + + /* Find the node that is the previous peer in the parent's child list */ + + while (NextNode != Node) + { + PrevNode = NextNode; + NextNode = NextNode->Peer; + } + + if (PrevNode) + { + /* Node is not first child, unlink it */ + + PrevNode->Peer = Node->Peer; + } + else + { + /* + * Node is first child (has no previous peer). + * Link peer list to parent + */ + ParentNode->Child = Node->Peer; + } + + /* Delete the node and any attached objects */ + + AcpiNsDeleteNode (Node); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInstallNode + * + * PARAMETERS: WalkState - Current state of the walk + * ParentNode - The parent of the new Node + * Node - The new Node to install + * Type - ACPI object type of the new Node + * + * RETURN: None + * + * DESCRIPTION: Initialize a new namespace node and install it amongst + * its peers. + * + * Note: Current namespace lookup is linear search. This appears + * to be sufficient as namespace searches consume only a small + * fraction of the execution time of the ACPI subsystem. + * + ******************************************************************************/ + +void +AcpiNsInstallNode ( + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *ParentNode, /* Parent */ + ACPI_NAMESPACE_NODE *Node, /* New Child*/ + ACPI_OBJECT_TYPE Type) +{ + ACPI_OWNER_ID OwnerId = 0; + ACPI_NAMESPACE_NODE *ChildNode; + + + ACPI_FUNCTION_TRACE (NsInstallNode); + + + if (WalkState) + { + /* + * Get the owner ID from the Walk state. The owner ID is used to + * track table deletion and deletion of objects created by methods. + */ + OwnerId = WalkState->OwnerId; + + if ((WalkState->MethodDesc) && + (ParentNode != WalkState->MethodNode)) + { + /* + * A method is creating a new node that is not a child of the + * method (it is non-local). Mark the executing method as having + * modified the namespace. This is used for cleanup when the + * method exits. + */ + WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_MODIFIED_NAMESPACE; + } + } + + /* Link the new entry into the parent and existing children */ + + Node->Peer = NULL; + Node->Parent = ParentNode; + ChildNode = ParentNode->Child; + + if (!ChildNode) + { + ParentNode->Child = Node; + } + else + { + /* Add node to the end of the peer list */ + + while (ChildNode->Peer) + { + ChildNode = ChildNode->Peer; + } + + ChildNode->Peer = Node; + } + + /* Init the new entry */ + + Node->OwnerId = OwnerId; + Node->Type = (UINT8) Type; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId, + AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type), + ParentNode)); + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDeleteChildren + * + * PARAMETERS: ParentNode - Delete this objects children + * + * RETURN: None. + * + * DESCRIPTION: Delete all children of the parent object. In other words, + * deletes a "scope". + * + ******************************************************************************/ + +void +AcpiNsDeleteChildren ( + ACPI_NAMESPACE_NODE *ParentNode) +{ + ACPI_NAMESPACE_NODE *NextNode; + ACPI_NAMESPACE_NODE *NodeToDelete; + + + ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode); + + + if (!ParentNode) + { + return_VOID; + } + + /* Deallocate all children at this level */ + + NextNode = ParentNode->Child; + while (NextNode) + { + /* Grandchildren should have all been deleted already */ + + if (NextNode->Child) + { + ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p", + ParentNode, NextNode)); + } + + /* + * Delete this child node and move on to the next child in the list. + * No need to unlink the node since we are deleting the entire branch. + */ + NodeToDelete = NextNode; + NextNode = NextNode->Peer; + AcpiNsDeleteNode (NodeToDelete); + }; + + /* Clear the parent's child pointer */ + + ParentNode->Child = NULL; + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDeleteNamespaceSubtree + * + * PARAMETERS: ParentNode - Root of the subtree to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects + * stored within the subtree. + * + ******************************************************************************/ + +void +AcpiNsDeleteNamespaceSubtree ( + ACPI_NAMESPACE_NODE *ParentNode) +{ + ACPI_NAMESPACE_NODE *ChildNode = NULL; + UINT32 Level = 1; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); + + + if (!ParentNode) + { + return_VOID; + } + + /* Lock namespace for possible update */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + while (Level > 0) + { + /* Get the next node in this scope (NULL if none) */ + + ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); + if (ChildNode) + { + /* Found a child node - detach any attached object */ + + AcpiNsDetachObject (ChildNode); + + /* Check if this node has any children */ + + if (ChildNode->Child) + { + /* + * There is at least one child of this node, + * visit the node + */ + Level++; + ParentNode = ChildNode; + ChildNode = NULL; + } + } + else + { + /* + * No more children of this parent node. + * Move up to the grandparent. + */ + Level--; + + /* + * Now delete all of the children of this parent + * all at the same time. + */ + AcpiNsDeleteChildren (ParentNode); + + /* New "last child" is this parent node */ + + ChildNode = ParentNode; + + /* Move up the tree to the grandparent */ + + ParentNode = ParentNode->Parent; + } + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDeleteNamespaceByOwner + * + * PARAMETERS: OwnerId - All nodes with this owner will be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete entries within the namespace that are owned by a + * specific ID. Used to delete entire ACPI tables. All + * reference counts are updated. + * + * MUTEX: Locks namespace during deletion walk. + * + ******************************************************************************/ + +void +AcpiNsDeleteNamespaceByOwner ( + ACPI_OWNER_ID OwnerId) +{ + ACPI_NAMESPACE_NODE *ChildNode; + ACPI_NAMESPACE_NODE *DeletionNode; + ACPI_NAMESPACE_NODE *ParentNode; + UINT32 Level; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId); + + + if (OwnerId == 0) + { + return_VOID; + } + + /* Lock namespace for possible update */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + DeletionNode = NULL; + ParentNode = AcpiGbl_RootNode; + ChildNode = NULL; + Level = 1; + + /* + * Traverse the tree of nodes until we bubble back up + * to where we started. + */ + while (Level > 0) + { + /* + * Get the next child of this parent node. When ChildNode is NULL, + * the first child of the parent is returned + */ + ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); + + if (DeletionNode) + { + AcpiNsDeleteChildren (DeletionNode); + AcpiNsRemoveNode (DeletionNode); + DeletionNode = NULL; + } + + if (ChildNode) + { + if (ChildNode->OwnerId == OwnerId) + { + /* Found a matching child node - detach any attached object */ + + AcpiNsDetachObject (ChildNode); + } + + /* Check if this node has any children */ + + if (ChildNode->Child) + { + /* + * There is at least one child of this node, + * visit the node + */ + Level++; + ParentNode = ChildNode; + ChildNode = NULL; + } + else if (ChildNode->OwnerId == OwnerId) + { + DeletionNode = ChildNode; + } + } + else + { + /* + * No more children of this parent node. + * Move up to the grandparent. + */ + Level--; + if (Level != 0) + { + if (ParentNode->OwnerId == OwnerId) + { + DeletionNode = ParentNode; + } + } + + /* New "last child" is this parent node */ + + ChildNode = ParentNode; + + /* Move up the tree to the grandparent */ + + ParentNode = ParentNode->Parent; + } + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_VOID; +} + + diff --git a/source/components/namespace/nsdump.c b/source/components/namespace/nsdump.c new file mode 100644 index 000000000000..edc16257d4dd --- /dev/null +++ b/source/components/namespace/nsdump.c @@ -0,0 +1,769 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSDUMP_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsdump") + +/* Local prototypes */ + +#ifdef ACPI_OBSOLETE_FUNCTIONS +void +AcpiNsDumpRootDevices ( + void); + +static ACPI_STATUS +AcpiNsDumpOneDevice ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); +#endif + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/******************************************************************************* + * + * FUNCTION: AcpiNsPrintPathname + * + * PARAMETERS: NumSegments - Number of ACPI name segments + * Pathname - The compressed (internal) path + * + * RETURN: None + * + * DESCRIPTION: Print an object's full namespace pathname + * + ******************************************************************************/ + +void +AcpiNsPrintPathname ( + UINT32 NumSegments, + char *Pathname) +{ + UINT32 i; + + + ACPI_FUNCTION_NAME (NsPrintPathname); + + + if (!(AcpiDbgLevel & ACPI_LV_NAMES) || !(AcpiDbgLayer & ACPI_NAMESPACE)) + { + return; + } + + /* Print the entire name */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[")); + + while (NumSegments) + { + for (i = 0; i < 4; i++) + { + ACPI_IS_PRINT (Pathname[i]) ? + AcpiOsPrintf ("%c", Pathname[i]) : + AcpiOsPrintf ("?"); + } + + Pathname += ACPI_NAME_SIZE; + NumSegments--; + if (NumSegments) + { + AcpiOsPrintf ("."); + } + } + + AcpiOsPrintf ("]\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpPathname + * + * PARAMETERS: Handle - Object + * Msg - Prefix message + * Level - Desired debug level + * Component - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +void +AcpiNsDumpPathname ( + ACPI_HANDLE Handle, + char *Msg, + UINT32 Level, + UINT32 Component) +{ + + ACPI_FUNCTION_TRACE (NsDumpPathname); + + + /* Do this only if the requested debug level and component are enabled */ + + if (!(AcpiDbgLevel & Level) || !(AcpiDbgLayer & Component)) + { + return_VOID; + } + + /* Convert handle to a full pathname and print it (with supplied message) */ + + AcpiNsPrintNodePathname (Handle, Msg); + AcpiOsPrintf ("\n"); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpOneObject + * + * PARAMETERS: ObjHandle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into WalkNamespace + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump a single Node + * This procedure is a UserFunction called by AcpiNsWalkNamespace. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsDumpOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_WALK_INFO *Info = (ACPI_WALK_INFO *) Context; + ACPI_NAMESPACE_NODE *ThisNode; + ACPI_OPERAND_OBJECT *ObjDesc = NULL; + ACPI_OBJECT_TYPE ObjType; + ACPI_OBJECT_TYPE Type; + UINT32 BytesToDump; + UINT32 DbgLevel; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsDumpOneObject); + + + /* Is output enabled? */ + + if (!(AcpiDbgLevel & Info->DebugLevel)) + { + return (AE_OK); + } + + if (!ObjHandle) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n")); + return (AE_OK); + } + + ThisNode = AcpiNsValidateHandle (ObjHandle); + if (!ThisNode) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n", + ObjHandle)); + return (AE_OK); + } + + Type = ThisNode->Type; + + /* Check if the owner matches */ + + if ((Info->OwnerId != ACPI_OWNER_ID_MAX) && + (Info->OwnerId != ThisNode->OwnerId)) + { + return (AE_OK); + } + + if (!(Info->DisplayType & ACPI_DISPLAY_SHORT)) + { + /* Indent the object according to the level */ + + AcpiOsPrintf ("%2d%*s", (UINT32) Level - 1, (int) Level * 2, " "); + + /* Check the node type and name */ + + if (Type > ACPI_TYPE_LOCAL_MAX) + { + ACPI_WARNING ((AE_INFO, "Invalid ACPI Object Type 0x%08X", Type)); + } + + AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (ThisNode)); + } + + /* Now we can print out the pertinent information */ + + AcpiOsPrintf (" %-12s %p %2.2X ", + AcpiUtGetTypeName (Type), ThisNode, ThisNode->OwnerId); + + DbgLevel = AcpiDbgLevel; + AcpiDbgLevel = 0; + ObjDesc = AcpiNsGetAttachedObject (ThisNode); + AcpiDbgLevel = DbgLevel; + + /* Temp nodes are those nodes created by a control method */ + + if (ThisNode->Flags & ANOBJ_TEMPORARY) + { + AcpiOsPrintf ("(T) "); + } + + switch (Info->DisplayType & ACPI_DISPLAY_MASK) + { + case ACPI_DISPLAY_SUMMARY: + + if (!ObjDesc) + { + /* No attached object, we are done */ + + AcpiOsPrintf ("\n"); + return (AE_OK); + } + + switch (Type) + { + case ACPI_TYPE_PROCESSOR: + + AcpiOsPrintf ("ID %X Len %.4X Addr %p\n", + ObjDesc->Processor.ProcId, ObjDesc->Processor.Length, + ACPI_CAST_PTR (void, ObjDesc->Processor.Address)); + break; + + + case ACPI_TYPE_DEVICE: + + AcpiOsPrintf ("Notify Object: %p\n", ObjDesc); + break; + + + case ACPI_TYPE_METHOD: + + AcpiOsPrintf ("Args %X Len %.4X Aml %p\n", + (UINT32) ObjDesc->Method.ParamCount, + ObjDesc->Method.AmlLength, ObjDesc->Method.AmlStart); + break; + + + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf ("= %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + + case ACPI_TYPE_PACKAGE: + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + AcpiOsPrintf ("Elements %.2X\n", + ObjDesc->Package.Count); + } + else + { + AcpiOsPrintf ("[Length not yet evaluated]\n"); + } + break; + + + case ACPI_TYPE_BUFFER: + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + AcpiOsPrintf ("Len %.2X", + ObjDesc->Buffer.Length); + + /* Dump some of the buffer */ + + if (ObjDesc->Buffer.Length > 0) + { + AcpiOsPrintf (" ="); + for (i = 0; (i < ObjDesc->Buffer.Length && i < 12); i++) + { + AcpiOsPrintf (" %.2hX", ObjDesc->Buffer.Pointer[i]); + } + } + AcpiOsPrintf ("\n"); + } + else + { + AcpiOsPrintf ("[Length not yet evaluated]\n"); + } + break; + + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("Len %.2X ", ObjDesc->String.Length); + AcpiUtPrintString (ObjDesc->String.Pointer, 32); + AcpiOsPrintf ("\n"); + break; + + + case ACPI_TYPE_REGION: + + AcpiOsPrintf ("[%s]", + AcpiUtGetRegionName (ObjDesc->Region.SpaceId)); + if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) + { + AcpiOsPrintf (" Addr %8.8X%8.8X Len %.4X\n", + ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), + ObjDesc->Region.Length); + } + else + { + AcpiOsPrintf (" [Address/Length not yet evaluated]\n"); + } + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + AcpiOsPrintf ("[%s]\n", AcpiUtGetReferenceName (ObjDesc)); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + if (ObjDesc->BufferField.BufferObj && + ObjDesc->BufferField.BufferObj->Buffer.Node) + { + AcpiOsPrintf ("Buf [%4.4s]", + AcpiUtGetNodeName ( + ObjDesc->BufferField.BufferObj->Buffer.Node)); + } + break; + + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + AcpiOsPrintf ("Rgn [%4.4s]", + AcpiUtGetNodeName ( + ObjDesc->CommonField.RegionObj->Region.Node)); + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]", + AcpiUtGetNodeName ( + ObjDesc->CommonField.RegionObj->Region.Node), + AcpiUtGetNodeName ( + ObjDesc->BankField.BankObj->CommonField.Node)); + break; + + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]", + AcpiUtGetNodeName ( + ObjDesc->IndexField.IndexObj->CommonField.Node), + AcpiUtGetNodeName ( + ObjDesc->IndexField.DataObj->CommonField.Node)); + break; + + + case ACPI_TYPE_LOCAL_ALIAS: + case ACPI_TYPE_LOCAL_METHOD_ALIAS: + + AcpiOsPrintf ("Target %4.4s (%p)\n", + AcpiUtGetNodeName (ObjDesc), ObjDesc); + break; + + default: + + AcpiOsPrintf ("Object %p\n", ObjDesc); + break; + } + + /* Common field handling */ + + switch (Type) + { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + AcpiOsPrintf (" Off %.3X Len %.2X Acc %.2hd\n", + (ObjDesc->CommonField.BaseByteOffset * 8) + + ObjDesc->CommonField.StartFieldBitOffset, + ObjDesc->CommonField.BitLength, + ObjDesc->CommonField.AccessByteWidth); + break; + + default: + break; + } + break; + + + case ACPI_DISPLAY_OBJECTS: + + AcpiOsPrintf ("O:%p", ObjDesc); + if (!ObjDesc) + { + /* No attached object, we are done */ + + AcpiOsPrintf ("\n"); + return (AE_OK); + } + + AcpiOsPrintf ("(R%u)", ObjDesc->Common.ReferenceCount); + + switch (Type) + { + case ACPI_TYPE_METHOD: + + /* Name is a Method and its AML offset/length are set */ + + AcpiOsPrintf (" M:%p-%X\n", ObjDesc->Method.AmlStart, + ObjDesc->Method.AmlLength); + break; + + case ACPI_TYPE_INTEGER: + + AcpiOsPrintf (" I:%8.8X8.8%X\n", + ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); + break; + + case ACPI_TYPE_STRING: + + AcpiOsPrintf (" S:%p-%X\n", ObjDesc->String.Pointer, + ObjDesc->String.Length); + break; + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf (" B:%p-%X\n", ObjDesc->Buffer.Pointer, + ObjDesc->Buffer.Length); + break; + + default: + + AcpiOsPrintf ("\n"); + break; + } + break; + + + default: + AcpiOsPrintf ("\n"); + break; + } + + /* If debug turned off, done */ + + if (!(AcpiDbgLevel & ACPI_LV_VALUES)) + { + return (AE_OK); + } + + /* If there is an attached object, display it */ + + DbgLevel = AcpiDbgLevel; + AcpiDbgLevel = 0; + ObjDesc = AcpiNsGetAttachedObject (ThisNode); + AcpiDbgLevel = DbgLevel; + + /* Dump attached objects */ + + while (ObjDesc) + { + ObjType = ACPI_TYPE_INVALID; + AcpiOsPrintf ("Attached Object %p: ", ObjDesc); + + /* Decode the type of attached object and dump the contents */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) + { + case ACPI_DESC_TYPE_NAMED: + + AcpiOsPrintf ("(Ptr to Node)\n"); + BytesToDump = sizeof (ACPI_NAMESPACE_NODE); + ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); + break; + + case ACPI_DESC_TYPE_OPERAND: + + ObjType = ObjDesc->Common.Type; + + if (ObjType > ACPI_TYPE_LOCAL_MAX) + { + AcpiOsPrintf ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n", + ObjType); + BytesToDump = 32; + } + else + { + AcpiOsPrintf ("(Pointer to ACPI Object type %.2X [%s])\n", + ObjType, AcpiUtGetTypeName (ObjType)); + BytesToDump = sizeof (ACPI_OPERAND_OBJECT); + } + + ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); + break; + + default: + + break; + } + + /* If value is NOT an internal object, we are done */ + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) + { + goto Cleanup; + } + + /* Valid object, get the pointer to next level, if any */ + + switch (ObjType) + { + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + /* + * NOTE: takes advantage of common fields between string/buffer + */ + BytesToDump = ObjDesc->String.Length; + ObjDesc = (void *) ObjDesc->String.Pointer; + AcpiOsPrintf ( "(Buffer/String pointer %p length %X)\n", + ObjDesc, BytesToDump); + ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); + goto Cleanup; + + case ACPI_TYPE_BUFFER_FIELD: + ObjDesc = (ACPI_OPERAND_OBJECT *) ObjDesc->BufferField.BufferObj; + break; + + case ACPI_TYPE_PACKAGE: + ObjDesc = (void *) ObjDesc->Package.Elements; + break; + + case ACPI_TYPE_METHOD: + ObjDesc = (void *) ObjDesc->Method.AmlStart; + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + ObjDesc = (void *) ObjDesc->Field.RegionObj; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + ObjDesc = (void *) ObjDesc->BankField.RegionObj; + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + ObjDesc = (void *) ObjDesc->IndexField.IndexObj; + break; + + default: + goto Cleanup; + } + + ObjType = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ + } + +Cleanup: + AcpiOsPrintf ("\n"); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpObjects + * + * PARAMETERS: Type - Object type to be dumped + * DisplayType - 0 or ACPI_DISPLAY_SUMMARY + * MaxDepth - Maximum depth of dump. Use ACPI_UINT32_MAX + * for an effectively unlimited depth. + * OwnerId - Dump only objects owned by this ID. Use + * ACPI_UINT32_MAX to match all owners. + * StartHandle - Where in namespace to start/end search + * + * RETURN: None + * + * DESCRIPTION: Dump typed objects within the loaded namespace. Uses + * AcpiNsWalkNamespace in conjunction with AcpiNsDumpOneObject. + * + ******************************************************************************/ + +void +AcpiNsDumpObjects ( + ACPI_OBJECT_TYPE Type, + UINT8 DisplayType, + UINT32 MaxDepth, + ACPI_OWNER_ID OwnerId, + ACPI_HANDLE StartHandle) +{ + ACPI_WALK_INFO Info; + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Just lock the entire namespace for the duration of the dump. + * We don't want any changes to the namespace during this time, + * especially the temporary nodes since we are going to display + * them also. + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not acquire namespace mutex\n"); + return; + } + + Info.DebugLevel = ACPI_LV_TABLES; + Info.OwnerId = OwnerId; + Info.DisplayType = DisplayType; + + (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth, + ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES, + AcpiNsDumpOneObject, NULL, (void *) &Info, NULL); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpEntry + * + * PARAMETERS: Handle - Node to be dumped + * DebugLevel - Output level + * + * RETURN: None + * + * DESCRIPTION: Dump a single Node + * + ******************************************************************************/ + +void +AcpiNsDumpEntry ( + ACPI_HANDLE Handle, + UINT32 DebugLevel) +{ + ACPI_WALK_INFO Info; + + + ACPI_FUNCTION_ENTRY (); + + + Info.DebugLevel = DebugLevel; + Info.OwnerId = ACPI_OWNER_ID_MAX; + Info.DisplayType = ACPI_DISPLAY_SUMMARY; + + (void) AcpiNsDumpOneObject (Handle, 1, &Info, NULL); +} + + +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpTables + * + * PARAMETERS: SearchBase - Root of subtree to be dumped, or + * NS_ALL to dump the entire namespace + * MaxDepth - Maximum depth of dump. Use INT_MAX + * for an effectively unlimited depth. + * + * RETURN: None + * + * DESCRIPTION: Dump the name space, or a portion of it. + * + ******************************************************************************/ + +void +AcpiNsDumpTables ( + ACPI_HANDLE SearchBase, + UINT32 MaxDepth) +{ + ACPI_HANDLE SearchHandle = SearchBase; + + + ACPI_FUNCTION_TRACE (NsDumpTables); + + + if (!AcpiGbl_RootNode) + { + /* + * If the name space has not been initialized, + * there is nothing to dump. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n")); + return_VOID; + } + + if (ACPI_NS_ALL == SearchBase) + { + /* Entire namespace */ + + SearchHandle = AcpiGbl_RootNode; + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n")); + } + + AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, MaxDepth, + ACPI_OWNER_ID_MAX, SearchHandle); + return_VOID; +} +#endif +#endif + diff --git a/source/components/namespace/nsdumpdv.c b/source/components/namespace/nsdumpdv.c new file mode 100644 index 000000000000..dde0a8d09abc --- /dev/null +++ b/source/components/namespace/nsdumpdv.c @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSDUMPDV_C__ + +#include "acpi.h" + + +/* TBD: This entire module is apparently obsolete and should be removed */ + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsdumpdv") + +#ifdef ACPI_OBSOLETE_FUNCTIONS +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#include "acnamesp.h" + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpOneDevice + * + * PARAMETERS: Handle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into WalkNamespace + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump a single Node that represents a device + * This procedure is a UserFunction called by AcpiNsWalkNamespace. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsDumpOneDevice ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_BUFFER Buffer; + ACPI_DEVICE_INFO *Info; + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsDumpOneDevice); + + + Status = AcpiNsDumpOneObject (ObjHandle, Level, Context, ReturnValue); + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiGetObjectInfo (ObjHandle, &Buffer); + if (ACPI_SUCCESS (Status)) + { + Info = Buffer.Pointer; + for (i = 0; i < Level; i++) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, + " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", + Info->HardwareId.Value, ACPI_FORMAT_UINT64 (Info->Address), + Info->CurrentStatus)); + ACPI_FREE (Info); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpRootDevices + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump all objects of type "device" + * + ******************************************************************************/ + +void +AcpiNsDumpRootDevices ( + void) +{ + ACPI_HANDLE SysBusHandle; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (NsDumpRootDevices); + + + /* Only dump the table if tracing is enabled */ + + if (!(ACPI_LV_TABLES & AcpiDbgLevel)) + { + return; + } + + Status = AcpiGetHandle (NULL, ACPI_NS_SYSTEM_BUS, &SysBusHandle); + if (ACPI_FAILURE (Status)) + { + return; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, + "Display of all devices in the namespace:\n")); + + Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, SysBusHandle, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + AcpiNsDumpOneDevice, NULL, NULL, NULL); +} + +#endif +#endif + + diff --git a/source/components/namespace/nseval.c b/source/components/namespace/nseval.c new file mode 100644 index 000000000000..0183f7e77441 --- /dev/null +++ b/source/components/namespace/nseval.c @@ -0,0 +1,485 @@ +/******************************************************************************* + * + * Module Name: nseval - Object evaluation, includes control method execution + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSEVAL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nseval") + +/* Local prototypes */ + +static void +AcpiNsExecModuleCode ( + ACPI_OPERAND_OBJECT *MethodObj, + ACPI_EVALUATE_INFO *Info); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsEvaluate + * + * PARAMETERS: Info - Evaluation info block, contains: + * PrefixNode - Prefix or Method/Object Node to execute + * Pathname - Name of method to execute, If NULL, the + * Node is the object to execute + * Parameters - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * ReturnObject - Where to put method's return value (if + * any). If NULL, no value is returned. + * ParameterType - Type of Parameter list + * ReturnObject - Where to put method's return value (if + * any). If NULL, no value is returned. + * Flags - ACPI_IGNORE_RETURN_VALUE to delete return + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method or return the current value of an + * ACPI namespace object. + * + * MUTEX: Locks interpreter + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsEvaluate ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (NsEvaluate); + + + if (!Info) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Initialize the return value to an invalid object */ + + Info->ReturnObject = NULL; + Info->ParamCount = 0; + + /* + * Get the actual namespace node for the target object. Handles these cases: + * + * 1) Null node, Pathname (absolute path) + * 2) Node, Pathname (path relative to Node) + * 3) Node, Null Pathname + */ + Status = AcpiNsGetNode (Info->PrefixNode, Info->Pathname, + ACPI_NS_NO_UPSEARCH, &Info->ResolvedNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * For a method alias, we must grab the actual method node so that proper + * scoping context will be established before execution. + */ + if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_LOCAL_METHOD_ALIAS) + { + Info->ResolvedNode = + ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Info->ResolvedNode->Object); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", Info->Pathname, + Info->ResolvedNode, AcpiNsGetAttachedObject (Info->ResolvedNode))); + + Node = Info->ResolvedNode; + + /* + * Two major cases here: + * + * 1) The object is a control method -- execute it + * 2) The object is not a method -- just return it's current value + */ + if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_METHOD) + { + /* + * 1) Object is a control method - execute it + */ + + /* Verify that there is a method object associated with this node */ + + Info->ObjDesc = AcpiNsGetAttachedObject (Info->ResolvedNode); + if (!Info->ObjDesc) + { + ACPI_ERROR ((AE_INFO, "Control method has no attached sub-object")); + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Count the number of arguments being passed to the method */ + + if (Info->Parameters) + { + while (Info->Parameters[Info->ParamCount]) + { + if (Info->ParamCount > ACPI_METHOD_MAX_ARG) + { + return_ACPI_STATUS (AE_LIMIT); + } + Info->ParamCount++; + } + } + + ACPI_DUMP_PATHNAME (Info->ResolvedNode, "ACPI: Execute Method", + ACPI_LV_INFO, _COMPONENT); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Method at AML address %p Length %X\n", + Info->ObjDesc->Method.AmlStart + 1, + Info->ObjDesc->Method.AmlLength - 1)); + + /* + * Any namespace deletion must acquire both the namespace and + * interpreter locks to ensure that no thread is using the portion of + * the namespace that is being deleted. + * + * Execute the method via the interpreter. The interpreter is locked + * here before calling into the AML parser + */ + AcpiExEnterInterpreter (); + Status = AcpiPsExecuteMethod (Info); + AcpiExExitInterpreter (); + } + else + { + /* + * 2) Object is not a method, return its current value + * + * Disallow certain object types. For these, "evaluation" is undefined. + */ + switch (Info->ResolvedNode->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + ACPI_ERROR ((AE_INFO, + "[%4.4s] Evaluation of object type [%s] is not supported", + Info->ResolvedNode->Name.Ascii, + AcpiUtGetTypeName (Info->ResolvedNode->Type))); + + return_ACPI_STATUS (AE_TYPE); + + default: + break; + } + + /* + * Objects require additional resolution steps (e.g., the Node may be + * a field that must be read, etc.) -- we can't just grab the object + * out of the node. + * + * Use ResolveNodeToValue() to get the associated value. + * + * NOTE: we can get away with passing in NULL for a walk state because + * ResolvedNode is guaranteed to not be a reference to either a method + * local or a method argument (because this interface is never called + * from a running method.) + * + * Even though we do not directly invoke the interpreter for object + * resolution, we must lock it because we could access an opregion. + * The opregion access code assumes that the interpreter is locked. + */ + AcpiExEnterInterpreter (); + + /* Function has a strange interface */ + + Status = AcpiExResolveNodeToValue (&Info->ResolvedNode, NULL); + AcpiExExitInterpreter (); + + /* + * If AcpiExResolveNodeToValue() succeeded, the return value was placed + * in ResolvedNode. + */ + if (ACPI_SUCCESS (Status)) + { + Status = AE_CTRL_RETURN_VALUE; + Info->ReturnObject = + ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->ResolvedNode); + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n", + Info->ReturnObject, + AcpiUtGetObjectTypeName (Info->ReturnObject))); + } + } + + /* + * Check input argument count against the ASL-defined count for a method. + * Also check predefined names: argument count and return value against + * the ACPI specification. Some incorrect return value types are repaired. + */ + (void) AcpiNsCheckPredefinedNames (Node, Info->ParamCount, + Status, &Info->ReturnObject); + + /* Check if there is a return value that must be dealt with */ + + if (Status == AE_CTRL_RETURN_VALUE) + { + /* If caller does not want the return value, delete it */ + + if (Info->Flags & ACPI_IGNORE_RETURN_VALUE) + { + AcpiUtRemoveReference (Info->ReturnObject); + Info->ReturnObject = NULL; + } + + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + Status = AE_OK; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", Info->Pathname)); + + /* + * Namespace was unlocked by the handling AcpiNs* function, so we + * just return + */ + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsExecModuleCodeList + * + * PARAMETERS: None + * + * RETURN: None. Exceptions during method execution are ignored, since + * we cannot abort a table load. + * + * DESCRIPTION: Execute all elements of the global module-level code list. + * Each element is executed as a single control method. + * + ******************************************************************************/ + +void +AcpiNsExecModuleCodeList ( + void) +{ + ACPI_OPERAND_OBJECT *Prev; + ACPI_OPERAND_OBJECT *Next; + ACPI_EVALUATE_INFO *Info; + UINT32 MethodCount = 0; + + + ACPI_FUNCTION_TRACE (NsExecModuleCodeList); + + + /* Exit now if the list is empty */ + + Next = AcpiGbl_ModuleCodeList; + if (!Next) + { + return_VOID; + } + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_VOID; + } + + /* Walk the list, executing each "method" */ + + while (Next) + { + Prev = Next; + Next = Next->Method.Mutex; + + /* Clear the link field and execute the method */ + + Prev->Method.Mutex = NULL; + AcpiNsExecModuleCode (Prev, Info); + MethodCount++; + + /* Delete the (temporary) method object */ + + AcpiUtRemoveReference (Prev); + } + + ACPI_INFO ((AE_INFO, + "Executed %u blocks of module-level executable AML code", + MethodCount)); + + ACPI_FREE (Info); + AcpiGbl_ModuleCodeList = NULL; + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsExecModuleCode + * + * PARAMETERS: MethodObj - Object container for the module-level code + * Info - Info block for method evaluation + * + * RETURN: None. Exceptions during method execution are ignored, since + * we cannot abort a table load. + * + * DESCRIPTION: Execute a control method containing a block of module-level + * executable AML code. The control method is temporarily + * installed to the root node, then evaluated. + * + ******************************************************************************/ + +static void +AcpiNsExecModuleCode ( + ACPI_OPERAND_OBJECT *MethodObj, + ACPI_EVALUATE_INFO *Info) +{ + ACPI_OPERAND_OBJECT *ParentObj; + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_OBJECT_TYPE Type; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsExecModuleCode); + + + /* + * Get the parent node. We cheat by using the NextObject field + * of the method object descriptor. + */ + ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, + MethodObj->Method.NextObject); + Type = AcpiNsGetType (ParentNode); + + /* + * Get the region handler and save it in the method object. We may need + * this if an operation region declaration causes a _REG method to be run. + * + * We can't do this in AcpiPsLinkModuleCode because + * AcpiGbl_RootNode->Object is NULL at PASS1. + */ + if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) + { + MethodObj->Method.Dispatch.Handler = + ParentNode->Object->Device.Handler; + } + + /* Must clear NextObject (AcpiNsAttachObject needs the field) */ + + MethodObj->Method.NextObject = NULL; + + /* Initialize the evaluation information block */ + + ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); + Info->PrefixNode = ParentNode; + + /* + * Get the currently attached parent object. Add a reference, because the + * ref count will be decreased when the method object is installed to + * the parent node. + */ + ParentObj = AcpiNsGetAttachedObject (ParentNode); + if (ParentObj) + { + AcpiUtAddReference (ParentObj); + } + + /* Install the method (module-level code) in the parent node */ + + Status = AcpiNsAttachObject (ParentNode, MethodObj, + ACPI_TYPE_METHOD); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Execute the parent node as a control method */ + + Status = AcpiNsEvaluate (Info); + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", + MethodObj->Method.AmlStart)); + + /* Delete a possible implicit return value (in slack mode) */ + + if (Info->ReturnObject) + { + AcpiUtRemoveReference (Info->ReturnObject); + } + + /* Detach the temporary method object */ + + AcpiNsDetachObject (ParentNode); + + /* Restore the original parent object */ + + if (ParentObj) + { + Status = AcpiNsAttachObject (ParentNode, ParentObj, Type); + } + else + { + ParentNode->Type = (UINT8) Type; + } + +Exit: + if (ParentObj) + { + AcpiUtRemoveReference (ParentObj); + } + return_VOID; +} + diff --git a/source/components/namespace/nsinit.c b/source/components/namespace/nsinit.c new file mode 100644 index 000000000000..f3907aafb3a4 --- /dev/null +++ b/source/components/namespace/nsinit.c @@ -0,0 +1,665 @@ +/****************************************************************************** + * + * Module Name: nsinit - namespace initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSXFINIT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdispat.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsinit") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsInitOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiNsInitOneDevice ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiNsFindIniMethods ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInitializeObjects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary + * initialization on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsInitializeObjects ( + void) +{ + ACPI_STATUS Status; + ACPI_INIT_WALK_INFO Info; + + + ACPI_FUNCTION_TRACE (NsInitializeObjects); + + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "**** Starting initialization of namespace objects ****\n")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Completing Region/Field/Buffer/Package initialization:")); + + /* Set all init info to zero */ + + ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + + /* Walk entire namespace from the supplied root */ + + Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL, + &Info, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "\nInitialized %u/%u Regions %u/%u Fields %u/%u " + "Buffers %u/%u Packages (%u nodes)\n", + Info.OpRegionInit, Info.OpRegionCount, + Info.FieldInit, Info.FieldCount, + Info.BufferInit, Info.BufferCount, + Info.PackageInit, Info.PackageCount, Info.ObjectCount)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "%u Control Methods found\n", Info.MethodCount)); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "%u Op Regions found\n", Info.OpRegionCount)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInitializeDevices + * + * PARAMETERS: None + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. + * This means running _INI on all present devices. + * + * Note: We install PCI config space handler on region access, + * not here. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsInitializeDevices ( + void) +{ + ACPI_STATUS Status; + ACPI_DEVICE_WALK_INFO Info; + + + ACPI_FUNCTION_TRACE (NsInitializeDevices); + + + /* Init counters */ + + Info.DeviceCount = 0; + Info.Num_STA = 0; + Info.Num_INI = 0; + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Initializing Device/Processor/Thermal objects " + "by executing _INI methods:")); + + /* Tree analysis: find all subtrees that contain _INI methods */ + + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + /* Allocate the evaluation information block */ + + Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info.EvaluateInfo) + { + Status = AE_NO_MEMORY; + goto ErrorExit; + } + + /* + * Execute the "global" _INI method that may appear at the root. This + * support is provided for Windows compatibility (Vista+) and is not + * part of the ACPI specification. + */ + Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode; + Info.EvaluateInfo->Pathname = METHOD_NAME__INI; + Info.EvaluateInfo->Parameters = NULL; + Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE; + + Status = AcpiNsEvaluate (Info.EvaluateInfo); + if (ACPI_SUCCESS (Status)) + { + Info.Num_INI++; + } + + /* Walk namespace to execute all _INIs on present devices */ + + Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL); + + /* + * Any _OSI requests should be completed by now. If the BIOS has + * requested any Windows OSI strings, we will always truncate + * I/O addresses to 16 bits -- for Windows compatibility. + */ + if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000) + { + AcpiGbl_TruncateIoAddresses = TRUE; + } + + ACPI_FREE (Info.EvaluateInfo); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "\nExecuted %u _INI methods requiring %u _STA executions " + "(examined %u objects)\n", + Info.Num_INI, Info.Num_STA, Info.DeviceCount)); + + return_ACPI_STATUS (Status); + + +ErrorExit: + ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization")); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInitOneObject + * + * PARAMETERS: ObjHandle - Node + * Level - Current nesting level + * Context - Points to a init info struct + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsInitOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_OBJECT_TYPE Type; + ACPI_STATUS Status = AE_OK; + ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_NAME (NsInitOneObject); + + + Info->ObjectCount++; + + /* And even then, we are only interested in a few object types */ + + Type = AcpiNsGetType (ObjHandle); + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return (AE_OK); + } + + /* Increment counters for object types we are looking for */ + + switch (Type) + { + case ACPI_TYPE_REGION: + Info->OpRegionCount++; + break; + + case ACPI_TYPE_BUFFER_FIELD: + Info->FieldCount++; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + Info->FieldCount++; + break; + + case ACPI_TYPE_BUFFER: + Info->BufferCount++; + break; + + case ACPI_TYPE_PACKAGE: + Info->PackageCount++; + break; + + default: + + /* No init required, just exit now */ + return (AE_OK); + } + + /* If the object is already initialized, nothing else to do */ + + if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) + { + return (AE_OK); + } + + /* Must lock the interpreter before executing AML code */ + + AcpiExEnterInterpreter (); + + /* + * Each of these types can contain executable AML code within the + * declaration. + */ + switch (Type) + { + case ACPI_TYPE_REGION: + + Info->OpRegionInit++; + Status = AcpiDsGetRegionArguments (ObjDesc); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + Info->FieldInit++; + Status = AcpiDsGetBufferFieldArguments (ObjDesc); + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + Info->FieldInit++; + Status = AcpiDsGetBankFieldArguments (ObjDesc); + break; + + case ACPI_TYPE_BUFFER: + + Info->BufferInit++; + Status = AcpiDsGetBufferArguments (ObjDesc); + break; + + case ACPI_TYPE_PACKAGE: + + Info->PackageInit++; + Status = AcpiDsGetPackageArguments (ObjDesc); + break; + + default: + /* No other types can get here */ + break; + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not execute arguments for [%4.4s] (%s)", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); + } + + /* + * Print a dot for each object unless we are going to print the entire + * pathname + */ + if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); + } + + /* + * We ignore errors from above, and always return OK, since we don't want + * to abort the walk on any single error. + */ + AcpiExExitInterpreter (); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsFindIniMethods + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Called during namespace walk. Finds objects named _INI under + * device/processor/thermal objects, and marks the entire subtree + * with a SUBTREE_HAS_INI flag. This flag is used during the + * subsequent device initialization walk to avoid entire subtrees + * that do not contain an _INI. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsFindIniMethods ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_DEVICE_WALK_INFO *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context); + ACPI_NAMESPACE_NODE *Node; + ACPI_NAMESPACE_NODE *ParentNode; + + + /* Keep count of device/processor/thermal objects */ + + Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + if ((Node->Type == ACPI_TYPE_DEVICE) || + (Node->Type == ACPI_TYPE_PROCESSOR) || + (Node->Type == ACPI_TYPE_THERMAL)) + { + Info->DeviceCount++; + return (AE_OK); + } + + /* We are only looking for methods named _INI */ + + if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI)) + { + return (AE_OK); + } + + /* + * The only _INI methods that we care about are those that are + * present under Device, Processor, and Thermal objects. + */ + ParentNode = Node->Parent; + switch (ParentNode->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Mark parent and bubble up the INI present flag to the root */ + + while (ParentNode) + { + ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI; + ParentNode = ParentNode->Parent; + } + break; + + default: + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInitOneDevice + * + * PARAMETERS: ACPI_WALK_CALLBACK + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: This is called once per device soon after ACPI is enabled + * to initialize each device. It determines if the device is + * present, and if so, calls _INI. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsInitOneDevice ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_DEVICE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context); + ACPI_EVALUATE_INFO *Info = WalkInfo->EvaluateInfo; + UINT32 Flags; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *DeviceNode; + + + ACPI_FUNCTION_TRACE (NsInitOneDevice); + + + /* We are interested in Devices, Processors and ThermalZones only */ + + DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + if ((DeviceNode->Type != ACPI_TYPE_DEVICE) && + (DeviceNode->Type != ACPI_TYPE_PROCESSOR) && + (DeviceNode->Type != ACPI_TYPE_THERMAL)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Because of an earlier namespace analysis, all subtrees that contain an + * _INI method are tagged. + * + * If this device subtree does not contain any _INI methods, we + * can exit now and stop traversing this entire subtree. + */ + if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI)) + { + return_ACPI_STATUS (AE_CTRL_DEPTH); + } + + /* + * Run _STA to determine if this device is present and functioning. We + * must know this information for two important reasons (from ACPI spec): + * + * 1) We can only run _INI if the device is present. + * 2) We must abort the device tree walk on this subtree if the device is + * not present and is not functional (we will not examine the children) + * + * The _STA method is not required to be present under the device, we + * assume the device is present if _STA does not exist. + */ + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname ( + ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA)); + + Status = AcpiUtExecute_STA (DeviceNode, &Flags); + if (ACPI_FAILURE (Status)) + { + /* Ignore error and move on to next device */ + + return_ACPI_STATUS (AE_OK); + } + + /* + * Flags == -1 means that _STA was not found. In this case, we assume that + * the device is both present and functional. + * + * From the ACPI spec, description of _STA: + * + * "If a device object (including the processor object) does not have an + * _STA object, then OSPM assumes that all of the above bits are set (in + * other words, the device is present, ..., and functioning)" + */ + if (Flags != ACPI_UINT32_MAX) + { + WalkInfo->Num_STA++; + } + + /* + * Examine the PRESENT and FUNCTIONING status bits + * + * Note: ACPI spec does not seem to specify behavior for the present but + * not functioning case, so we assume functioning if present. + */ + if (!(Flags & ACPI_STA_DEVICE_PRESENT)) + { + /* Device is not present, we must examine the Functioning bit */ + + if (Flags & ACPI_STA_DEVICE_FUNCTIONING) + { + /* + * Device is not present but is "functioning". In this case, + * we will not run _INI, but we continue to examine the children + * of this device. + * + * From the ACPI spec, description of _STA: (Note - no mention + * of whether to run _INI or not on the device in question) + * + * "_STA may return bit 0 clear (not present) with bit 3 set + * (device is functional). This case is used to indicate a valid + * device for which no device driver should be loaded (for example, + * a bridge device.) Children of this device may be present and + * valid. OSPM should continue enumeration below a device whose + * _STA returns this bit combination" + */ + return_ACPI_STATUS (AE_OK); + } + else + { + /* + * Device is not present and is not functioning. We must abort the + * walk of this subtree immediately -- don't look at the children + * of such a device. + * + * From the ACPI spec, description of _INI: + * + * "If the _STA method indicates that the device is not present, + * OSPM will not run the _INI and will not examine the children + * of the device for _INI methods" + */ + return_ACPI_STATUS (AE_CTRL_DEPTH); + } + } + + /* + * The device is present or is assumed present if no _STA exists. + * Run the _INI if it exists (not required to exist) + * + * Note: We know there is an _INI within this subtree, but it may not be + * under this particular device, it may be lower in the branch. + */ + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname ( + ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI)); + + Info->PrefixNode = DeviceNode; + Info->Pathname = METHOD_NAME__INI; + Info->Parameters = NULL; + Info->Flags = ACPI_IGNORE_RETURN_VALUE; + + Status = AcpiNsEvaluate (Info); + if (ACPI_SUCCESS (Status)) + { + WalkInfo->Num_INI++; + + if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) && + (!(AcpiDbgLevel & ACPI_LV_INFO))) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); + } + } + +#ifdef ACPI_DEBUG_OUTPUT + else if (Status != AE_NOT_FOUND) + { + /* Ignore error and move on to next device */ + + char *ScopeName = AcpiNsGetExternalPathname (Info->ResolvedNode); + + ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution", + ScopeName)); + ACPI_FREE (ScopeName); + } +#endif + + /* Ignore errors from above */ + + Status = AE_OK; + + /* + * The _INI method has been run if present; call the Global Initialization + * Handler for this device. + */ + if (AcpiGbl_InitHandler) + { + Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI); + } + + return_ACPI_STATUS (Status); +} diff --git a/source/components/namespace/nsload.c b/source/components/namespace/nsload.c new file mode 100644 index 000000000000..3ef33f9ce9d9 --- /dev/null +++ b/source/components/namespace/nsload.c @@ -0,0 +1,356 @@ +/****************************************************************************** + * + * Module Name: nsload - namespace loading/expanding/contracting procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSLOAD_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdispat.h" +#include "actables.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsload") + +/* Local prototypes */ + +#ifdef ACPI_FUTURE_IMPLEMENTATION +ACPI_STATUS +AcpiNsUnloadNamespace ( + ACPI_HANDLE Handle); + +static ACPI_STATUS +AcpiNsDeleteSubtree ( + ACPI_HANDLE StartHandle); +#endif + + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: AcpiNsLoadTable + * + * PARAMETERS: TableIndex - Index for table to be loaded + * Node - Owning NS node + * + * RETURN: Status + * + * DESCRIPTION: Load one ACPI table into the namespace + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsLoadTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsLoadTable); + + + /* + * Parse the table and load the namespace with all named + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be + * parsed until the entire namespace is loaded, because + * if a control method makes a forward reference (call) + * to another control method, we can't continue parsing + * because we don't know how many arguments to parse next! + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* If table already loaded into namespace, just return */ + + if (AcpiTbIsTableLoaded (TableIndex)) + { + Status = AE_ALREADY_EXISTS; + goto Unlock; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "**** Loading table into namespace ****\n")); + + Status = AcpiTbAllocateOwnerId (TableIndex); + if (ACPI_FAILURE (Status)) + { + goto Unlock; + } + + Status = AcpiNsParseTable (TableIndex, Node); + if (ACPI_SUCCESS (Status)) + { + AcpiTbSetTableLoadedFlag (TableIndex, TRUE); + } + else + { + (void) AcpiTbReleaseOwnerId (TableIndex); + } + +Unlock: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Now we can parse the control methods. We always parse + * them here for a sanity check, and if configured for + * just-in-time parsing, we delete the control method + * parse trees. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "**** Begin Table Method Parsing and Object Initialization\n")); + + Status = AcpiDsInitializeObjects (TableIndex, Node); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "**** Completed Table Method Parsing and Object Initialization\n")); + + return_ACPI_STATUS (Status); +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiLoadNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsLoadNamespace ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLoadNameSpace); + + + /* There must be at least a DSDT installed */ + + if (AcpiGbl_DSDT == NULL) + { + ACPI_ERROR ((AE_INFO, "DSDT is not in memory")); + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Ignore exceptions from these */ + + (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT); + (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT); + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "ACPI Namespace successfully loaded at root %p\n", + AcpiGbl_RootNode)); + + return_ACPI_STATUS (Status); +} +#endif + +#ifdef ACPI_FUTURE_IMPLEMENTATION +/******************************************************************************* + * + * FUNCTION: AcpiNsDeleteSubtree + * + * PARAMETERS: StartHandle - Handle in namespace where search begins + * + * RETURNS Status + * + * DESCRIPTION: Walks the namespace starting at the given handle and deletes + * all objects, entries, and scopes in the entire subtree. + * + * Namespace/Interpreter should be locked or the subsystem should + * be in shutdown before this routine is called. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsDeleteSubtree ( + ACPI_HANDLE StartHandle) +{ + ACPI_STATUS Status; + ACPI_HANDLE ChildHandle; + ACPI_HANDLE ParentHandle; + ACPI_HANDLE NextChildHandle; + ACPI_HANDLE Dummy; + UINT32 Level; + + + ACPI_FUNCTION_TRACE (NsDeleteSubtree); + + + ParentHandle = StartHandle; + ChildHandle = NULL; + Level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + while (Level > 0) + { + /* Attempt to get the next object in this scope */ + + Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle, + ChildHandle, &NextChildHandle); + + ChildHandle = NextChildHandle; + + /* Did we get a new object? */ + + if (ACPI_SUCCESS (Status)) + { + /* Check if this object has any children */ + + if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle, + NULL, &Dummy))) + { + /* + * There is at least one child of this object, + * visit the object + */ + Level++; + ParentHandle = ChildHandle; + ChildHandle = NULL; + } + } + else + { + /* + * No more children in this object, go back up to + * the object's parent + */ + Level--; + + /* Delete all children now */ + + AcpiNsDeleteChildren (ChildHandle); + + ChildHandle = ParentHandle; + Status = AcpiGetParent (ParentHandle, &ParentHandle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + } + + /* Now delete the starting object, and we are done */ + + AcpiNsRemoveNode (ChildHandle); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsUnloadNameSpace + * + * PARAMETERS: Handle - Root of namespace subtree to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Shrinks the namespace, typically in response to an undocking + * event. Deletes an entire subtree starting from (and + * including) the given handle. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsUnloadNamespace ( + ACPI_HANDLE Handle) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsUnloadNameSpace); + + + /* Parameter validation */ + + if (!AcpiGbl_RootNode) + { + return_ACPI_STATUS (AE_NO_NAMESPACE); + } + + if (!Handle) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* This function does the real work */ + + Status = AcpiNsDeleteSubtree (Handle); + + return_ACPI_STATUS (Status); +} +#endif +#endif + diff --git a/source/components/namespace/nsnames.c b/source/components/namespace/nsnames.c new file mode 100644 index 000000000000..f70900da1d1a --- /dev/null +++ b/source/components/namespace/nsnames.c @@ -0,0 +1,303 @@ +/******************************************************************************* + * + * Module Name: nsnames - Name manipulation and search + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSNAMES_C__ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsnames") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsBuildExternalPath + * + * PARAMETERS: Node - NS node whose pathname is needed + * Size - Size of the pathname + * *NameBuffer - Where to return the pathname + * + * RETURN: Status + * Places the pathname into the NameBuffer, in external format + * (name segments separated by path separators) + * + * DESCRIPTION: Generate a full pathaname + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsBuildExternalPath ( + ACPI_NAMESPACE_NODE *Node, + ACPI_SIZE Size, + char *NameBuffer) +{ + ACPI_SIZE Index; + ACPI_NAMESPACE_NODE *ParentNode; + + + ACPI_FUNCTION_ENTRY (); + + + /* Special case for root */ + + Index = Size - 1; + if (Index < ACPI_NAME_SIZE) + { + NameBuffer[0] = AML_ROOT_PREFIX; + NameBuffer[1] = 0; + return (AE_OK); + } + + /* Store terminator byte, then build name backwards */ + + ParentNode = Node; + NameBuffer[Index] = 0; + + while ((Index > ACPI_NAME_SIZE) && (ParentNode != AcpiGbl_RootNode)) + { + Index -= ACPI_NAME_SIZE; + + /* Put the name into the buffer */ + + ACPI_MOVE_32_TO_32 ((NameBuffer + Index), &ParentNode->Name); + ParentNode = ParentNode->Parent; + + /* Prefix name with the path separator */ + + Index--; + NameBuffer[Index] = ACPI_PATH_SEPARATOR; + } + + /* Overwrite final separator with the root prefix character */ + + NameBuffer[Index] = AML_ROOT_PREFIX; + + if (Index != 0) + { + ACPI_ERROR ((AE_INFO, + "Could not construct external pathname; index=%u, size=%u, Path=%s", + (UINT32) Index, (UINT32) Size, &NameBuffer[Size])); + + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetExternalPathname + * + * PARAMETERS: Node - Namespace node whose pathname is needed + * + * RETURN: Pointer to storage containing the fully qualified name of + * the node, In external format (name segments separated by path + * separators.) + * + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. + * + ******************************************************************************/ + +char * +AcpiNsGetExternalPathname ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_STATUS Status; + char *NameBuffer; + ACPI_SIZE Size; + + + ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname, Node); + + + /* Calculate required buffer size based on depth below root */ + + Size = AcpiNsGetPathnameLength (Node); + if (!Size) + { + return_PTR (NULL); + } + + /* Allocate a buffer to be returned to caller */ + + NameBuffer = ACPI_ALLOCATE_ZEROED (Size); + if (!NameBuffer) + { + ACPI_ERROR ((AE_INFO, "Could not allocate %u bytes", (UINT32) Size)); + return_PTR (NULL); + } + + /* Build the path in the allocated buffer */ + + Status = AcpiNsBuildExternalPath (Node, Size, NameBuffer); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (NameBuffer); + return_PTR (NULL); + } + + return_PTR (NameBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetPathnameLength + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Length of path, including prefix + * + * DESCRIPTION: Get the length of the pathname string for this node + * + ******************************************************************************/ + +ACPI_SIZE +AcpiNsGetPathnameLength ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_SIZE Size; + ACPI_NAMESPACE_NODE *NextNode; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Compute length of pathname as 5 * number of name segments. + * Go back up the parent tree to the root + */ + Size = 0; + NextNode = Node; + + while (NextNode && (NextNode != AcpiGbl_RootNode)) + { + if (ACPI_GET_DESCRIPTOR_TYPE (NextNode) != ACPI_DESC_TYPE_NAMED) + { + ACPI_ERROR ((AE_INFO, + "Invalid Namespace Node (%p) while traversing namespace", + NextNode)); + return 0; + } + Size += ACPI_PATH_SEGMENT_LENGTH; + NextNode = NextNode->Parent; + } + + if (!Size) + { + Size = 1; /* Root node case */ + } + + return (Size + 1); /* +1 for null string terminator */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsHandleToPathname + * + * PARAMETERS: TargetHandle - Handle of named object whose name is + * to be found + * Buffer - Where the pathname is returned + * + * RETURN: Status, Buffer is filled with pathname if status is AE_OK + * + * DESCRIPTION: Build and return a full namespace pathname + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsHandleToPathname ( + ACPI_HANDLE TargetHandle, + ACPI_BUFFER *Buffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_SIZE RequiredSize; + + + ACPI_FUNCTION_TRACE_PTR (NsHandleToPathname, TargetHandle); + + + Node = AcpiNsValidateHandle (TargetHandle); + if (!Node) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Determine size required for the caller buffer */ + + RequiredSize = AcpiNsGetPathnameLength (Node); + if (!RequiredSize) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (Buffer, RequiredSize); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Build the path in the caller buffer */ + + Status = AcpiNsBuildExternalPath (Node, RequiredSize, Buffer->Pointer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X]\n", + (char *) Buffer->Pointer, (UINT32) RequiredSize)); + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/namespace/nsobject.c b/source/components/namespace/nsobject.c new file mode 100644 index 000000000000..9b219a562447 --- /dev/null +++ b/source/components/namespace/nsobject.c @@ -0,0 +1,505 @@ +/******************************************************************************* + * + * Module Name: nsobject - Utilities for objects attached to namespace + * table entries + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSOBJECT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsobject") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsAttachObject + * + * PARAMETERS: Node - Parent Node + * Object - Object to be attached + * Type - Type of object, or ACPI_TYPE_ANY if not + * known + * + * RETURN: Status + * + * DESCRIPTION: Record the given object as the value associated with the + * name whose ACPI_HANDLE is passed. If Object is NULL + * and Type is ACPI_TYPE_ANY, set the name as having no value. + * Note: Future may require that the Node->Flags field be passed + * as a parameter. + * + * MUTEX: Assumes namespace is locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsAttachObject ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OPERAND_OBJECT *Object, + ACPI_OBJECT_TYPE Type) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *LastObjDesc; + ACPI_OBJECT_TYPE ObjectType = ACPI_TYPE_ANY; + + + ACPI_FUNCTION_TRACE (NsAttachObject); + + + /* + * Parameter validation + */ + if (!Node) + { + /* Invalid handle */ + + ACPI_ERROR ((AE_INFO, "Null NamedObj handle")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!Object && (ACPI_TYPE_ANY != Type)) + { + /* Null object */ + + ACPI_ERROR ((AE_INFO, + "Null object, but type not ACPI_TYPE_ANY")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + /* Not a name handle */ + + ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]", + Node, AcpiUtGetDescriptorName (Node))); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Check if this object is already attached */ + + if (Node->Object == Object) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Obj %p already installed in NameObj %p\n", + Object, Node)); + + return_ACPI_STATUS (AE_OK); + } + + /* If null object, we will just install it */ + + if (!Object) + { + ObjDesc = NULL; + ObjectType = ACPI_TYPE_ANY; + } + + /* + * If the source object is a namespace Node with an attached object, + * we will use that (attached) object + */ + else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) && + ((ACPI_NAMESPACE_NODE *) Object)->Object) + { + /* + * Value passed is a name handle and that name has a + * non-null value. Use that name's value and type. + */ + ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object; + ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type; + } + + /* + * Otherwise, we will use the parameter object, but we must type + * it first + */ + else + { + ObjDesc = (ACPI_OPERAND_OBJECT *) Object; + + /* Use the given type */ + + ObjectType = Type; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", + ObjDesc, Node, AcpiUtGetNodeName (Node))); + + /* Detach an existing attached object if present */ + + if (Node->Object) + { + AcpiNsDetachObject (Node); + } + + if (ObjDesc) + { + /* + * Must increment the new value's reference count + * (if it is an internal object) + */ + AcpiUtAddReference (ObjDesc); + + /* + * Handle objects with multiple descriptors - walk + * to the end of the descriptor list + */ + LastObjDesc = ObjDesc; + while (LastObjDesc->Common.NextObject) + { + LastObjDesc = LastObjDesc->Common.NextObject; + } + + /* Install the object at the front of the object list */ + + LastObjDesc->Common.NextObject = Node->Object; + } + + Node->Type = (UINT8) ObjectType; + Node->Object = ObjDesc; + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDetachObject + * + * PARAMETERS: Node - A Namespace node whose object will be detached + * + * RETURN: None. + * + * DESCRIPTION: Detach/delete an object associated with a namespace node. + * if the object is an allocated object, it is freed. + * Otherwise, the field is simply cleared. + * + ******************************************************************************/ + +void +AcpiNsDetachObject ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE (NsDetachObject); + + + ObjDesc = Node->Object; + + if (!ObjDesc || + (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) + { + return_VOID; + } + + if (Node->Flags & ANOBJ_ALLOCATED_BUFFER) + { + /* Free the dynamic aml buffer */ + + if (ObjDesc->Common.Type == ACPI_TYPE_METHOD) + { + ACPI_FREE (ObjDesc->Method.AmlStart); + } + } + + /* Clear the entry in all cases */ + + Node->Object = NULL; + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) + { + Node->Object = ObjDesc->Common.NextObject; + if (Node->Object && + ((Node->Object)->Common.Type != ACPI_TYPE_LOCAL_DATA)) + { + Node->Object = Node->Object->Common.NextObject; + } + } + + /* Reset the node type to untyped */ + + Node->Type = ACPI_TYPE_ANY; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", + Node, AcpiUtGetNodeName (Node), ObjDesc)); + + /* Remove one reference on the object (and all subobjects) */ + + AcpiUtRemoveReference (ObjDesc); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetAttachedObject + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Current value of the object field from the Node whose + * handle is passed + * + * DESCRIPTION: Obtain the object attached to a namespace node. + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiNsGetAttachedObject ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_FUNCTION_TRACE_PTR (NsGetAttachedObject, Node); + + + if (!Node) + { + ACPI_WARNING ((AE_INFO, "Null Node ptr")); + return_PTR (NULL); + } + + if (!Node->Object || + ((ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_OPERAND) && + (ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_NAMED)) || + ((Node->Object)->Common.Type == ACPI_TYPE_LOCAL_DATA)) + { + return_PTR (NULL); + } + + return_PTR (Node->Object); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetSecondaryObject + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Current value of the object field from the Node whose + * handle is passed. + * + * DESCRIPTION: Obtain a secondary object associated with a namespace node. + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiNsGetSecondaryObject ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_FUNCTION_TRACE_PTR (NsGetSecondaryObject, ObjDesc); + + + if ((!ObjDesc) || + (ObjDesc->Common.Type== ACPI_TYPE_LOCAL_DATA) || + (!ObjDesc->Common.NextObject) || + ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA)) + { + return_PTR (NULL); + } + + return_PTR (ObjDesc->Common.NextObject); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsAttachData + * + * PARAMETERS: Node - Namespace node + * Handler - Handler to be associated with the data + * Data - Data to be attached + * + * RETURN: Status + * + * DESCRIPTION: Low-level attach data. Create and attach a Data object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsAttachData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler, + void *Data) +{ + ACPI_OPERAND_OBJECT *PrevObjDesc; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *DataDesc; + + + /* We only allow one attachment per handler */ + + PrevObjDesc = NULL; + ObjDesc = Node->Object; + while (ObjDesc) + { + if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && + (ObjDesc->Data.Handler == Handler)) + { + return (AE_ALREADY_EXISTS); + } + + PrevObjDesc = ObjDesc; + ObjDesc = ObjDesc->Common.NextObject; + } + + /* Create an internal object for the data */ + + DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA); + if (!DataDesc) + { + return (AE_NO_MEMORY); + } + + DataDesc->Data.Handler = Handler; + DataDesc->Data.Pointer = Data; + + /* Install the data object */ + + if (PrevObjDesc) + { + PrevObjDesc->Common.NextObject = DataDesc; + } + else + { + Node->Object = DataDesc; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDetachData + * + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data + * + * RETURN: Status + * + * DESCRIPTION: Low-level detach data. Delete the data node, but the caller + * is responsible for the actual data. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsDetachData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *PrevObjDesc; + + + PrevObjDesc = NULL; + ObjDesc = Node->Object; + while (ObjDesc) + { + if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && + (ObjDesc->Data.Handler == Handler)) + { + if (PrevObjDesc) + { + PrevObjDesc->Common.NextObject = ObjDesc->Common.NextObject; + } + else + { + Node->Object = ObjDesc->Common.NextObject; + } + + AcpiUtRemoveReference (ObjDesc); + return (AE_OK); + } + + PrevObjDesc = ObjDesc; + ObjDesc = ObjDesc->Common.NextObject; + } + + return (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetAttachedData + * + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data + * Data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Low level interface to obtain data previously associated with + * a namespace node. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsGetAttachedData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler, + void **Data) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + ObjDesc = Node->Object; + while (ObjDesc) + { + if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && + (ObjDesc->Data.Handler == Handler)) + { + *Data = ObjDesc->Data.Pointer; + return (AE_OK); + } + + ObjDesc = ObjDesc->Common.NextObject; + } + + return (AE_NOT_FOUND); +} + + diff --git a/source/components/namespace/nsparse.c b/source/components/namespace/nsparse.c new file mode 100644 index 000000000000..2c768c0b699f --- /dev/null +++ b/source/components/namespace/nsparse.c @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * Module Name: nsparse - namespace interface to AML parser + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSPARSE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acdispat.h" +#include "actables.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsparse") + + +/******************************************************************************* + * + * FUNCTION: NsOneCompleteParse + * + * PARAMETERS: PassNumber - 1 or 2 + * TableDesc - The table to be parsed. + * + * RETURN: Status + * + * DESCRIPTION: Perform one complete parse of an ACPI/AML table. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsOneCompleteParse ( + UINT32 PassNumber, + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode) +{ + ACPI_PARSE_OBJECT *ParseRoot; + ACPI_STATUS Status; + UINT32 AmlLength; + UINT8 *AmlStart; + ACPI_WALK_STATE *WalkState; + ACPI_TABLE_HEADER *Table; + ACPI_OWNER_ID OwnerId; + + + ACPI_FUNCTION_TRACE (NsOneCompleteParse); + + + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create and init a Root Node */ + + ParseRoot = AcpiPsCreateScopeOp (); + if (!ParseRoot) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL); + if (!WalkState) + { + AcpiPsFreeOp (ParseRoot); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + AcpiPsFreeOp (ParseRoot); + return_ACPI_STATUS (Status); + } + + /* Table must consist of at least a complete header */ + + if (Table->Length < sizeof (ACPI_TABLE_HEADER)) + { + Status = AE_BAD_HEADER; + } + else + { + AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER); + AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); + Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL, + AmlStart, AmlLength, NULL, (UINT8) PassNumber); + } + + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + /* StartNode is the default location to load the table */ + + if (StartNode && StartNode != AcpiGbl_RootNode) + { + Status = AcpiDsScopeStackPush (StartNode, ACPI_TYPE_METHOD, WalkState); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + } + + /* Parse the AML */ + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %u parse\n", PassNumber)); + Status = AcpiPsParseAml (WalkState); + +Cleanup: + AcpiPsDeleteParseTree (ParseRoot); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsParseTable + * + * PARAMETERS: TableDesc - An ACPI table descriptor for table to parse + * StartNode - Where to enter the table into the namespace + * + * RETURN: Status + * + * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsParseTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsParseTable); + + + /* + * AML Parse, pass 1 + * + * In this pass, we load most of the namespace. Control methods + * are not parsed until later. A parse tree is not created. Instead, + * each Parser Op subtree is deleted when it is finished. This saves + * a great deal of memory, and allows a small cache of parse objects + * to service the entire parse. The second pass of the parse then + * performs another complete parse of the AML. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n")); + Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS1, + TableIndex, StartNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * AML Parse, pass 2 + * + * In this pass, we resolve forward references and other things + * that could not be completed during the first pass. + * Another complete parse of the AML is performed, but the + * overhead of this is compensated for by the fact that the + * parse objects are all cached. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n")); + Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, + TableIndex, StartNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/namespace/nspredef.c b/source/components/namespace/nspredef.c new file mode 100644 index 000000000000..19662680125c --- /dev/null +++ b/source/components/namespace/nspredef.c @@ -0,0 +1,1243 @@ +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define ACPI_CREATE_PREDEFINED_TABLE + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nspredef") + + +/******************************************************************************* + * + * This module validates predefined ACPI objects that appear in the namespace, + * at the time they are evaluated (via AcpiEvaluateObject). The purpose of this + * validation is to detect problems with BIOS-exposed predefined ACPI objects + * before the results are returned to the ACPI-related drivers. + * + * There are several areas that are validated: + * + * 1) The number of input arguments as defined by the method/object in the + * ASL is validated against the ACPI specification. + * 2) The type of the return object (if any) is validated against the ACPI + * specification. + * 3) For returned package objects, the count of package elements is + * validated, as well as the type of each package element. Nested + * packages are supported. + * + * For any problems found, a warning message is issued. + * + ******************************************************************************/ + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsCheckPackage ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsCheckPackageList ( + ACPI_PREDEFINED_DATA *Data, + const ACPI_PREDEFINED_INFO *Package, + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count); + +static ACPI_STATUS +AcpiNsCheckPackageElements ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **Elements, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2, + UINT32 StartIndex); + +static ACPI_STATUS +AcpiNsCheckObjectType ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr, + UINT32 ExpectedBtypes, + UINT32 PackageIndex); + +static ACPI_STATUS +AcpiNsCheckReference ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT *ReturnObject); + +static void +AcpiNsGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes); + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *AcpiRtypeNames[] = +{ + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPredefinedNames + * + * PARAMETERS: Node - Namespace node for the method/object + * UserParamCount - Number of parameters actually passed + * ReturnStatus - Status from the object evaluation + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsCheckPredefinedNames ( + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + ACPI_STATUS ReturnStatus, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status = AE_OK; + const ACPI_PREDEFINED_INFO *Predefined; + char *Pathname; + ACPI_PREDEFINED_DATA *Data; + + + /* Match the name for this method/object against the predefined list */ + + Predefined = AcpiNsCheckForPredefinedName (Node); + + /* Get the full pathname to the object, for use in warning messages */ + + Pathname = AcpiNsGetExternalPathname (Node); + if (!Pathname) + { + return (AE_OK); /* Could not get pathname, ignore */ + } + + /* + * Check that the parameter count for this method matches the ASL + * definition. For predefined names, ensure that both the caller and + * the method itself are in accordance with the ACPI specification. + */ + AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined); + + /* If not a predefined name, we cannot validate the return object */ + + if (!Predefined) + { + goto Cleanup; + } + + /* + * If the method failed or did not actually return an object, we cannot + * validate the return object + */ + if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE)) + { + goto Cleanup; + } + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Exit now if there is no return object. Warning if one was expected. + */ + if (!ReturnObject) + { + if ((Predefined->Info.ExpectedBtypes) && + (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE))) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Missing expected return value")); + + Status = AE_AML_NO_RETURN_VALUE; + } + goto Cleanup; + } + + /* + * Return value validation and possible repair. + * + * 1) Don't perform return value validation/repair if this feature + * has been disabled via a global option. + * + * 2) We have a return value, but if one wasn't expected, just exit, + * this is not a problem. For example, if the "Implicit Return" + * feature is enabled, methods will always return a value. + * + * 3) If the return value can be of any type, then we cannot perform + * any validation, just exit. + */ + if (AcpiGbl_DisableAutoRepair || + (!Predefined->Info.ExpectedBtypes) || + (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL)) + { + goto Cleanup; + } + + /* Create the parameter data block for object validation */ + + Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA)); + if (!Data) + { + goto Cleanup; + } + Data->Predefined = Predefined; + Data->Node = Node; + Data->NodeFlags = Node->Flags; + Data->Pathname = Pathname; + + /* + * Check that the type of the main return object is what is expected + * for this predefined name + */ + Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr, + Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been newly created by call above. + */ + if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE) + { + Data->ParentPackage = *ReturnObjectPtr; + Status = AcpiNsCheckPackage (Data, ReturnObjectPtr); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + } + + /* + * The return object was OK, or it was successfully repaired above. + * Now make some additional checks such as verifying that package + * objects are sorted correctly (if required) or buffer objects have + * the correct data width (bytes vs. dwords). These repairs are + * performed on a per-name basis, i.e., the code is specific to + * particular predefined names. + */ + Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr); + +Exit: + /* + * If the object validation failed or if we successfully repaired one + * or more objects, mark the parent node to suppress further warning + * messages during the next evaluation of the same method/object. + */ + if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED)) + { + Node->Flags |= ANOBJ_EVALUATED; + } + ACPI_FREE (Data); + +Cleanup: + ACPI_FREE (Pathname); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckParameterCount + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Node - Namespace node for the method/object + * UserParamCount - Number of args passed in by the caller + * Predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a + * predefined name is what is expected (i.e., what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +AcpiNsCheckParameterCount ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + const ACPI_PREDEFINED_INFO *Predefined) +{ + UINT32 ParamCount; + UINT32 RequiredParamsCurrent; + UINT32 RequiredParamsOld; + + + /* Methods have 0-7 parameters. All other types have zero. */ + + ParamCount = 0; + if (Node->Type == ACPI_TYPE_METHOD) + { + ParamCount = Node->Object->Method.ParamCount; + } + + if (!Predefined) + { + /* + * Check the parameter count for non-predefined methods/objects. + * + * Warning if too few or too many arguments have been passed by the + * caller. An incorrect number of arguments may not cause the method + * to fail. However, the method will fail if there are too few + * arguments and the method attempts to use one of the missing ones. + */ + if (UserParamCount < ParamCount) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - needs %u, found %u", + ParamCount, UserParamCount)); + } + else if (UserParamCount > ParamCount) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Excess arguments - needs %u, found %u", + ParamCount, UserParamCount)); + } + return; + } + + /* + * Validate the user-supplied parameter count. + * Allow two different legal argument counts (_SCP, etc.) + */ + RequiredParamsCurrent = Predefined->Info.ParamCount & 0x0F; + RequiredParamsOld = Predefined->Info.ParamCount >> 4; + + if (UserParamCount != ACPI_UINT32_MAX) + { + if ((UserParamCount != RequiredParamsCurrent) && + (UserParamCount != RequiredParamsOld)) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Parameter count mismatch - " + "caller passed %u, ACPI requires %u", + UserParamCount, RequiredParamsCurrent)); + } + } + + /* + * Check that the ASL-defined parameter count is what is expected for + * this predefined name (parameter count as defined by the ACPI + * specification) + */ + if ((ParamCount != RequiredParamsCurrent) && + (ParamCount != RequiredParamsOld)) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, Node->Flags, + "Parameter count mismatch - ASL declared %u, ACPI requires %u", + ParamCount, RequiredParamsCurrent)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckForPredefinedName + * + * PARAMETERS: Node - Namespace node for the method/object + * + * RETURN: Pointer to entry in predefined table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the predefined object list. + * + ******************************************************************************/ + +const ACPI_PREDEFINED_INFO * +AcpiNsCheckForPredefinedName ( + ACPI_NAMESPACE_NODE *Node) +{ + const ACPI_PREDEFINED_INFO *ThisName; + + + /* Quick check for a predefined name, first character must be underscore */ + + if (Node->Name.Ascii[0] != '_') + { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + ThisName = PredefinedNames; + while (ThisName->Info.Name[0]) + { + if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Info.Name)) + { + return (ThisName); + } + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE) + { + ThisName++; + } + + ThisName++; + } + + return (NULL); /* Not found */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackage + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckPackage ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + const ACPI_PREDEFINED_INFO *Package; + ACPI_OPERAND_OBJECT **Elements; + ACPI_STATUS Status = AE_OK; + UINT32 ExpectedCount; + UINT32 Count; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsCheckPackage); + + + /* The package info for this name is in the next table entry */ + + Package = Data->Predefined + 1; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count)); + + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject); + + /* Extract package count and elements array */ + + Elements = ReturnObject->Package.Elements; + Count = ReturnObject->Package.Count; + + /* The package must have at least one element, else invalid */ + + if (!Count) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return Package has no elements (empty)")); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (Package->RetInfo.Type) + { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (Count < ExpectedCount) + { + goto PackageTooSmall; + } + else if (Count > ExpectedCount) + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + Data->Pathname, Count, ExpectedCount)); + } + + /* Validate all elements of the returned package */ + + Status = AcpiNsCheckPackageElements (Data, Elements, + Package->RetInfo.ObjectType1, Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); + break; + + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < Count; i++) + { + Status = AcpiNsCheckObjectType (Data, Elements, + Package->RetInfo.ObjectType1, i); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + Elements++; + } + break; + + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + ExpectedCount = Package->RetInfo3.Count; + if (Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < Count; i++) + { + if (i < Package->RetInfo3.Count) + { + /* These are the required package elements (0, 1, or 2) */ + + Status = AcpiNsCheckObjectType (Data, Elements, + Package->RetInfo3.ObjectType[i], i); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + else + { + /* These are the optional package elements */ + + Status = AcpiNsCheckObjectType (Data, Elements, + Package->RetInfo3.TailObjectType, i); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + Elements++; + } + break; + + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + Status = AcpiNsCheckObjectType (Data, Elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Elements++; + Count--; + + /* Examine the sub-packages */ + + Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); + break; + + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + Status = AcpiNsCheckObjectType (Data, Elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + ExpectedCount = (UINT32) (*Elements)->Integer.Value; + if (ExpectedCount >= Count) + { + goto PackageTooSmall; + } + + Count = ExpectedCount; + Elements++; + + /* Examine the sub-packages */ + + Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); + break; + + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_FIX_VAR: + + /* + * These types all return a single Package that consists of a + * variable number of sub-Packages. + * + * First, ensure that the first element is a sub-Package. If not, + * the BIOS may have incorrectly returned the object as a single + * package instead of a Package of Packages (a common error if + * there is only one entry). We may be able to repair this by + * wrapping the returned Package with a new outer Package. + */ + if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE)) + { + /* Create the new outer package and populate it */ + + Status = AcpiNsRepairPackageList (Data, ReturnObjectPtr); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Update locals to point to the new package (of 1 element) */ + + ReturnObject = *ReturnObjectPtr; + Elements = ReturnObject->Package.Elements; + Count = 1; + } + + /* Examine the sub-packages */ + + Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); + break; + + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Invalid internal return type in table entry: %X", + Package->RetInfo.Type)); + + return (AE_AML_INTERNAL); + } + + return (Status); + + +PackageTooSmall: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return Package is too small - found %u elements, expected %u", + Count, ExpectedCount)); + + return (AE_AML_OPERAND_VALUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackageList + * + * PARAMETERS: Data - Pointer to validation data structure + * Package - Pointer to package-specific info for method + * Elements - Element list of parent package. All elements + * of this list should be of type Package. + * Count - Count of subpackages + * + * RETURN: Status + * + * DESCRIPTION: Examine a list of subpackages + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckPackageList ( + ACPI_PREDEFINED_DATA *Data, + const ACPI_PREDEFINED_INFO *Package, + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count) +{ + ACPI_OPERAND_OBJECT *SubPackage; + ACPI_OPERAND_OBJECT **SubElements; + ACPI_STATUS Status; + UINT32 ExpectedCount; + UINT32 i; + UINT32 j; + + + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to AcpiNsRemoveNullElements. + */ + for (i = 0; i < Count; i++) + { + SubPackage = *Elements; + SubElements = SubPackage->Package.Elements; + Data->ParentPackage = SubPackage; + + /* Each sub-object must be of type Package */ + + Status = AcpiNsCheckObjectType (Data, &SubPackage, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Examine the different types of expected sub-packages */ + + Data->ParentPackage = SubPackage; + switch (Package->RetInfo.Type) + { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_REV_FIXED: + + /* Each subpackage has a fixed number of elements */ + + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + Status = AcpiNsCheckPackageElements (Data, SubElements, + Package->RetInfo.ObjectType1, + Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, + Package->RetInfo.Count2, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + case ACPI_PTYPE2_FIX_VAR: + /* + * Each subpackage has a fixed number of elements and an + * optional element + */ + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + Status = AcpiNsCheckPackageElements (Data, SubElements, + Package->RetInfo.ObjectType1, + Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, + SubPackage->Package.Count - Package->RetInfo.Count1, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + ExpectedCount = Package->RetInfo2.Count; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < ExpectedCount; j++) + { + Status = AcpiNsCheckObjectType (Data, &SubElements[j], + Package->RetInfo2.ObjectType[j], j); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + break; + + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + ExpectedCount = Package->RetInfo.Count1; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Check the type of each sub-package element */ + + Status = AcpiNsCheckPackageElements (Data, SubElements, + Package->RetInfo.ObjectType1, + SubPackage->Package.Count, 0, 0, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + case ACPI_PTYPE2_COUNT: + + /* + * First element is the (Integer) count of elements, including + * the count field (the ACPI name is NumElements) + */ + Status = AcpiNsCheckObjectType (Data, SubElements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Make sure package is large enough for the Count and is + * is as large as the minimum size + */ + ExpectedCount = (UINT32) (*SubElements)->Integer.Value; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + if (SubPackage->Package.Count < Package->RetInfo.Count1) + { + ExpectedCount = Package->RetInfo.Count1; + goto PackageTooSmall; + } + if (ExpectedCount == 0) + { + /* + * Either the NumEntries element was originally zero or it was + * a NULL element and repaired to an Integer of value zero. + * In either case, repair it by setting NumEntries to be the + * actual size of the subpackage. + */ + ExpectedCount = SubPackage->Package.Count; + (*SubElements)->Integer.Value = ExpectedCount; + } + + /* Check the type of each sub-package element */ + + Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), + Package->RetInfo.ObjectType1, + (ExpectedCount - 1), 0, 0, 1); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + default: /* Should not get here, type was validated by caller */ + + return (AE_AML_INTERNAL); + } + + Elements++; + } + + return (AE_OK); + + +PackageTooSmall: + + /* The sub-package count was smaller than required */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return Sub-Package[%u] is too small - found %u elements, expected %u", + i, SubPackage->Package.Count, ExpectedCount)); + + return (AE_AML_OPERAND_VALUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackageElements + * + * PARAMETERS: Data - Pointer to validation data structure + * Elements - Pointer to the package elements array + * Type1 - Object type for first group + * Count1 - Count for first group + * Type2 - Object type for second group + * Count2 - Count for second group + * StartIndex - Start of the first group of elements + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckPackageElements ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **Elements, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2, + UINT32 StartIndex) +{ + ACPI_OPERAND_OBJECT **ThisElement = Elements; + ACPI_STATUS Status; + UINT32 i; + + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < Count1; i++) + { + Status = AcpiNsCheckObjectType (Data, ThisElement, + Type1, i + StartIndex); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + ThisElement++; + } + + for (i = 0; i < Count2; i++) + { + Status = AcpiNsCheckObjectType (Data, ThisElement, + Type2, (i + Count1 + StartIndex)); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + ThisElement++; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckObjectType + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * ExpectedBtypes - Bitmap of expected return type(s) + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) + * + * RETURN: Status + * + * DESCRIPTION: Check the type of the return object against the expected object + * type(s). Use of Btype allows multiple expected object types. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckObjectType ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr, + UINT32 ExpectedBtypes, + UINT32 PackageIndex) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status = AE_OK; + UINT32 ReturnBtype; + char TypeBuffer[48]; /* Room for 5 types */ + + + /* + * If we get a NULL ReturnObject here, it is a NULL package element. + * Since all extraneous NULL package elements were removed earlier by a + * call to AcpiNsRemoveNullElements, this is an unexpected NULL element. + * We will attempt to repair it. + */ + if (!ReturnObject) + { + Status = AcpiNsRepairNullElement (Data, ExpectedBtypes, + PackageIndex, ReturnObjectPtr); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); /* Repair was successful */ + } + goto TypeErrorExit; + } + + /* A Namespace node should not get here, but make sure */ + + if (ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Invalid return type - Found a Namespace node [%4.4s] type %s", + ReturnObject->Node.Name.Ascii, + AcpiUtGetTypeName (ReturnObject->Node.Type))); + return (AE_AML_OPERAND_TYPE); + } + + /* + * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. + * The bitmapped type allows multiple possible return types. + * + * Note, the cases below must handle all of the possible types returned + * from all of the predefined names (including elements of returned + * packages) + */ + switch (ReturnObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + ReturnBtype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + ReturnBtype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + ReturnBtype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + ReturnBtype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + ReturnBtype = ACPI_RTYPE_REFERENCE; + break; + + default: + /* Not one of the supported objects, must be incorrect */ + + goto TypeErrorExit; + } + + /* Is the object one of the expected types? */ + + if (ReturnBtype & ExpectedBtypes) + { + /* For reference objects, check that the reference type is correct */ + + if (ReturnObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) + { + Status = AcpiNsCheckReference (Data, ReturnObject); + } + + return (Status); + } + + /* Type mismatch -- attempt repair of the returned object */ + + Status = AcpiNsRepairObject (Data, ExpectedBtypes, + PackageIndex, ReturnObjectPtr); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); /* Repair was successful */ + } + + +TypeErrorExit: + + /* Create a string with all expected types for this predefined object */ + + AcpiNsGetExpectedTypes (TypeBuffer, ExpectedBtypes); + + if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return type mismatch - found %s, expected %s", + AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); + } + else + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return Package type mismatch at index %u - " + "found %s, expected %s", PackageIndex, + AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckReference + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObject - Object returned from the evaluation of a + * method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned reference object for the correct reference + * type. The only reference type that can be returned from a + * predefined method is a named reference. All others are invalid. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckReference ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT *ReturnObject) +{ + + /* + * Check the reference object for the correct reference type (opcode). + * The only type of reference that can be converted to an ACPI_OBJECT is + * a reference to a named object (reference class: NAME) + */ + if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME) + { + return (AE_OK); + } + + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Return type mismatch - unexpected reference object type [%s] %2.2X", + AcpiUtGetReferenceName (ReturnObject), + ReturnObject->Reference.Class)); + + return (AE_AML_OPERAND_TYPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetExpectedTypes + * + * PARAMETERS: Buffer - Pointer to where the string is returned + * ExpectedBtypes - Bitmap of expected return type(s) + * + * RETURN: Buffer is populated with type names. + * + * DESCRIPTION: Translate the expected types bitmap into a string of ascii + * names of expected types, for use in warning messages. + * + ******************************************************************************/ + +static void +AcpiNsGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes) +{ + UINT32 ThisRtype; + UINT32 i; + UINT32 j; + + + j = 1; + Buffer[0] = 0; + ThisRtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) + { + /* If one of the expected types, concatenate the name of this type */ + + if (ExpectedBtypes & ThisRtype) + { + ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]); + j = 0; /* Use name separator from now on */ + } + ThisRtype <<= 1; /* Next Rtype */ + } +} diff --git a/source/components/namespace/nsrepair.c b/source/components/namespace/nsrepair.c new file mode 100644 index 000000000000..d820834e881e --- /dev/null +++ b/source/components/namespace/nsrepair.c @@ -0,0 +1,802 @@ +/****************************************************************************** + * + * Module Name: nsrepair - Repair for objects returned by predefined methods + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSREPAIR_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsrepair") + + +/******************************************************************************* + * + * This module attempts to repair or convert objects returned by the + * predefined methods to an object type that is expected, as per the ACPI + * specification. The need for this code is dictated by the many machines that + * return incorrect types for the standard predefined methods. Performing these + * conversions here, in one place, eliminates the need for individual ACPI + * device drivers to do the same. Note: Most of these conversions are different + * than the internal object conversion routines used for implicit object + * conversion. + * + * The following conversions can be performed as necessary: + * + * Integer -> String + * Integer -> Buffer + * String -> Integer + * String -> Buffer + * Buffer -> Integer + * Buffer -> String + * Buffer -> Package of Integers + * Package -> Package of one Package + * + * Additional possible repairs: + * + * Required package elements that are NULL replaced by Integer/String/Buffer + * Incorrect standalone package wrapped with required outer package + * + ******************************************************************************/ + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToPackage ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRepairObject + * + * PARAMETERS: Data - Pointer to validation data structure + * ExpectedBtypes - Object types expected + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if repair was successful. + * + * DESCRIPTION: Attempt to repair/convert a return object of a type that was + * not expected. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsRepairObject ( + ACPI_PREDEFINED_DATA *Data, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (NsRepairObject); + + + /* + * At this point, we know that the type of the returned object was not + * one of the expected types for this predefined name. Attempt to + * repair the object by converting it to one of the expected object + * types for this predefined name. + */ + if (ExpectedBtypes & ACPI_RTYPE_INTEGER) + { + Status = AcpiNsConvertToInteger (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_STRING) + { + Status = AcpiNsConvertToString (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_BUFFER) + { + Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_PACKAGE) + { + Status = AcpiNsConvertToPackage (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + + /* We cannot repair this object */ + + return (AE_AML_OPERAND_TYPE); + + +ObjectRepaired: + + /* Object was successfully repaired */ + + /* + * If the original object is a package element, we need to: + * 1. Set the reference count of the new object to match the + * reference count of the old object. + * 2. Decrement the reference count of the original object. + */ + if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) + { + NewObject->Common.ReferenceCount = + ReturnObject->Common.ReferenceCount; + + if (ReturnObject->Common.ReferenceCount > 1) + { + ReturnObject->Common.ReferenceCount--; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s at index %u\n", + Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject), PackageIndex)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s\n", + Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject))); + } + + /* Delete old object, install the new return object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = NewObject; + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToInteger + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + UINT64 Value = 0; + UINT32 i; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, + ACPI_ANY_BASE, &Value); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_BUFFER: + + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ + + if (OriginalObject->Buffer.Length > 8) + { + return (AE_AML_OPERAND_TYPE); + } + + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < OriginalObject->Buffer.Length; i++) + { + Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + NewObject = AcpiUtCreateIntegerObject (Value); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToString + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_SIZE Length; + ACPI_STATUS Status; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-String conversion. Commonly, convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (OriginalObject->Integer.Value == 0) + { + /* Allocate a new NULL string object */ + + NewObject = AcpiUtCreateStringObject (0); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + } + else + { + Status = AcpiExConvertToString (OriginalObject, &NewObject, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + break; + + case ACPI_TYPE_BUFFER: + /* + * Buffer-to-String conversion. Use a ToString + * conversion, no transform performed on the buffer data. The best + * example of this is the _BIF method, where the string data from + * the battery is often (incorrectly) returned as buffer object(s). + */ + Length = 0; + while ((Length < OriginalObject->Buffer.Length) && + (OriginalObject->Buffer.Pointer[Length])) + { + Length++; + } + + /* Allocate a new string object */ + + NewObject = AcpiUtCreateStringObject (Length); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* + * Copy the raw buffer data with no transform. String is already NULL + * terminated at Length+1. + */ + ACPI_MEMCPY (NewObject->String.Pointer, + OriginalObject->Buffer.Pointer, Length); + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToBuffer + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT **Elements; + UINT32 *DwordBuffer; + UINT32 Count; + UINT32 i; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-Buffer conversion. + * Convert the Integer to a packed-byte buffer. _MAT and other + * objects need this sometimes, if a read has been performed on a + * Field object that is less than or equal to the global integer + * size (32 or 64 bits). + */ + Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_STRING: + + /* String-to-Buffer conversion. Simple data copy */ + + NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMCPY (NewObject->Buffer.Pointer, + OriginalObject->String.Pointer, OriginalObject->String.Length); + break; + + case ACPI_TYPE_PACKAGE: + /* + * This case is often seen for predefined names that must return a + * Buffer object with multiple DWORD integers within. For example, + * _FDE and _GTM. The Package can be converted to a Buffer. + */ + + /* All elements of the Package must be integers */ + + Elements = OriginalObject->Package.Elements; + Count = OriginalObject->Package.Count; + + for (i = 0; i < Count; i++) + { + if ((!*Elements) || + ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) + { + return (AE_AML_OPERAND_TYPE); + } + Elements++; + } + + /* Create the new buffer object to replace the Package */ + + NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* Copy the package elements (integers) to the buffer as DWORDs */ + + Elements = OriginalObject->Package.Elements; + DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); + + for (i = 0; i < Count; i++) + { + *DwordBuffer = (UINT32) (*Elements)->Integer.Value; + DwordBuffer++; + Elements++; + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToPackage + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of + * the buffer is converted to a single integer package element. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToPackage ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_OPERAND_OBJECT **Elements; + UINT32 Length; + UINT8 *Buffer; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_BUFFER: + + /* Buffer-to-Package conversion */ + + Length = OriginalObject->Buffer.Length; + NewObject = AcpiUtCreatePackageObject (Length); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* Convert each buffer byte to an integer package element */ + + Elements = NewObject->Package.Elements; + Buffer = OriginalObject->Buffer.Pointer; + + while (Length--) + { + *Elements = AcpiUtCreateIntegerObject ((UINT64) *Buffer); + if (!*Elements) + { + AcpiUtRemoveReference (NewObject); + return (AE_NO_MEMORY); + } + Elements++; + Buffer++; + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRepairNullElement + * + * PARAMETERS: Data - Pointer to validation data structure + * ExpectedBtypes - Object types expected + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if repair was successful. + * + * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsRepairNullElement ( + ACPI_PREDEFINED_DATA *Data, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *NewObject; + + + ACPI_FUNCTION_NAME (NsRepairNullElement); + + + /* No repair needed if return object is non-NULL */ + + if (ReturnObject) + { + return (AE_OK); + } + + /* + * Attempt to repair a NULL element of a Package object. This applies to + * predefined names that return a fixed-length package and each element + * is required. It does not apply to variable-length packages where NULL + * elements are allowed, especially at the end of the package. + */ + if (ExpectedBtypes & ACPI_RTYPE_INTEGER) + { + /* Need an Integer - create a zero-value integer */ + + NewObject = AcpiUtCreateIntegerObject ((UINT64) 0); + } + else if (ExpectedBtypes & ACPI_RTYPE_STRING) + { + /* Need a String - create a NULL string */ + + NewObject = AcpiUtCreateStringObject (0); + } + else if (ExpectedBtypes & ACPI_RTYPE_BUFFER) + { + /* Need a Buffer - create a zero-length buffer */ + + NewObject = AcpiUtCreateBufferObject (0); + } + else + { + /* Error for all other expected types */ + + return (AE_AML_OPERAND_TYPE); + } + + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* Set the reference count according to the parent Package object */ + + NewObject->Common.ReferenceCount = Data->ParentPackage->Common.ReferenceCount; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted NULL package element to expected %s at index %u\n", + Data->Pathname, AcpiUtGetObjectTypeName (NewObject), PackageIndex)); + + *ReturnObjectPtr = NewObject; + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRemoveNullElements + * + * PARAMETERS: Data - Pointer to validation data structure + * PackageType - An AcpiReturnPackageTypes value + * ObjDesc - A Package object + * + * RETURN: None. + * + * DESCRIPTION: Remove all NULL package elements from packages that contain + * a variable number of sub-packages. For these types of + * packages, NULL elements can be safely removed. + * + *****************************************************************************/ + +void +AcpiNsRemoveNullElements ( + ACPI_PREDEFINED_DATA *Data, + UINT8 PackageType, + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_OPERAND_OBJECT **Source; + ACPI_OPERAND_OBJECT **Dest; + UINT32 Count; + UINT32 NewCount; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsRemoveNullElements); + + + /* + * We can safely remove all NULL elements from these package types: + * PTYPE1_VAR packages contain a variable number of simple data types. + * PTYPE2 packages contain a variable number of sub-packages. + */ + switch (PackageType) + { + case ACPI_PTYPE1_VAR: + case ACPI_PTYPE2: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_REV_FIXED: + case ACPI_PTYPE2_FIX_VAR: + break; + + default: + case ACPI_PTYPE1_FIXED: + case ACPI_PTYPE1_OPTION: + return; + } + + Count = ObjDesc->Package.Count; + NewCount = Count; + + Source = ObjDesc->Package.Elements; + Dest = Source; + + /* Examine all elements of the package object, remove nulls */ + + for (i = 0; i < Count; i++) + { + if (!*Source) + { + NewCount--; + } + else + { + *Dest = *Source; + Dest++; + } + Source++; + } + + /* Update parent package if any null elements were removed */ + + if (NewCount < Count) + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Found and removed %u NULL elements\n", + Data->Pathname, (Count - NewCount))); + + /* NULL terminate list and update the package count */ + + *Dest = NULL; + ObjDesc->Package.Count = NewCount; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRepairPackageList + * + * PARAMETERS: Data - Pointer to validation data structure + * ObjDescPtr - Pointer to the object to repair. The new + * package object is returned here, + * overwriting the old object. + * + * RETURN: Status, new object in *ObjDescPtr + * + * DESCRIPTION: Repair a common problem with objects that are defined to return + * a variable-length Package of Packages. If the variable-length + * is one, some BIOS code mistakenly simply declares a single + * Package instead of a Package with one sub-Package. This + * function attempts to repair this error by wrapping a Package + * object around the original Package, creating the correct + * Package with one sub-Package. + * + * Names that can be repaired in this manner include: + * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsRepairPackageList ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_OPERAND_OBJECT *PkgObjDesc; + + + ACPI_FUNCTION_NAME (NsRepairPackageList); + + + /* + * Create the new outer package and populate it. The new package will + * have a single element, the lone subpackage. + */ + PkgObjDesc = AcpiUtCreatePackageObject (1); + if (!PkgObjDesc) + { + return (AE_NO_MEMORY); + } + + PkgObjDesc->Package.Elements[0] = *ObjDescPtr; + + /* Return the new object in the object pointer */ + + *ObjDescPtr = PkgObjDesc; + Data->Flags |= ACPI_OBJECT_REPAIRED; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Repaired incorrectly formed Package\n", Data->Pathname)); + + return (AE_OK); +} diff --git a/source/components/namespace/nsrepair2.c b/source/components/namespace/nsrepair2.c new file mode 100644 index 000000000000..a6a4d6874dec --- /dev/null +++ b/source/components/namespace/nsrepair2.c @@ -0,0 +1,827 @@ +/****************************************************************************** + * + * Module Name: nsrepair2 - Repair for objects returned by specific + * predefined methods + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSREPAIR2_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsrepair2") + + +/* + * Information structure and handler for ACPI predefined names that can + * be repaired on a per-name basis. + */ +typedef +ACPI_STATUS (*ACPI_REPAIR_FUNCTION) ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +typedef struct acpi_repair_info +{ + char Name[ACPI_NAME_SIZE]; + ACPI_REPAIR_FUNCTION RepairFunction; + +} ACPI_REPAIR_INFO; + + +/* Local prototypes */ + +static const ACPI_REPAIR_INFO * +AcpiNsMatchRepairableName ( + ACPI_NAMESPACE_NODE *Node); + +static ACPI_STATUS +AcpiNsRepair_ALR ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_CID ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_FDE ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_HID ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_PSS ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_TSS ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsCheckSortedList ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT *ReturnObject, + UINT32 ExpectedCount, + UINT32 SortIndex, + UINT8 SortDirection, + char *SortKeyName); + +static void +AcpiNsSortList ( + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count, + UINT32 Index, + UINT8 SortDirection); + +/* Values for SortDirection above */ + +#define ACPI_SORT_ASCENDING 0 +#define ACPI_SORT_DESCENDING 1 + + +/* + * This table contains the names of the predefined methods for which we can + * perform more complex repairs. + * + * As necessary: + * + * _ALR: Sort the list ascending by AmbientIlluminance + * _CID: Strings: uppercase all, remove any leading asterisk + * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs + * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs + * _HID: Strings: uppercase all, remove any leading asterisk + * _PSS: Sort the list descending by Power + * _TSS: Sort the list descending by Power + * + * Names that must be packages, but cannot be sorted: + * + * _BCL: Values are tied to the Package index where they appear, and cannot + * be moved or sorted. These index values are used for _BQC and _BCM. + * However, we can fix the case where a buffer is returned, by converting + * it to a Package of integers. + */ +static const ACPI_REPAIR_INFO AcpiNsRepairableNames[] = +{ + {"_ALR", AcpiNsRepair_ALR}, + {"_CID", AcpiNsRepair_CID}, + {"_FDE", AcpiNsRepair_FDE}, + {"_GTM", AcpiNsRepair_FDE}, /* _GTM has same repair as _FDE */ + {"_HID", AcpiNsRepair_HID}, + {"_PSS", AcpiNsRepair_PSS}, + {"_TSS", AcpiNsRepair_TSS}, + {{0,0,0,0}, NULL} /* Table terminator */ +}; + + +#define ACPI_FDE_FIELD_COUNT 5 +#define ACPI_FDE_BYTE_BUFFER_SIZE 5 +#define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (UINT32)) + + +/****************************************************************************** + * + * FUNCTION: AcpiNsComplexRepairs + * + * PARAMETERS: Data - Pointer to validation data structure + * Node - Namespace node for the method/object + * ValidateStatus - Original status of earlier validation + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if repair was successful. If name is not + * matched, ValidateStatus is returned. + * + * DESCRIPTION: Attempt to repair/convert a return object of a type that was + * not expected. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiNsComplexRepairs ( + ACPI_PREDEFINED_DATA *Data, + ACPI_NAMESPACE_NODE *Node, + ACPI_STATUS ValidateStatus, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + const ACPI_REPAIR_INFO *Predefined; + ACPI_STATUS Status; + + + /* Check if this name is in the list of repairable names */ + + Predefined = AcpiNsMatchRepairableName (Node); + if (!Predefined) + { + return (ValidateStatus); + } + + Status = Predefined->RepairFunction (Data, ReturnObjectPtr); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsMatchRepairableName + * + * PARAMETERS: Node - Namespace node for the method/object + * + * RETURN: Pointer to entry in repair table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the repairable object list. + * + *****************************************************************************/ + +static const ACPI_REPAIR_INFO * +AcpiNsMatchRepairableName ( + ACPI_NAMESPACE_NODE *Node) +{ + const ACPI_REPAIR_INFO *ThisName; + + + /* Search info table for a repairable predefined method/object name */ + + ThisName = AcpiNsRepairableNames; + while (ThisName->RepairFunction) + { + if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) + { + return (ThisName); + } + ThisName++; + } + + return (NULL); /* Not found */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_ALR + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list + * ascending by the ambient illuminance values. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_ALR ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status; + + + Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1, + ACPI_SORT_ASCENDING, "AmbientIlluminance"); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_FDE + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return + * value is a Buffer of 5 DWORDs. This function repairs a common + * problem where the return value is a Buffer of BYTEs, not + * DWORDs. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_FDE ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *BufferObject; + UINT8 *ByteBuffer; + UINT32 *DwordBuffer; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsRepair_FDE); + + + switch (ReturnObject->Common.Type) + { + case ACPI_TYPE_BUFFER: + + /* This is the expected type. Length should be (at least) 5 DWORDs */ + + if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE) + { + return (AE_OK); + } + + /* We can only repair if we have exactly 5 BYTEs */ + + if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Incorrect return buffer length %u, expected %u", + ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE)); + + return (AE_AML_OPERAND_TYPE); + } + + /* Create the new (larger) buffer object */ + + BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE); + if (!BufferObject) + { + return (AE_NO_MEMORY); + } + + /* Expand each byte to a DWORD */ + + ByteBuffer = ReturnObject->Buffer.Pointer; + DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer); + + for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) + { + *DwordBuffer = (UINT32) *ByteBuffer; + DwordBuffer++; + ByteBuffer++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s Expanded Byte Buffer to expected DWord Buffer\n", + Data->Pathname)); + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + /* Delete the original return object, return the new buffer object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = BufferObject; + + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_CID + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _CID object. If a string, ensure that all + * letters are uppercase and that there is no leading asterisk. + * If a Package, ensure same for all string elements. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_CID ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT **ElementPtr; + ACPI_OPERAND_OBJECT *OriginalElement; + UINT16 OriginalRefCount; + UINT32 i; + + + /* Check for _CID as a simple string */ + + if (ReturnObject->Common.Type == ACPI_TYPE_STRING) + { + Status = AcpiNsRepair_HID (Data, ReturnObjectPtr); + return (Status); + } + + /* Exit if not a Package */ + + if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) + { + return (AE_OK); + } + + /* Examine each element of the _CID package */ + + ElementPtr = ReturnObject->Package.Elements; + for (i = 0; i < ReturnObject->Package.Count; i++) + { + OriginalElement = *ElementPtr; + OriginalRefCount = OriginalElement->Common.ReferenceCount; + + Status = AcpiNsRepair_HID (Data, ElementPtr); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Take care with reference counts */ + + if (OriginalElement != *ElementPtr) + { + /* Element was replaced */ + + (*ElementPtr)->Common.ReferenceCount = + OriginalRefCount; + + AcpiUtRemoveReference (OriginalElement); + } + + ElementPtr++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_HID + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _HID object. If a string, ensure that all + * letters are uppercase and that there is no leading asterisk. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_HID ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *NewString; + char *Source; + char *Dest; + + + ACPI_FUNCTION_NAME (NsRepair_HID); + + + /* We only care about string _HID objects (not integers) */ + + if (ReturnObject->Common.Type != ACPI_TYPE_STRING) + { + return (AE_OK); + } + + if (ReturnObject->String.Length == 0) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Invalid zero-length _HID or _CID string")); + + /* Return AE_OK anyway, let driver handle it */ + + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); + } + + /* It is simplest to always create a new string object */ + + NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); + if (!NewString) + { + return (AE_NO_MEMORY); + } + + /* + * Remove a leading asterisk if present. For some unknown reason, there + * are many machines in the field that contains IDs like this. + * + * Examples: "*PNP0C03", "*ACPI0003" + */ + Source = ReturnObject->String.Pointer; + if (*Source == '*') + { + Source++; + NewString->String.Length--; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Removed invalid leading asterisk\n", Data->Pathname)); + } + + /* + * Copy and uppercase the string. From the ACPI 5.0 specification: + * + * A valid PNP ID must be of the form "AAA####" where A is an uppercase + * letter and # is a hex digit. A valid ACPI ID must be of the form + * "NNNN####" where N is an uppercase letter or decimal digit, and + * # is a hex digit. + */ + for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) + { + *Dest = (char) ACPI_TOUPPER (*Source); + } + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = NewString; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_TSS + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list + * descending by the power dissipation values. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_TSS ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + /* + * We can only sort the _TSS return package if there is no _PSS in the + * same scope. This is because if _PSS is present, the ACPI specification + * dictates that the _TSS Power Dissipation field is to be ignored, and + * therefore some BIOSs leave garbage values in the _TSS Power field(s). + * In this case, it is best to just return the _TSS package as-is. + * (May, 2011) + */ + Status = AcpiNsGetNode (Data->Node, "^_PSS", ACPI_NS_NO_UPSEARCH, &Node); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); + } + + Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1, + ACPI_SORT_DESCENDING, "PowerDissipation"); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_PSS + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list + * by the CPU frequencies. Check that the power dissipation values + * are all proportional to CPU frequency (i.e., sorting by + * frequency should be the same as sorting by power.) + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_PSS ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT **OuterElements; + UINT32 OuterElementCount; + ACPI_OPERAND_OBJECT **Elements; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 PreviousValue; + ACPI_STATUS Status; + UINT32 i; + + + /* + * Entries (sub-packages) in the _PSS Package must be sorted by power + * dissipation, in descending order. If it appears that the list is + * incorrectly sorted, sort it. We sort by CpuFrequency, since this + * should be proportional to the power. + */ + Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0, + ACPI_SORT_DESCENDING, "CpuFrequency"); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * We now know the list is correctly sorted by CPU frequency. Check if + * the power dissipation values are proportional. + */ + PreviousValue = ACPI_UINT32_MAX; + OuterElements = ReturnObject->Package.Elements; + OuterElementCount = ReturnObject->Package.Count; + + for (i = 0; i < OuterElementCount; i++) + { + Elements = (*OuterElements)->Package.Elements; + ObjDesc = Elements[1]; /* Index1 = PowerDissipation */ + + if ((UINT32) ObjDesc->Integer.Value > PreviousValue) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "SubPackage[%u,%u] - suspicious power dissipation values", + i-1, i)); + } + + PreviousValue = (UINT32) ObjDesc->Integer.Value; + OuterElements++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsCheckSortedList + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObject - Pointer to the top-level returned object + * ExpectedCount - Minimum length of each sub-package + * SortIndex - Sub-package entry to sort on + * SortDirection - Ascending or descending + * SortKeyName - Name of the SortIndex field + * + * RETURN: Status. AE_OK if the list is valid and is sorted correctly or + * has been repaired by sorting the list. + * + * DESCRIPTION: Check if the package list is valid and sorted correctly by the + * SortIndex. If not, then sort the list. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsCheckSortedList ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT *ReturnObject, + UINT32 ExpectedCount, + UINT32 SortIndex, + UINT8 SortDirection, + char *SortKeyName) +{ + UINT32 OuterElementCount; + ACPI_OPERAND_OBJECT **OuterElements; + ACPI_OPERAND_OBJECT **Elements; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 i; + UINT32 PreviousValue; + + + ACPI_FUNCTION_NAME (NsCheckSortedList); + + + /* The top-level object must be a package */ + + if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) + { + return (AE_AML_OPERAND_TYPE); + } + + /* + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to AcpiNsRemoveNullElements. + */ + OuterElements = ReturnObject->Package.Elements; + OuterElementCount = ReturnObject->Package.Count; + if (!OuterElementCount) + { + return (AE_AML_PACKAGE_LIMIT); + } + + PreviousValue = 0; + if (SortDirection == ACPI_SORT_DESCENDING) + { + PreviousValue = ACPI_UINT32_MAX; + } + + /* Examine each subpackage */ + + for (i = 0; i < OuterElementCount; i++) + { + /* Each element of the top-level package must also be a package */ + + if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) + { + return (AE_AML_OPERAND_TYPE); + } + + /* Each sub-package must have the minimum length */ + + if ((*OuterElements)->Package.Count < ExpectedCount) + { + return (AE_AML_PACKAGE_LIMIT); + } + + Elements = (*OuterElements)->Package.Elements; + ObjDesc = Elements[SortIndex]; + + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + return (AE_AML_OPERAND_TYPE); + } + + /* + * The list must be sorted in the specified order. If we detect a + * discrepancy, sort the entire list. + */ + if (((SortDirection == ACPI_SORT_ASCENDING) && + (ObjDesc->Integer.Value < PreviousValue)) || + ((SortDirection == ACPI_SORT_DESCENDING) && + (ObjDesc->Integer.Value > PreviousValue))) + { + AcpiNsSortList (ReturnObject->Package.Elements, + OuterElementCount, SortIndex, SortDirection); + + Data->Flags |= ACPI_OBJECT_REPAIRED; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Repaired unsorted list - now sorted by %s\n", + Data->Pathname, SortKeyName)); + return (AE_OK); + } + + PreviousValue = (UINT32) ObjDesc->Integer.Value; + OuterElements++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsSortList + * + * PARAMETERS: Elements - Package object element list + * Count - Element count for above + * Index - Sort by which package element + * SortDirection - Ascending or Descending sort + * + * RETURN: None + * + * DESCRIPTION: Sort the objects that are in a package element list. + * + * NOTE: Assumes that all NULL elements have been removed from the package, + * and that all elements have been verified to be of type Integer. + * + *****************************************************************************/ + +static void +AcpiNsSortList ( + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count, + UINT32 Index, + UINT8 SortDirection) +{ + ACPI_OPERAND_OBJECT *ObjDesc1; + ACPI_OPERAND_OBJECT *ObjDesc2; + ACPI_OPERAND_OBJECT *TempObj; + UINT32 i; + UINT32 j; + + + /* Simple bubble sort */ + + for (i = 1; i < Count; i++) + { + for (j = (Count - 1); j >= i; j--) + { + ObjDesc1 = Elements[j-1]->Package.Elements[Index]; + ObjDesc2 = Elements[j]->Package.Elements[Index]; + + if (((SortDirection == ACPI_SORT_ASCENDING) && + (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) || + + ((SortDirection == ACPI_SORT_DESCENDING) && + (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value))) + { + TempObj = Elements[j-1]; + Elements[j-1] = Elements[j]; + Elements[j] = TempObj; + } + } + } +} diff --git a/source/components/namespace/nssearch.c b/source/components/namespace/nssearch.c new file mode 100644 index 000000000000..d6f59ccbd104 --- /dev/null +++ b/source/components/namespace/nssearch.c @@ -0,0 +1,424 @@ +/******************************************************************************* + * + * Module Name: nssearch - Namespace search + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSSEARCH_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + +#ifdef ACPI_ASL_COMPILER +#include "amlcode.h" +#endif + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nssearch") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsSearchParentTree ( + UINT32 TargetName, + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE **ReturnNode); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsSearchOneScope + * + * PARAMETERS: TargetName - Ascii ACPI name to search for + * ParentNode - Starting node where search will begin + * Type - Object type to match + * ReturnNode - Where the matched Named obj is returned + * + * RETURN: Status + * + * DESCRIPTION: Search a single level of the namespace. Performs a + * simple search of the specified level, and does not add + * entries or search parents. + * + * + * Named object lists are built (and subsequently dumped) in the + * order in which the names are encountered during the namespace load; + * + * All namespace searching is linear in this implementation, but + * could be easily modified to support any improved search + * algorithm. However, the linear search was chosen for simplicity + * and because the trees are small and the other interpreter + * execution overhead is relatively high. + * + * Note: CPU execution analysis has shown that the AML interpreter spends + * a very small percentage of its time searching the namespace. Therefore, + * the linear search seems to be sufficient, as there would seem to be + * little value in improving the search. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsSearchOneScope ( + UINT32 TargetName, + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (NsSearchOneScope); + + +#ifdef ACPI_DEBUG_OUTPUT + if (ACPI_LV_NAMES & AcpiDbgLevel) + { + char *ScopeName; + + ScopeName = AcpiNsGetExternalPathname (ParentNode); + if (ScopeName) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Searching %s (%p) For [%4.4s] (%s)\n", + ScopeName, ParentNode, ACPI_CAST_PTR (char, &TargetName), + AcpiUtGetTypeName (Type))); + + ACPI_FREE (ScopeName); + } + } +#endif + + /* + * Search for name at this namespace level, which is to say that we + * must search for the name among the children of this object + */ + Node = ParentNode->Child; + while (Node) + { + /* Check for match against the name */ + + if (Node->Name.Integer == TargetName) + { + /* Resolve a control method alias if any */ + + if (AcpiNsGetType (Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) + { + Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Node->Object); + } + + /* Found matching entry */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", + ACPI_CAST_PTR (char, &TargetName), + AcpiUtGetTypeName (Node->Type), + Node, AcpiUtGetNodeName (ParentNode), ParentNode)); + + *ReturnNode = Node; + return_ACPI_STATUS (AE_OK); + } + + /* Didn't match name, move on to the next peer object */ + + Node = Node->Peer; + } + + /* Searched entire namespace level, not found */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name [%4.4s] (%s) not found in search in scope [%4.4s] " + "%p first child %p\n", + ACPI_CAST_PTR (char, &TargetName), AcpiUtGetTypeName (Type), + AcpiUtGetNodeName (ParentNode), ParentNode, ParentNode->Child)); + + return_ACPI_STATUS (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsSearchParentTree + * + * PARAMETERS: TargetName - Ascii ACPI name to search for + * Node - Starting node where search will begin + * Type - Object type to match + * ReturnNode - Where the matched Node is returned + * + * RETURN: Status + * + * DESCRIPTION: Called when a name has not been found in the current namespace + * level. Before adding it or giving up, ACPI scope rules require + * searching enclosing scopes in cases identified by AcpiNsLocal(). + * + * "A name is located by finding the matching name in the current + * name space, and then in the parent name space. If the parent + * name space does not contain the name, the search continues + * recursively until either the name is found or the name space + * does not have a parent (the root of the name space). This + * indicates that the name is not found" (From ACPI Specification, + * section 5.3) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsSearchParentTree ( + UINT32 TargetName, + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *ParentNode; + + + ACPI_FUNCTION_TRACE (NsSearchParentTree); + + + ParentNode = Node->Parent; + + /* + * If there is no parent (i.e., we are at the root) or type is "local", + * we won't be searching the parent tree. + */ + if (!ParentNode) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n", + ACPI_CAST_PTR (char, &TargetName))); + return_ACPI_STATUS (AE_NOT_FOUND); + } + + if (AcpiNsLocal (Type)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "[%4.4s] type [%s] must be local to this scope (no parent search)\n", + ACPI_CAST_PTR (char, &TargetName), AcpiUtGetTypeName (Type))); + return_ACPI_STATUS (AE_NOT_FOUND); + } + + /* Search the parent tree */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Searching parent [%4.4s] for [%4.4s]\n", + AcpiUtGetNodeName (ParentNode), ACPI_CAST_PTR (char, &TargetName))); + + /* Search parents until target is found or we have backed up to the root */ + + while (ParentNode) + { + /* + * Search parent scope. Use TYPE_ANY because we don't care about the + * object type at this point, we only care about the existence of + * the actual name we are searching for. Typechecking comes later. + */ + Status = AcpiNsSearchOneScope ( + TargetName, ParentNode, ACPI_TYPE_ANY, ReturnNode); + if (ACPI_SUCCESS (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Not found here, go up another level (until we reach the root) */ + + ParentNode = ParentNode->Parent; + } + + /* Not found in parent tree */ + + return_ACPI_STATUS (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsSearchAndEnter + * + * PARAMETERS: TargetName - Ascii ACPI name to search for (4 chars) + * WalkState - Current state of the walk + * Node - Starting node where search will begin + * InterpreterMode - Add names only in ACPI_MODE_LOAD_PASS_x. + * Otherwise,search only. + * Type - Object type to match + * Flags - Flags describing the search restrictions + * ReturnNode - Where the Node is returned + * + * RETURN: Status + * + * DESCRIPTION: Search for a name segment in a single namespace level, + * optionally adding it if it is not found. If the passed + * Type is not Any and the type previously stored in the + * entry was Any (i.e. unknown), update the stored type. + * + * In ACPI_IMODE_EXECUTE, search only. + * In other modes, search and add if not found. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsSearchAndEnter ( + UINT32 TargetName, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *Node, + ACPI_INTERPRETER_MODE InterpreterMode, + ACPI_OBJECT_TYPE Type, + UINT32 Flags, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *NewNode; + + + ACPI_FUNCTION_TRACE (NsSearchAndEnter); + + + /* Parameter validation */ + + if (!Node || !TargetName || !ReturnNode) + { + ACPI_ERROR ((AE_INFO, + "Null parameter: Node %p Name 0x%X ReturnNode %p", + Node, TargetName, ReturnNode)); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Name must consist of valid ACPI characters. We will repair the name if + * necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + */ + AcpiUtRepairName (ACPI_CAST_PTR (char, &TargetName)); + + /* Try to find the name in the namespace level specified by the caller */ + + *ReturnNode = ACPI_ENTRY_NOT_FOUND; + Status = AcpiNsSearchOneScope (TargetName, Node, Type, ReturnNode); + if (Status != AE_NOT_FOUND) + { + /* + * If we found it AND the request specifies that a find is an error, + * return the error + */ + if ((Status == AE_OK) && + (Flags & ACPI_NS_ERROR_IF_FOUND)) + { + Status = AE_ALREADY_EXISTS; + } + +#ifdef ACPI_ASL_COMPILER + if (*ReturnNode && (*ReturnNode)->Type == ACPI_TYPE_ANY) + { + (*ReturnNode)->Flags |= ANOBJ_IS_EXTERNAL; + } +#endif + + /* Either found it or there was an error: finished either way */ + + return_ACPI_STATUS (Status); + } + + /* + * The name was not found. If we are NOT performing the first pass + * (name entry) of loading the namespace, search the parent tree (all the + * way to the root if necessary.) We don't want to perform the parent + * search when the namespace is actually being loaded. We want to perform + * the search when namespace references are being resolved (load pass 2) + * and during the execution phase. + */ + if ((InterpreterMode != ACPI_IMODE_LOAD_PASS1) && + (Flags & ACPI_NS_SEARCH_PARENT)) + { + /* + * Not found at this level - search parent tree according to the + * ACPI specification + */ + Status = AcpiNsSearchParentTree (TargetName, Node, Type, ReturnNode); + if (ACPI_SUCCESS (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* In execute mode, just search, never add names. Exit now */ + + if (InterpreterMode == ACPI_IMODE_EXECUTE) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%4.4s Not found in %p [Not adding]\n", + ACPI_CAST_PTR (char, &TargetName), Node)); + + return_ACPI_STATUS (AE_NOT_FOUND); + } + + /* Create the new named object */ + + NewNode = AcpiNsCreateNode (TargetName); + if (!NewNode) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + +#ifdef ACPI_ASL_COMPILER + + /* Node is an object defined by an External() statement */ + + if (Flags & ACPI_NS_EXTERNAL || + (WalkState && WalkState->Opcode == AML_SCOPE_OP)) + { + NewNode->Flags |= ANOBJ_IS_EXTERNAL; + } +#endif + + if (Flags & ACPI_NS_TEMPORARY) + { + NewNode->Flags |= ANOBJ_TEMPORARY; + } + + /* Install the new object into the parent's list of children */ + + AcpiNsInstallNode (WalkState, Node, NewNode, Type); + *ReturnNode = NewNode; + return_ACPI_STATUS (AE_OK); +} + diff --git a/source/components/namespace/nsutils.c b/source/components/namespace/nsutils.c new file mode 100644 index 000000000000..3b07f83a9e33 --- /dev/null +++ b/source/components/namespace/nsutils.c @@ -0,0 +1,875 @@ +/****************************************************************************** + * + * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing + * parents and siblings and Scope manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSUTILS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsutils") + +/* Local prototypes */ + +static BOOLEAN +AcpiNsValidPathSeparator ( + char Sep); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +ACPI_NAME +AcpiNsFindParentName ( + ACPI_NAMESPACE_NODE *NodeToSearch); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiNsPrintNodePathname + * + * PARAMETERS: Node - Object + * Message - Prefix message + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +void +AcpiNsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Message) +{ + ACPI_BUFFER Buffer; + ACPI_STATUS Status; + + + if (!Node) + { + AcpiOsPrintf ("[NULL NAME]"); + return; + } + + /* Convert handle to full pathname and print it (with supplied message) */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + Status = AcpiNsHandleToPathname (Node, &Buffer); + if (ACPI_SUCCESS (Status)) + { + if (Message) + { + AcpiOsPrintf ("%s ", Message); + } + + AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node); + ACPI_FREE (Buffer.Pointer); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsValidRootPrefix + * + * PARAMETERS: Prefix - Character to be checked + * + * RETURN: TRUE if a valid prefix + * + * DESCRIPTION: Check if a character is a valid ACPI Root prefix + * + ******************************************************************************/ + +BOOLEAN +AcpiNsValidRootPrefix ( + char Prefix) +{ + + return ((BOOLEAN) (Prefix == '\\')); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsValidPathSeparator + * + * PARAMETERS: Sep - Character to be checked + * + * RETURN: TRUE if a valid path separator + * + * DESCRIPTION: Check if a character is a valid ACPI path separator + * + ******************************************************************************/ + +static BOOLEAN +AcpiNsValidPathSeparator ( + char Sep) +{ + + return ((BOOLEAN) (Sep == '.')); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetType + * + * PARAMETERS: Node - Parent Node to be examined + * + * RETURN: Type field from Node whose handle is passed + * + * DESCRIPTION: Return the type of a Namespace node + * + ******************************************************************************/ + +ACPI_OBJECT_TYPE +AcpiNsGetType ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_FUNCTION_TRACE (NsGetType); + + + if (!Node) + { + ACPI_WARNING ((AE_INFO, "Null Node parameter")); + return_UINT32 (ACPI_TYPE_ANY); + } + + return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsLocal + * + * PARAMETERS: Type - A namespace object type + * + * RETURN: LOCAL if names must be found locally in objects of the + * passed type, 0 if enclosing scopes should be searched + * + * DESCRIPTION: Returns scope rule for the given object type. + * + ******************************************************************************/ + +UINT32 +AcpiNsLocal ( + ACPI_OBJECT_TYPE Type) +{ + ACPI_FUNCTION_TRACE (NsLocal); + + + if (!AcpiUtValidObjectType (Type)) + { + /* Type code out of range */ + + ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); + return_UINT32 (ACPI_NS_NORMAL); + } + + return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetInternalNameLength + * + * PARAMETERS: Info - Info struct initialized with the + * external name pointer. + * + * RETURN: None + * + * DESCRIPTION: Calculate the length of the internal (AML) namestring + * corresponding to the external (ASL) namestring. + * + ******************************************************************************/ + +void +AcpiNsGetInternalNameLength ( + ACPI_NAMESTRING_INFO *Info) +{ + const char *NextExternalChar; + UINT32 i; + + + ACPI_FUNCTION_ENTRY (); + + + NextExternalChar = Info->ExternalName; + Info->NumCarats = 0; + Info->NumSegments = 0; + Info->FullyQualified = FALSE; + + /* + * For the internal name, the required length is 4 bytes per segment, plus + * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null + * (which is not really needed, but no there's harm in putting it there) + * + * strlen() + 1 covers the first NameSeg, which has no path separator + */ + if (AcpiNsValidRootPrefix (*NextExternalChar)) + { + Info->FullyQualified = TRUE; + NextExternalChar++; + + /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */ + + while (AcpiNsValidRootPrefix (*NextExternalChar)) + { + NextExternalChar++; + } + } + else + { + /* Handle Carat prefixes */ + + while (*NextExternalChar == '^') + { + Info->NumCarats++; + NextExternalChar++; + } + } + + /* + * Determine the number of ACPI name "segments" by counting the number of + * path separators within the string. Start with one segment since the + * segment count is [(# separators) + 1], and zero separators is ok. + */ + if (*NextExternalChar) + { + Info->NumSegments = 1; + for (i = 0; NextExternalChar[i]; i++) + { + if (AcpiNsValidPathSeparator (NextExternalChar[i])) + { + Info->NumSegments++; + } + } + } + + Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) + + 4 + Info->NumCarats; + + Info->NextExternalChar = NextExternalChar; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsBuildInternalName + * + * PARAMETERS: Info - Info struct fully initialized + * + * RETURN: Status + * + * DESCRIPTION: Construct the internal (AML) namestring + * corresponding to the external (ASL) namestring. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsBuildInternalName ( + ACPI_NAMESTRING_INFO *Info) +{ + UINT32 NumSegments = Info->NumSegments; + char *InternalName = Info->InternalName; + const char *ExternalName = Info->NextExternalChar; + char *Result = NULL; + UINT32 i; + + + ACPI_FUNCTION_TRACE (NsBuildInternalName); + + + /* Setup the correct prefixes, counts, and pointers */ + + if (Info->FullyQualified) + { + InternalName[0] = '\\'; + + if (NumSegments <= 1) + { + Result = &InternalName[1]; + } + else if (NumSegments == 2) + { + InternalName[1] = AML_DUAL_NAME_PREFIX; + Result = &InternalName[2]; + } + else + { + InternalName[1] = AML_MULTI_NAME_PREFIX_OP; + InternalName[2] = (char) NumSegments; + Result = &InternalName[3]; + } + } + else + { + /* + * Not fully qualified. + * Handle Carats first, then append the name segments + */ + i = 0; + if (Info->NumCarats) + { + for (i = 0; i < Info->NumCarats; i++) + { + InternalName[i] = '^'; + } + } + + if (NumSegments <= 1) + { + Result = &InternalName[i]; + } + else if (NumSegments == 2) + { + InternalName[i] = AML_DUAL_NAME_PREFIX; + Result = &InternalName[(ACPI_SIZE) i+1]; + } + else + { + InternalName[i] = AML_MULTI_NAME_PREFIX_OP; + InternalName[(ACPI_SIZE) i+1] = (char) NumSegments; + Result = &InternalName[(ACPI_SIZE) i+2]; + } + } + + /* Build the name (minus path separators) */ + + for (; NumSegments; NumSegments--) + { + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (AcpiNsValidPathSeparator (*ExternalName) || + (*ExternalName == 0)) + { + /* Pad the segment with underscore(s) if segment is short */ + + Result[i] = '_'; + } + else + { + /* Convert the character to uppercase and save it */ + + Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName); + ExternalName++; + } + } + + /* Now we must have a path separator, or the pathname is bad */ + + if (!AcpiNsValidPathSeparator (*ExternalName) && + (*ExternalName != 0)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Move on the next segment */ + + ExternalName++; + Result += ACPI_NAME_SIZE; + } + + /* Terminate the string */ + + *Result = 0; + + if (Info->FullyQualified) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n", + InternalName, InternalName)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", + InternalName, InternalName)); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsInternalizeName + * + * PARAMETERS: *ExternalName - External representation of name + * **Converted Name - Where to return the resulting + * internal represention of the name + * + * RETURN: Status + * + * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") + * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * + *******************************************************************************/ + +ACPI_STATUS +AcpiNsInternalizeName ( + const char *ExternalName, + char **ConvertedName) +{ + char *InternalName; + ACPI_NAMESTRING_INFO Info; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsInternalizeName); + + + if ((!ExternalName) || + (*ExternalName == 0) || + (!ConvertedName)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the length of the new internal name */ + + Info.ExternalName = ExternalName; + AcpiNsGetInternalNameLength (&Info); + + /* We need a segment to store the internal name */ + + InternalName = ACPI_ALLOCATE_ZEROED (Info.Length); + if (!InternalName) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Build the name */ + + Info.InternalName = InternalName; + Status = AcpiNsBuildInternalName (&Info); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (InternalName); + return_ACPI_STATUS (Status); + } + + *ConvertedName = InternalName; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsExternalizeName + * + * PARAMETERS: InternalNameLength - Lenth of the internal name below + * InternalName - Internal representation of name + * ConvertedNameLength - Where the length is returned + * ConvertedName - Where the resulting external name + * is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * to its external (printable) form (e.g. "\_PR_.CPU0") + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsExternalizeName ( + UINT32 InternalNameLength, + const char *InternalName, + UINT32 *ConvertedNameLength, + char **ConvertedName) +{ + UINT32 NamesIndex = 0; + UINT32 NumSegments = 0; + UINT32 RequiredLength; + UINT32 PrefixLength = 0; + UINT32 i = 0; + UINT32 j = 0; + + + ACPI_FUNCTION_TRACE (NsExternalizeName); + + + if (!InternalNameLength || + !InternalName || + !ConvertedName) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Check for a prefix (one '\' | one or more '^') */ + + switch (InternalName[0]) + { + case '\\': + PrefixLength = 1; + break; + + case '^': + for (i = 0; i < InternalNameLength; i++) + { + if (InternalName[i] == '^') + { + PrefixLength = i + 1; + } + else + { + break; + } + } + + if (i == InternalNameLength) + { + PrefixLength = i; + } + + break; + + default: + break; + } + + /* + * Check for object names. Note that there could be 0-255 of these + * 4-byte elements. + */ + if (PrefixLength < InternalNameLength) + { + switch (InternalName[PrefixLength]) + { + case AML_MULTI_NAME_PREFIX_OP: + + /* 4-byte names */ + + NamesIndex = PrefixLength + 2; + NumSegments = (UINT8) + InternalName[(ACPI_SIZE) PrefixLength + 1]; + break; + + case AML_DUAL_NAME_PREFIX: + + /* Two 4-byte names */ + + NamesIndex = PrefixLength + 1; + NumSegments = 2; + break; + + case 0: + + /* NullName */ + + NamesIndex = 0; + NumSegments = 0; + break; + + default: + + /* one 4-byte name */ + + NamesIndex = PrefixLength; + NumSegments = 1; + break; + } + } + + /* + * Calculate the length of ConvertedName, which equals the length + * of the prefix, length of all object names, length of any required + * punctuation ('.') between object names, plus the NULL terminator. + */ + RequiredLength = PrefixLength + (4 * NumSegments) + + ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1; + + /* + * Check to see if we're still in bounds. If not, there's a problem + * with InternalName (invalid format). + */ + if (RequiredLength > InternalNameLength) + { + ACPI_ERROR ((AE_INFO, "Invalid internal name")); + return_ACPI_STATUS (AE_BAD_PATHNAME); + } + + /* Build the ConvertedName */ + + *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength); + if (!(*ConvertedName)) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + j = 0; + + for (i = 0; i < PrefixLength; i++) + { + (*ConvertedName)[j++] = InternalName[i]; + } + + if (NumSegments > 0) + { + for (i = 0; i < NumSegments; i++) + { + if (i > 0) + { + (*ConvertedName)[j++] = '.'; + } + + (*ConvertedName)[j++] = InternalName[NamesIndex++]; + (*ConvertedName)[j++] = InternalName[NamesIndex++]; + (*ConvertedName)[j++] = InternalName[NamesIndex++]; + (*ConvertedName)[j++] = InternalName[NamesIndex++]; + } + } + + if (ConvertedNameLength) + { + *ConvertedNameLength = (UINT32) RequiredLength; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsValidateHandle + * + * PARAMETERS: Handle - Handle to be validated and typecast to a + * namespace node. + * + * RETURN: A pointer to a namespace node + * + * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special + * cases for the root node. + * + * NOTE: Real integer handles would allow for more verification + * and keep all pointers within this subsystem - however this introduces + * more overhead and has not been necessary to this point. Drivers + * holding handles are typically notified before a node becomes invalid + * due to a table unload. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiNsValidateHandle ( + ACPI_HANDLE Handle) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* Parameter validation */ + + if ((!Handle) || (Handle == ACPI_ROOT_OBJECT)) + { + return (AcpiGbl_RootNode); + } + + /* We can at least attempt to verify the handle */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED) + { + return (NULL); + } + + return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsTerminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for namespace and ACPI table storage. + * + ******************************************************************************/ + +void +AcpiNsTerminate ( + void) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + ACPI_FUNCTION_TRACE (NsTerminate); + + + /* + * 1) Free the entire namespace -- all nodes and objects + * + * Delete all object descriptors attached to namepsace nodes + */ + AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); + + /* Detach any objects attached to the root */ + + ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); + if (ObjDesc) + { + AcpiNsDetachObject (AcpiGbl_RootNode); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsOpensScope + * + * PARAMETERS: Type - A valid namespace type + * + * RETURN: NEWSCOPE if the passed type "opens a name scope" according + * to the ACPI specification, else 0 + * + ******************************************************************************/ + +UINT32 +AcpiNsOpensScope ( + ACPI_OBJECT_TYPE Type) +{ + ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type)); + + + if (!AcpiUtValidObjectType (Type)) + { + /* type code out of range */ + + ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); + return_UINT32 (ACPI_NS_NORMAL); + } + + return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNode + * + * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The + * \ (backslash) and ^ (carat) prefixes, and the + * . (period) to separate segments are supported. + * PrefixNode - Root of subtree to be searched, or NS_ALL for the + * root of the name space. If Name is fully + * qualified (first INT8 is '\'), the passed value + * of Scope will not be accessed. + * Flags - Used to indicate whether to perform upsearch or + * not. + * ReturnNode - Where the Node is returned + * + * DESCRIPTION: Look up a name relative to a given scope and return the + * corresponding Node. NOTE: Scope can be null. + * + * MUTEX: Locks namespace + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsGetNode ( + ACPI_NAMESPACE_NODE *PrefixNode, + const char *Pathname, + UINT32 Flags, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_GENERIC_STATE ScopeInfo; + ACPI_STATUS Status; + char *InternalPath; + + + ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname)); + + + if (!Pathname) + { + *ReturnNode = PrefixNode; + if (!PrefixNode) + { + *ReturnNode = AcpiGbl_RootNode; + } + return_ACPI_STATUS (AE_OK); + } + + /* Convert path to internal representation */ + + Status = AcpiNsInternalizeName (Pathname, &InternalPath); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Must lock namespace during lookup */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Setup lookup scope (search starting point) */ + + ScopeInfo.Scope.Node = PrefixNode; + + /* Lookup the name in the namespace */ + + Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE), + NULL, ReturnNode); + if (ACPI_FAILURE (Status)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n", + Pathname, AcpiFormatException (Status))); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + +Cleanup: + ACPI_FREE (InternalPath); + return_ACPI_STATUS (Status); +} diff --git a/source/components/namespace/nswalk.c b/source/components/namespace/nswalk.c new file mode 100644 index 000000000000..35c3e178966a --- /dev/null +++ b/source/components/namespace/nswalk.c @@ -0,0 +1,386 @@ +/****************************************************************************** + * + * Module Name: nswalk - Functions for walking the ACPI namespace + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSWALK_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nswalk") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNextNode + * + * PARAMETERS: ParentNode - Parent node whose children we are + * getting + * ChildNode - Previous child that was found. + * The NEXT child will be returned + * + * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if + * none is found. + * + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node + * within Scope is returned. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiNsGetNextNode ( + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_NAMESPACE_NODE *ChildNode) +{ + ACPI_FUNCTION_ENTRY (); + + + if (!ChildNode) + { + /* It's really the parent's _scope_ that we want */ + + return (ParentNode->Child); + } + + /* Otherwise just return the next peer */ + + return (ChildNode->Peer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNextNodeTyped + * + * PARAMETERS: Type - Type of node to be searched for + * ParentNode - Parent node whose children we are + * getting + * ChildNode - Previous child that was found. + * The NEXT child will be returned + * + * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if + * none is found. + * + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node + * within Scope is returned. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +AcpiNsGetNextNodeTyped ( + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_NAMESPACE_NODE *ChildNode) +{ + ACPI_NAMESPACE_NODE *NextNode = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + NextNode = AcpiNsGetNextNode (ParentNode, ChildNode); + + /* If any type is OK, we are done */ + + if (Type == ACPI_TYPE_ANY) + { + /* NextNode is NULL if we are at the end-of-list */ + + return (NextNode); + } + + /* Must search for the node -- but within this scope only */ + + while (NextNode) + { + /* If type matches, we are done */ + + if (NextNode->Type == Type) + { + return (NextNode); + } + + /* Otherwise, move on to the next peer node */ + + NextNode = NextNode->Peer; + } + + /* Not found */ + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsWalkNamespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * StartNode - Handle in namespace where search begins + * MaxDepth - Depth to which search is to reach + * Flags - Whether to unlock the NS before invoking + * the callback routine + * PreOrderVisit - Called during tree pre-order visit + * when an object of "Type" is found + * PostOrderVisit - Called during tree post-order visit + * when an object of "Type" is found + * Context - Passed to user function(s) above + * ReturnValue - from the UserFunction if terminated + * early. Otherwise, returns NULL. + * RETURNS: Status + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the node specified by StartHandle. + * The callback function is called whenever a node that matches + * the type parameter is found. If the callback function returns + * a non-zero value, the search is terminated immediately and + * this value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the callback function(s) can be + * tailored to each task, whether it is a print function, + * a compare function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsWalkNamespace ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE StartNode, + UINT32 MaxDepth, + UINT32 Flags, + ACPI_WALK_CALLBACK PreOrderVisit, + ACPI_WALK_CALLBACK PostOrderVisit, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + ACPI_STATUS MutexStatus; + ACPI_NAMESPACE_NODE *ChildNode; + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_OBJECT_TYPE ChildType; + UINT32 Level; + BOOLEAN NodePreviouslyVisited = FALSE; + + + ACPI_FUNCTION_TRACE (NsWalkNamespace); + + + /* Special case for the namespace Root Node */ + + if (StartNode == ACPI_ROOT_OBJECT) + { + StartNode = AcpiGbl_RootNode; + } + + /* Null child means "get first node" */ + + ParentNode = StartNode; + ChildNode = AcpiNsGetNextNode (ParentNode, NULL); + ChildType = ACPI_TYPE_ANY; + Level = 1; + + /* + * Traverse the tree of nodes until we bubble back up to where we + * started. When Level is zero, the loop is done because we have + * bubbled up to (and passed) the original parent handle (StartEntry) + */ + while (Level > 0 && ChildNode) + { + Status = AE_OK; + + /* Found next child, get the type if we are not searching for ANY */ + + if (Type != ACPI_TYPE_ANY) + { + ChildType = ChildNode->Type; + } + + /* + * Ignore all temporary namespace nodes (created during control + * method execution) unless told otherwise. These temporary nodes + * can cause a race condition because they can be deleted during + * the execution of the user function (if the namespace is + * unlocked before invocation of the user function.) Only the + * debugger namespace dump will examine the temporary nodes. + */ + if ((ChildNode->Flags & ANOBJ_TEMPORARY) && + !(Flags & ACPI_NS_WALK_TEMP_NODES)) + { + Status = AE_CTRL_DEPTH; + } + + /* Type must match requested type */ + + else if (ChildType == Type) + { + /* + * Found a matching node, invoke the user callback function. + * Unlock the namespace if flag is set. + */ + if (Flags & ACPI_NS_WALK_UNLOCK) + { + MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (MutexStatus)) + { + return_ACPI_STATUS (MutexStatus); + } + } + + /* + * Invoke the user function, either pre-order or post-order + * or both. + */ + if (!NodePreviouslyVisited) + { + if (PreOrderVisit) + { + Status = PreOrderVisit (ChildNode, Level, + Context, ReturnValue); + } + } + else + { + if (PostOrderVisit) + { + Status = PostOrderVisit (ChildNode, Level, + Context, ReturnValue); + } + } + + if (Flags & ACPI_NS_WALK_UNLOCK) + { + MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (MutexStatus)) + { + return_ACPI_STATUS (MutexStatus); + } + } + + switch (Status) + { + case AE_OK: + case AE_CTRL_DEPTH: + + /* Just keep going */ + break; + + case AE_CTRL_TERMINATE: + + /* Exit now, with OK status */ + + return_ACPI_STATUS (AE_OK); + + default: + + /* All others are valid exceptions */ + + return_ACPI_STATUS (Status); + } + } + + /* + * Depth first search: Attempt to go down another level in the + * namespace if we are allowed to. Don't go any further if we have + * reached the caller specified maximum depth or if the user + * function has specified that the maximum depth has been reached. + */ + if (!NodePreviouslyVisited && + (Level < MaxDepth) && + (Status != AE_CTRL_DEPTH)) + { + if (ChildNode->Child) + { + /* There is at least one child of this node, visit it */ + + Level++; + ParentNode = ChildNode; + ChildNode = AcpiNsGetNextNode (ParentNode, NULL); + continue; + } + } + + /* No more children, re-visit this node */ + + if (!NodePreviouslyVisited) + { + NodePreviouslyVisited = TRUE; + continue; + } + + /* No more children, visit peers */ + + ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); + if (ChildNode) + { + NodePreviouslyVisited = FALSE; + } + + /* No peers, re-visit parent */ + + else + { + /* + * No more children of this node (AcpiNsGetNextNode failed), go + * back upwards in the namespace tree to the node's parent. + */ + Level--; + ChildNode = ParentNode; + ParentNode = ParentNode->Parent; + + NodePreviouslyVisited = TRUE; + } + } + + /* Complete walk, not terminated by user function */ + + return_ACPI_STATUS (AE_OK); +} + + diff --git a/source/components/namespace/nsxfeval.c b/source/components/namespace/nsxfeval.c new file mode 100644 index 000000000000..5006588e85b6 --- /dev/null +++ b/source/components/namespace/nsxfeval.c @@ -0,0 +1,960 @@ +/******************************************************************************* + * + * Module Name: nsxfeval - Public interfaces to the ACPI subsystem + * ACPI Object evaluation interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSXFEVAL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsxfeval") + +/* Local prototypes */ + +static void +AcpiNsResolveReferences ( + ACPI_EVALUATE_INFO *Info); + + +/******************************************************************************* + * + * FUNCTION: AcpiEvaluateObjectTyped + * + * PARAMETERS: Handle - Object handle (optional) + * Pathname - Object pathname (optional) + * ExternalParams - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * ReturnBuffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * ReturnType - Expected type of return object + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvaluateObjectTyped ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ExternalParams, + ACPI_BUFFER *ReturnBuffer, + ACPI_OBJECT_TYPE ReturnType) +{ + ACPI_STATUS Status; + BOOLEAN MustFree = FALSE; + + + ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped); + + + /* Return buffer must be valid */ + + if (!ReturnBuffer) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER) + { + MustFree = TRUE; + } + + /* Evaluate the object */ + + Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Type ANY means "don't care" */ + + if (ReturnType == ACPI_TYPE_ANY) + { + return_ACPI_STATUS (AE_OK); + } + + if (ReturnBuffer->Length == 0) + { + /* Error because caller specifically asked for a return value */ + + ACPI_ERROR ((AE_INFO, "No return value")); + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Examine the object type returned from EvaluateObject */ + + if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType) + { + return_ACPI_STATUS (AE_OK); + } + + /* Return object type does not match requested type */ + + ACPI_ERROR ((AE_INFO, + "Incorrect return type [%s] requested [%s]", + AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type), + AcpiUtGetTypeName (ReturnType))); + + if (MustFree) + { + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ + + AcpiOsFree (ReturnBuffer->Pointer); + ReturnBuffer->Pointer = NULL; + } + + ReturnBuffer->Length = 0; + return_ACPI_STATUS (AE_TYPE); +} + +ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped) + + +/******************************************************************************* + * + * FUNCTION: AcpiEvaluateObject + * + * PARAMETERS: Handle - Object handle (optional) + * Pathname - Object pathname (optional) + * ExternalParams - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * ReturnBuffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvaluateObject ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ExternalParams, + ACPI_BUFFER *ReturnBuffer) +{ + ACPI_STATUS Status; + ACPI_EVALUATE_INFO *Info; + ACPI_SIZE BufferSpaceNeeded; + UINT32 i; + + + ACPI_FUNCTION_TRACE (AcpiEvaluateObject); + + + /* Allocate and initialize the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->Pathname = Pathname; + + /* Convert and validate the device handle */ + + Info->PrefixNode = AcpiNsValidateHandle (Handle); + if (!Info->PrefixNode) + { + Status = AE_BAD_PARAMETER; + goto Cleanup; + } + + /* + * If there are parameters to be passed to a control method, the external + * objects must all be converted to internal objects + */ + if (ExternalParams && ExternalParams->Count) + { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + Info->Parameters = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *)); + if (!Info->Parameters) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Convert each external object in the list to an internal object */ + + for (i = 0; i < ExternalParams->Count; i++) + { + Status = AcpiUtCopyEobjectToIobject ( + &ExternalParams->Pointer[i], &Info->Parameters[i]); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + Info->Parameters[ExternalParams->Count] = NULL; + } + + /* + * Three major cases: + * 1) Fully qualified pathname + * 2) No handle, not fully qualified pathname (error) + * 3) Valid handle + */ + if ((Pathname) && + (AcpiNsValidRootPrefix (Pathname[0]))) + { + /* The path is fully qualified, just evaluate by name */ + + Info->PrefixNode = NULL; + Status = AcpiNsEvaluate (Info); + } + else if (!Handle) + { + /* + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error + */ + if (!Pathname) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", Pathname)); + } + + Status = AE_BAD_PARAMETER; + } + else + { + /* We have a namespace a node and a possible relative path */ + + Status = AcpiNsEvaluate (Info); + } + + /* + * If we are expecting a return value, and all went well above, + * copy the return value to an external object. + */ + if (ReturnBuffer) + { + if (!Info->ReturnObject) + { + ReturnBuffer->Length = 0; + } + else + { + if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) == + ACPI_DESC_TYPE_NAMED) + { + /* + * If we received a NS Node as a return object, this means that + * the object we are evaluating has nothing interesting to + * return (such as a mutex, etc.) We return an error because + * these types are essentially unsupported by this interface. + * We don't check up front because this makes it easier to add + * support for various types at a later date if necessary. + */ + Status = AE_TYPE; + Info->ReturnObject = NULL; /* No need to delete a NS Node */ + ReturnBuffer->Length = 0; + } + + if (ACPI_SUCCESS (Status)) + { + /* Dereference Index and RefOf references */ + + AcpiNsResolveReferences (Info); + + /* Get the size of the returned object */ + + Status = AcpiUtGetObjectSize (Info->ReturnObject, + &BufferSpaceNeeded); + if (ACPI_SUCCESS (Status)) + { + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (ReturnBuffer, + BufferSpaceNeeded); + if (ACPI_FAILURE (Status)) + { + /* + * Caller's buffer is too small or a new one can't + * be allocated + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Needed buffer size %X, %s\n", + (UINT32) BufferSpaceNeeded, + AcpiFormatException (Status))); + } + else + { + /* We have enough space for the object, build it */ + + Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject, + ReturnBuffer); + } + } + } + } + } + + if (Info->ReturnObject) + { + /* + * Delete the internal return object. NOTE: Interpreter must be + * locked to avoid race condition. + */ + AcpiExEnterInterpreter (); + + /* Remove one reference on the return object (should delete it) */ + + AcpiUtRemoveReference (Info->ReturnObject); + AcpiExExitInterpreter (); + } + + +Cleanup: + + /* Free the input parameter list (if we created one) */ + + if (Info->Parameters) + { + /* Free the allocated parameter block */ + + AcpiUtDeleteInternalObjectList (Info->Parameters); + } + + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEvaluateObject) + + +/******************************************************************************* + * + * FUNCTION: AcpiNsResolveReferences + * + * PARAMETERS: Info - Evaluation info block + * + * RETURN: Info->ReturnObject is replaced with the dereferenced object + * + * DESCRIPTION: Dereference certain reference objects. Called before an + * internal return object is converted to an external ACPI_OBJECT. + * + * Performs an automatic dereference of Index and RefOf reference objects. + * These reference objects are not supported by the ACPI_OBJECT, so this is a + * last resort effort to return something useful. Also, provides compatibility + * with other ACPI implementations. + * + * NOTE: does not handle references within returned package objects or nested + * references, but this support could be added later if found to be necessary. + * + ******************************************************************************/ + +static void +AcpiNsResolveReferences ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_OPERAND_OBJECT *ObjDesc = NULL; + ACPI_NAMESPACE_NODE *Node; + + + /* We are interested in reference objects only */ + + if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) + { + return; + } + + /* + * Two types of references are supported - those created by Index and + * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted + * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle + * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to + * an ACPI_OBJECT. + */ + switch (Info->ReturnObject->Reference.Class) + { + case ACPI_REFCLASS_INDEX: + + ObjDesc = *(Info->ReturnObject->Reference.Where); + break; + + case ACPI_REFCLASS_REFOF: + + Node = Info->ReturnObject->Reference.Object; + if (Node) + { + ObjDesc = Node->Object; + } + break; + + default: + return; + } + + /* Replace the existing reference object */ + + if (ObjDesc) + { + AcpiUtAddReference (ObjDesc); + AcpiUtRemoveReference (Info->ReturnObject); + Info->ReturnObject = ObjDesc; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiWalkNamespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * StartObject - Handle in namespace where search begins + * MaxDepth - Depth to which search is to reach + * PreOrderVisit - Called during tree pre-order visit + * when an object of "Type" is found + * PostOrderVisit - Called during tree post-order visit + * when an object of "Type" is found + * Context - Passed to user function(s) above + * ReturnValue - Location where return value of + * UserFunction is put if terminated early + * + * RETURNS Return value from the UserFunction if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by StartHandle. + * The callback function is called whenever an object that matches + * the type parameter is found. If the callback function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the callback function(s) can be + * tailored to each task, whether it is a print function, + * a compare function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiWalkNamespace ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE StartObject, + UINT32 MaxDepth, + ACPI_WALK_CALLBACK PreOrderVisit, + ACPI_WALK_CALLBACK PostOrderVisit, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiWalkNamespace); + + + /* Parameter validation */ + + if ((Type > ACPI_TYPE_LOCAL_MAX) || + (!MaxDepth) || + (!PreOrderVisit && !PostOrderVisit)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Need to acquire the namespace reader lock to prevent interference + * with any concurrent table unloads (which causes the deletion of + * namespace objects). We cannot allow the deletion of a namespace node + * while the user function is using it. The exception to this are the + * nodes created and deleted during control method execution -- these + * nodes are marked as temporary nodes and are ignored by the namespace + * walk. Thus, control methods can be executed while holding the + * namespace deletion lock (and the user function can execute control + * methods.) + */ + Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Lock the namespace around the walk. The namespace will be + * unlocked/locked around each call to the user function - since the user + * function must be allowed to make ACPICA calls itself (for example, it + * will typically execute control methods during device enumeration.) + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth, + ACPI_NS_WALK_UNLOCK, PreOrderVisit, + PostOrderVisit, Context, ReturnValue); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + +UnlockAndExit: + (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWalkNamespace) + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetDeviceCallback + * + * PARAMETERS: Callback from AcpiGetDevice + * + * RETURN: Status + * + * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non- + * present devices, or if they specified a HID, it filters based + * on that. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsGetDeviceCallback ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + ACPI_GET_DEVICES_INFO *Info = Context; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + UINT32 Flags; + ACPI_DEVICE_ID *Hid; + ACPI_DEVICE_ID_LIST *Cid; + UINT32 i; + BOOLEAN Found; + int NoMatch; + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Node = AcpiNsValidateHandle (ObjHandle); + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (!Node) + { + return (AE_BAD_PARAMETER); + } + + /* + * First, filter based on the device HID and CID. + * + * 01/2010: For this case where a specific HID is requested, we don't + * want to run _STA until we have an actual HID match. Thus, we will + * not unnecessarily execute _STA on devices for which the caller + * doesn't care about. Previously, _STA was executed unconditionally + * on all devices found here. + * + * A side-effect of this change is that now we will continue to search + * for a matching HID even under device trees where the parent device + * would have returned a _STA that indicates it is not present or + * not functioning (thus aborting the search on that branch). + */ + if (Info->Hid != NULL) + { + Status = AcpiUtExecute_HID (Node, &Hid); + if (Status == AE_NOT_FOUND) + { + return (AE_OK); + } + else if (ACPI_FAILURE (Status)) + { + return (AE_CTRL_DEPTH); + } + + NoMatch = ACPI_STRCMP (Hid->String, Info->Hid); + ACPI_FREE (Hid); + + if (NoMatch) + { + /* + * HID does not match, attempt match within the + * list of Compatible IDs (CIDs) + */ + Status = AcpiUtExecute_CID (Node, &Cid); + if (Status == AE_NOT_FOUND) + { + return (AE_OK); + } + else if (ACPI_FAILURE (Status)) + { + return (AE_CTRL_DEPTH); + } + + /* Walk the CID list */ + + Found = FALSE; + for (i = 0; i < Cid->Count; i++) + { + if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0) + { + /* Found a matching CID */ + + Found = TRUE; + break; + } + } + + ACPI_FREE (Cid); + if (!Found) + { + return (AE_OK); + } + } + } + + /* Run _STA to determine if device is present */ + + Status = AcpiUtExecute_STA (Node, &Flags); + if (ACPI_FAILURE (Status)) + { + return (AE_CTRL_DEPTH); + } + + if (!(Flags & ACPI_STA_DEVICE_PRESENT) && + !(Flags & ACPI_STA_DEVICE_FUNCTIONING)) + { + /* + * Don't examine the children of the device only when the + * device is neither present nor functional. See ACPI spec, + * description of _STA for more information. + */ + return (AE_CTRL_DEPTH); + } + + /* We have a valid device, invoke the user function */ + + Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context, + ReturnValue); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiGetDevices + * + * PARAMETERS: HID - HID to search for. Can be NULL. + * UserFunction - Called when a matching object is found + * Context - Passed to user function + * ReturnValue - Location where return value of + * UserFunction is put if terminated early + * + * RETURNS Return value from the UserFunction if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by StartHandle. + * The UserFunction is called whenever an object of type + * Device is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * This is a wrapper for WalkNamespace, but the callback performs + * additional filtering. Please see AcpiNsGetDeviceCallback. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetDevices ( + char *HID, + ACPI_WALK_CALLBACK UserFunction, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + ACPI_GET_DEVICES_INFO Info; + + + ACPI_FUNCTION_TRACE (AcpiGetDevices); + + + /* Parameter validation */ + + if (!UserFunction) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * We're going to call their callback from OUR callback, so we need + * to know what it is, and their context parameter. + */ + Info.Hid = HID; + Info.Context = Context; + Info.UserFunction = UserFunction; + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, + AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetDevices) + + +/******************************************************************************* + * + * FUNCTION: AcpiAttachData + * + * PARAMETERS: ObjHandle - Namespace node + * Handler - Handler for this attachment + * Data - Pointer to data to be attached + * + * RETURN: Status + * + * DESCRIPTION: Attach arbitrary data and handler to a namespace node. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiAttachData ( + ACPI_HANDLE ObjHandle, + ACPI_OBJECT_HANDLER Handler, + void *Data) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!ObjHandle || + !Handler || + !Data) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert and validate the handle */ + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiNsAttachData (Node, Handler, Data); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiAttachData) + + +/******************************************************************************* + * + * FUNCTION: AcpiDetachData + * + * PARAMETERS: ObjHandle - Namespace node handle + * Handler - Handler used in call to AcpiAttachData + * + * RETURN: Status + * + * DESCRIPTION: Remove data that was previously attached to a node. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDetachData ( + ACPI_HANDLE ObjHandle, + ACPI_OBJECT_HANDLER Handler) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!ObjHandle || + !Handler) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert and validate the handle */ + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiNsDetachData (Node, Handler); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiDetachData) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetData + * + * PARAMETERS: ObjHandle - Namespace node + * Handler - Handler used in call to AttachData + * Data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetData ( + ACPI_HANDLE ObjHandle, + ACPI_OBJECT_HANDLER Handler, + void **Data) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!ObjHandle || + !Handler || + !Data) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert and validate the handle */ + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiNsGetAttachedData (Node, Handler, Data); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetData) + + diff --git a/source/components/namespace/nsxfname.c b/source/components/namespace/nsxfname.c new file mode 100644 index 000000000000..4690d09e90d5 --- /dev/null +++ b/source/components/namespace/nsxfname.c @@ -0,0 +1,702 @@ +/****************************************************************************** + * + * Module Name: nsxfname - Public interfaces to the ACPI subsystem + * ACPI Namespace oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSXFNAME_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acparser.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsxfname") + +/* Local prototypes */ + +static char * +AcpiNsCopyDeviceId ( + ACPI_DEVICE_ID *Dest, + ACPI_DEVICE_ID *Source, + char *StringArea); + + +/****************************************************************************** + * + * FUNCTION: AcpiGetHandle + * + * PARAMETERS: Parent - Object to search under (search scope). + * Pathname - Pointer to an asciiz string containing the + * name + * RetHandle - Where the return handle is returned + * + * RETURN: Status + * + * DESCRIPTION: This routine will search for a caller specified name in the + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a + * namespace handle. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetHandle ( + ACPI_HANDLE Parent, + ACPI_STRING Pathname, + ACPI_HANDLE *RetHandle) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node = NULL; + ACPI_NAMESPACE_NODE *PrefixNode = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + /* Parameter Validation */ + + if (!RetHandle || !Pathname) + { + return (AE_BAD_PARAMETER); + } + + /* Convert a parent handle to a prefix node */ + + if (Parent) + { + PrefixNode = AcpiNsValidateHandle (Parent); + if (!PrefixNode) + { + return (AE_BAD_PARAMETER); + } + } + + /* + * Valid cases are: + * 1) Fully qualified pathname + * 2) Parent + Relative pathname + * + * Error for + */ + if (AcpiNsValidRootPrefix (Pathname[0])) + { + /* Pathname is fully qualified (starts with '\') */ + + /* Special case for root-only, since we can't search for it */ + + if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH)) + { + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode); + return (AE_OK); + } + } + else if (!PrefixNode) + { + /* Relative path with null prefix is disallowed */ + + return (AE_BAD_PARAMETER); + } + + /* Find the Node and convert to a handle */ + + Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node); + if (ACPI_SUCCESS (Status)) + { + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node); + } + + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetHandle) + + +/****************************************************************************** + * + * FUNCTION: AcpiGetName + * + * PARAMETERS: Handle - Handle to be converted to a pathname + * NameType - Full pathname or single segment + * Buffer - Buffer for returned path + * + * RETURN: Pointer to a string containing the fully qualified Name. + * + * DESCRIPTION: This routine returns the fully qualified name associated with + * the Handle parameter. This and the AcpiPathnameToHandle are + * complementary functions. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetName ( + ACPI_HANDLE Handle, + UINT32 NameType, + ACPI_BUFFER *Buffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + /* Parameter validation */ + + if (NameType > ACPI_NAME_TYPE_MAX) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtValidateBuffer (Buffer); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (NameType == ACPI_FULL_PATHNAME) + { + /* Get the full pathname (From the namespace root) */ + + Status = AcpiNsHandleToPathname (Handle, Buffer); + return (Status); + } + + /* + * Wants the single segment ACPI name. + * Validate handle and convert to a namespace Node + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Node = AcpiNsValidateHandle (Handle); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + /* Just copy the ACPI name from the Node and zero terminate it */ + + ACPI_STRNCPY (Buffer->Pointer, AcpiUtGetNodeName (Node), + ACPI_NAME_SIZE); + ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0; + Status = AE_OK; + + +UnlockAndExit: + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetName) + + +/****************************************************************************** + * + * FUNCTION: AcpiNsCopyDeviceId + * + * PARAMETERS: Dest - Pointer to the destination DEVICE_ID + * Source - Pointer to the source DEVICE_ID + * StringArea - Pointer to where to copy the dest string + * + * RETURN: Pointer to the next string area + * + * DESCRIPTION: Copy a single DEVICE_ID, including the string data. + * + ******************************************************************************/ + +static char * +AcpiNsCopyDeviceId ( + ACPI_DEVICE_ID *Dest, + ACPI_DEVICE_ID *Source, + char *StringArea) +{ + /* Create the destination DEVICE_ID */ + + Dest->String = StringArea; + Dest->Length = Source->Length; + + /* Copy actual string and return a pointer to the next string area */ + + ACPI_MEMCPY (StringArea, Source->String, Source->Length); + return (StringArea + Source->Length); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiGetObjectInfo + * + * PARAMETERS: Handle - Object Handle + * ReturnBuffer - Where the info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns information about an object as gleaned from the + * namespace node and possibly by running several standard + * control methods (Such as in the case of a device.) + * + * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, + * _ADR, _SxW, and _SxD methods. + * + * Note: Allocates the return buffer, must be freed by the caller. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetObjectInfo ( + ACPI_HANDLE Handle, + ACPI_DEVICE_INFO **ReturnBuffer) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_DEVICE_INFO *Info; + ACPI_DEVICE_ID_LIST *CidList = NULL; + ACPI_DEVICE_ID *Hid = NULL; + ACPI_DEVICE_ID *Uid = NULL; + char *NextIdString; + ACPI_OBJECT_TYPE Type; + ACPI_NAME Name; + UINT8 ParamCount= 0; + UINT8 Valid = 0; + UINT32 InfoSize; + UINT32 i; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!Handle || !ReturnBuffer) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Node = AcpiNsValidateHandle (Handle); + if (!Node) + { + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + /* Get the namespace node data while the namespace is locked */ + + InfoSize = sizeof (ACPI_DEVICE_INFO); + Type = Node->Type; + Name = Node->Name.Integer; + + if (Node->Type == ACPI_TYPE_METHOD) + { + ParamCount = Node->Object->Method.ParamCount; + } + + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if ((Type == ACPI_TYPE_DEVICE) || + (Type == ACPI_TYPE_PROCESSOR)) + { + /* + * Get extra info for ACPI Device/Processor objects only: + * Run the Device _HID, _UID, and _CID methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info->Valid bitfield is used + * to indicate which methods were found and run successfully. + */ + + /* Execute the Device._HID method */ + + Status = AcpiUtExecute_HID (Node, &Hid); + if (ACPI_SUCCESS (Status)) + { + InfoSize += Hid->Length; + Valid |= ACPI_VALID_HID; + } + + /* Execute the Device._UID method */ + + Status = AcpiUtExecute_UID (Node, &Uid); + if (ACPI_SUCCESS (Status)) + { + InfoSize += Uid->Length; + Valid |= ACPI_VALID_UID; + } + + /* Execute the Device._CID method */ + + Status = AcpiUtExecute_CID (Node, &CidList); + if (ACPI_SUCCESS (Status)) + { + /* Add size of CID strings and CID pointer array */ + + InfoSize += (CidList->ListSize - sizeof (ACPI_DEVICE_ID_LIST)); + Valid |= ACPI_VALID_CID; + } + } + + /* + * Now that we have the variable-length data, we can allocate the + * return buffer + */ + Info = ACPI_ALLOCATE_ZEROED (InfoSize); + if (!Info) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Get the fixed-length data */ + + if ((Type == ACPI_TYPE_DEVICE) || + (Type == ACPI_TYPE_PROCESSOR)) + { + /* + * Get extra info for ACPI Device/Processor objects only: + * Run the _STA, _ADR and, SxW, and _SxD methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info->Valid bitfield is used + * to indicate which methods were found and run successfully. + */ + + /* Execute the Device._STA method */ + + Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus); + if (ACPI_SUCCESS (Status)) + { + Valid |= ACPI_VALID_STA; + } + + /* Execute the Device._ADR method */ + + Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, + &Info->Address); + if (ACPI_SUCCESS (Status)) + { + Valid |= ACPI_VALID_ADR; + } + + /* Execute the Device._SxW methods */ + + Status = AcpiUtExecutePowerMethods (Node, + AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS, + Info->LowestDstates); + if (ACPI_SUCCESS (Status)) + { + Valid |= ACPI_VALID_SXWS; + } + + /* Execute the Device._SxD methods */ + + Status = AcpiUtExecutePowerMethods (Node, + AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS, + Info->HighestDstates); + if (ACPI_SUCCESS (Status)) + { + Valid |= ACPI_VALID_SXDS; + } + } + + /* + * Create a pointer to the string area of the return buffer. + * Point to the end of the base ACPI_DEVICE_INFO structure. + */ + NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids); + if (CidList) + { + /* Point past the CID DEVICE_ID array */ + + NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_DEVICE_ID)); + } + + /* + * Copy the HID, UID, and CIDs to the return buffer. The variable-length + * strings are copied to the reserved area at the end of the buffer. + * + * For HID and CID, check if the ID is a PCI Root Bridge. + */ + if (Hid) + { + NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId, + Hid, NextIdString); + + if (AcpiUtIsPciRootBridge (Hid->String)) + { + Info->Flags |= ACPI_PCI_ROOT_BRIDGE; + } + } + + if (Uid) + { + NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId, + Uid, NextIdString); + } + + if (CidList) + { + Info->CompatibleIdList.Count = CidList->Count; + Info->CompatibleIdList.ListSize = CidList->ListSize; + + /* Copy each CID */ + + for (i = 0; i < CidList->Count; i++) + { + NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i], + &CidList->Ids[i], NextIdString); + + if (AcpiUtIsPciRootBridge (CidList->Ids[i].String)) + { + Info->Flags |= ACPI_PCI_ROOT_BRIDGE; + } + } + } + + /* Copy the fixed-length data */ + + Info->InfoSize = InfoSize; + Info->Type = Type; + Info->Name = Name; + Info->ParamCount = ParamCount; + Info->Valid = Valid; + + *ReturnBuffer = Info; + Status = AE_OK; + + +Cleanup: + if (Hid) + { + ACPI_FREE (Hid); + } + if (Uid) + { + ACPI_FREE (Uid); + } + if (CidList) + { + ACPI_FREE (CidList); + } + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo) + + +/****************************************************************************** + * + * FUNCTION: AcpiInstallMethod + * + * PARAMETERS: Buffer - An ACPI table containing one control method + * + * RETURN: Status + * + * DESCRIPTION: Install a control method into the namespace. If the method + * name already exists in the namespace, it is overwritten. The + * input buffer must contain a valid DSDT or SSDT containing a + * single control method. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallMethod ( + UINT8 *Buffer) +{ + ACPI_TABLE_HEADER *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer); + UINT8 *AmlBuffer; + UINT8 *AmlStart; + char *Path; + ACPI_NAMESPACE_NODE *Node; + ACPI_OPERAND_OBJECT *MethodObj; + ACPI_PARSE_STATE ParserState; + UINT32 AmlLength; + UINT16 Opcode; + UINT8 MethodFlags; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!Buffer) + { + return (AE_BAD_PARAMETER); + } + + /* Table must be a DSDT or SSDT */ + + if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) && + !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT)) + { + return (AE_BAD_HEADER); + } + + /* First AML opcode in the table must be a control method */ + + ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER); + Opcode = AcpiPsPeekOpcode (&ParserState); + if (Opcode != AML_METHOD_OP) + { + return (AE_BAD_PARAMETER); + } + + /* Extract method information from the raw AML */ + + ParserState.Aml += AcpiPsGetOpcodeSize (Opcode); + ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState); + Path = AcpiPsGetNextNamestring (&ParserState); + MethodFlags = *ParserState.Aml++; + AmlStart = ParserState.Aml; + AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart); + + /* + * Allocate resources up-front. We don't want to have to delete a new + * node from the namespace if we cannot allocate memory. + */ + AmlBuffer = ACPI_ALLOCATE (AmlLength); + if (!AmlBuffer) + { + return (AE_NO_MEMORY); + } + + MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); + if (!MethodObj) + { + ACPI_FREE (AmlBuffer); + return (AE_NO_MEMORY); + } + + /* Lock namespace for AcpiNsLookup, we may be creating a new node */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + /* The lookup either returns an existing node or creates a new one */ + + Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1, + ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (Status)) /* NsLookup */ + { + if (Status != AE_ALREADY_EXISTS) + { + goto ErrorExit; + } + + /* Node existed previously, make sure it is a method node */ + + if (Node->Type != ACPI_TYPE_METHOD) + { + Status = AE_TYPE; + goto ErrorExit; + } + } + + /* Copy the method AML to the local buffer */ + + ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength); + + /* Initialize the method object with the new method's information */ + + MethodObj->Method.AmlStart = AmlBuffer; + MethodObj->Method.AmlLength = AmlLength; + + MethodObj->Method.ParamCount = (UINT8) + (MethodFlags & AML_METHOD_ARG_COUNT); + + if (MethodFlags & AML_METHOD_SERIALIZED) + { + MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED; + + MethodObj->Method.SyncLevel = (UINT8) + ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4); + } + + /* + * Now that it is complete, we can attach the new method object to + * the method Node (detaches/deletes any existing object) + */ + Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD); + + /* + * Flag indicates AML buffer is dynamic, must be deleted later. + * Must be set only after attach above. + */ + Node->Flags |= ANOBJ_ALLOCATED_BUFFER; + + /* Remove local reference to the method object */ + + AcpiUtRemoveReference (MethodObj); + return (Status); + + +ErrorExit: + + ACPI_FREE (AmlBuffer); + ACPI_FREE (MethodObj); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallMethod) diff --git a/source/components/namespace/nsxfobj.c b/source/components/namespace/nsxfobj.c new file mode 100644 index 000000000000..02f7777a3965 --- /dev/null +++ b/source/components/namespace/nsxfobj.c @@ -0,0 +1,285 @@ +/******************************************************************************* + * + * Module Name: nsxfobj - Public interfaces to the ACPI subsystem + * ACPI Object oriented interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __NSXFOBJ_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsxfobj") + +/******************************************************************************* + * + * FUNCTION: AcpiGetType + * + * PARAMETERS: Handle - Handle of object whose type is desired + * RetType - Where the type will be placed + * + * RETURN: Status + * + * DESCRIPTION: This routine returns the type associatd with a particular handle + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetType ( + ACPI_HANDLE Handle, + ACPI_OBJECT_TYPE *RetType) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + /* Parameter Validation */ + + if (!RetType) + { + return (AE_BAD_PARAMETER); + } + + /* + * Special case for the predefined Root Node + * (return type ANY) + */ + if (Handle == ACPI_ROOT_OBJECT) + { + *RetType = ACPI_TYPE_ANY; + return (AE_OK); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert and validate the handle */ + + Node = AcpiNsValidateHandle (Handle); + if (!Node) + { + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + *RetType = Node->Type; + + + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetType) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetParent + * + * PARAMETERS: Handle - Handle of object whose parent is desired + * RetHandle - Where the parent handle will be placed + * + * RETURN: Status + * + * DESCRIPTION: Returns a handle to the parent of the object represented by + * Handle. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetParent ( + ACPI_HANDLE Handle, + ACPI_HANDLE *RetHandle) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_NAMESPACE_NODE *ParentNode; + ACPI_STATUS Status; + + + if (!RetHandle) + { + return (AE_BAD_PARAMETER); + } + + /* Special case for the predefined Root Node (no parent) */ + + if (Handle == ACPI_ROOT_OBJECT) + { + return (AE_NULL_ENTRY); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert and validate the handle */ + + Node = AcpiNsValidateHandle (Handle); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Get the parent entry */ + + ParentNode = Node->Parent; + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, ParentNode); + + /* Return exception if parent is null */ + + if (!ParentNode) + { + Status = AE_NULL_ENTRY; + } + + +UnlockAndExit: + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetParent) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetNextObject + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * LastChild - Previous child that was found. + * The NEXT child will be returned + * RetHandle - Where handle to the next object is placed + * + * RETURN: Status + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetNextObject ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE Parent, + ACPI_HANDLE Child, + ACPI_HANDLE *RetHandle) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_NAMESPACE_NODE *ParentNode = NULL; + ACPI_NAMESPACE_NODE *ChildNode = NULL; + + + /* Parameter validation */ + + if (Type > ACPI_TYPE_EXTERNAL_MAX) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* If null handle, use the parent */ + + if (!Child) + { + /* Start search at the beginning of the specified scope */ + + ParentNode = AcpiNsValidateHandle (Parent); + if (!ParentNode) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + } + else + { + /* Non-null handle, ignore the parent */ + /* Convert and validate the handle */ + + ChildNode = AcpiNsValidateHandle (Child); + if (!ChildNode) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + } + + /* Internal function does the real work */ + + Node = AcpiNsGetNextNodeTyped (Type, ParentNode, ChildNode); + if (!Node) + { + Status = AE_NOT_FOUND; + goto UnlockAndExit; + } + + if (RetHandle) + { + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node); + } + + +UnlockAndExit: + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetNextObject) + diff --git a/source/components/parser/psargs.c b/source/components/parser/psargs.c new file mode 100644 index 000000000000..68e4d5d21042 --- /dev/null +++ b/source/components/parser/psargs.c @@ -0,0 +1,940 @@ +/****************************************************************************** + * + * Module Name: psargs - Parse AML opcode arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __PSARGS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psargs") + +/* Local prototypes */ + +static UINT32 +AcpiPsGetNextPackageLength ( + ACPI_PARSE_STATE *ParserState); + +static ACPI_PARSE_OBJECT * +AcpiPsGetNextField ( + ACPI_PARSE_STATE *ParserState); + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextPackageLength + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: Decoded package length. On completion, the AML pointer points + * past the length byte or bytes. + * + * DESCRIPTION: Decode and return a package length field. + * Note: Largest package length is 28 bits, from ACPI specification + * + ******************************************************************************/ + +static UINT32 +AcpiPsGetNextPackageLength ( + ACPI_PARSE_STATE *ParserState) +{ + UINT8 *Aml = ParserState->Aml; + UINT32 PackageLength = 0; + UINT32 ByteCount; + UINT8 ByteZeroMask = 0x3F; /* Default [0:5] */ + + + ACPI_FUNCTION_TRACE (PsGetNextPackageLength); + + + /* + * Byte 0 bits [6:7] contain the number of additional bytes + * used to encode the package length, either 0,1,2, or 3 + */ + ByteCount = (Aml[0] >> 6); + ParserState->Aml += ((ACPI_SIZE) ByteCount + 1); + + /* Get bytes 3, 2, 1 as needed */ + + while (ByteCount) + { + /* + * Final bit positions for the package length bytes: + * Byte3->[20:27] + * Byte2->[12:19] + * Byte1->[04:11] + * Byte0->[00:03] + */ + PackageLength |= (Aml[ByteCount] << ((ByteCount << 3) - 4)); + + ByteZeroMask = 0x0F; /* Use bits [0:3] of byte 0 */ + ByteCount--; + } + + /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ + + PackageLength |= (Aml[0] & ByteZeroMask); + return_UINT32 (PackageLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextPackageEnd + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: Pointer to end-of-package +1 + * + * DESCRIPTION: Get next package length and return a pointer past the end of + * the package. Consumes the package length field + * + ******************************************************************************/ + +UINT8 * +AcpiPsGetNextPackageEnd ( + ACPI_PARSE_STATE *ParserState) +{ + UINT8 *Start = ParserState->Aml; + UINT32 PackageLength; + + + ACPI_FUNCTION_TRACE (PsGetNextPackageEnd); + + + /* Function below updates ParserState->Aml */ + + PackageLength = AcpiPsGetNextPackageLength (ParserState); + + return_PTR (Start + PackageLength); /* end of package */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextNamestring + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: Pointer to the start of the name string (pointer points into + * the AML. + * + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. + * (Name is consumed from the AML.) + * + ******************************************************************************/ + +char * +AcpiPsGetNextNamestring ( + ACPI_PARSE_STATE *ParserState) +{ + UINT8 *Start = ParserState->Aml; + UINT8 *End = ParserState->Aml; + + + ACPI_FUNCTION_TRACE (PsGetNextNamestring); + + + /* Point past any namestring prefix characters (backslash or carat) */ + + while (AcpiPsIsPrefixChar (*End)) + { + End++; + } + + /* Decode the path prefix character */ + + switch (*End) + { + case 0: + + /* NullName */ + + if (End == Start) + { + Start = NULL; + } + End++; + break; + + case AML_DUAL_NAME_PREFIX: + + /* Two name segments */ + + End += 1 + (2 * ACPI_NAME_SIZE); + break; + + case AML_MULTI_NAME_PREFIX_OP: + + /* Multiple name segments, 4 chars each, count in next byte */ + + End += 2 + (*(End + 1) * ACPI_NAME_SIZE); + break; + + default: + + /* Single name segment */ + + End += ACPI_NAME_SIZE; + break; + } + + ParserState->Aml = End; + return_PTR ((char *) Start); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextNamepath + * + * PARAMETERS: ParserState - Current parser state object + * Arg - Where the namepath will be stored + * ArgCount - If the namepath points to a control method + * the method's argument is returned here. + * PossibleMethodCall - Whether the namepath can possibly be the + * start of a method call + * + * RETURN: Status + * + * DESCRIPTION: Get next name (if method call, return # of required args). + * Names are looked up in the internal namespace to determine + * if the name represents a control method. If a method + * is found, the number of arguments to the method is returned. + * This information is critical for parsing to continue correctly. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsGetNextNamepath ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *Arg, + BOOLEAN PossibleMethodCall) +{ + ACPI_STATUS Status; + char *Path; + ACPI_PARSE_OBJECT *NameOp; + ACPI_OPERAND_OBJECT *MethodDesc; + ACPI_NAMESPACE_NODE *Node; + UINT8 *Start = ParserState->Aml; + + + ACPI_FUNCTION_TRACE (PsGetNextNamepath); + + + Path = AcpiPsGetNextNamestring (ParserState); + AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP); + + /* Null path case is allowed, just exit */ + + if (!Path) + { + Arg->Common.Value.Name = Path; + return_ACPI_STATUS (AE_OK); + } + + /* + * Lookup the name in the internal namespace, starting with the current + * scope. We don't want to add anything new to the namespace here, + * however, so we use MODE_EXECUTE. + * Allow searching of the parent tree, but don't open a new scope - + * we just want to lookup the object (must be mode EXECUTE to perform + * the upsearch) + */ + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); + + /* + * If this name is a control method invocation, we must + * setup the method call + */ + if (ACPI_SUCCESS (Status) && + PossibleMethodCall && + (Node->Type == ACPI_TYPE_METHOD)) + { + if (WalkState->Opcode == AML_UNLOAD_OP) + { + /* + * AcpiPsGetNextNamestring has increased the AML pointer, + * so we need to restore the saved AML pointer for method call. + */ + WalkState->ParserState.Aml = Start; + WalkState->ArgCount = 1; + AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); + return_ACPI_STATUS (AE_OK); + } + + /* This name is actually a control method invocation */ + + MethodDesc = AcpiNsGetAttachedObject (Node); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Control Method - %p Desc %p Path=%p\n", Node, MethodDesc, Path)); + + NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + if (!NameOp) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Change Arg into a METHOD CALL and attach name to it */ + + AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); + NameOp->Common.Value.Name = Path; + + /* Point METHODCALL/NAME to the METHOD Node */ + + NameOp->Common.Node = Node; + AcpiPsAppendArg (Arg, NameOp); + + if (!MethodDesc) + { + ACPI_ERROR ((AE_INFO, + "Control Method %p has no attached object", + Node)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Control Method - %p Args %X\n", + Node, MethodDesc->Method.ParamCount)); + + /* Get the number of arguments to expect */ + + WalkState->ArgCount = MethodDesc->Method.ParamCount; + return_ACPI_STATUS (AE_OK); + } + + /* + * Special handling if the name was not found during the lookup - + * some NotFound cases are allowed + */ + if (Status == AE_NOT_FOUND) + { + /* 1) NotFound is ok during load pass 1/2 (allow forward references) */ + + if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) != + ACPI_PARSE_EXECUTE) + { + Status = AE_OK; + } + + /* 2) NotFound during a CondRefOf(x) is ok by definition */ + + else if (WalkState->Op->Common.AmlOpcode == AML_COND_REF_OF_OP) + { + Status = AE_OK; + } + + /* + * 3) NotFound while building a Package is ok at this point, we + * may flag as an error later if slack mode is not enabled. + * (Some ASL code depends on allowing this behavior) + */ + else if ((Arg->Common.Parent) && + ((Arg->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Arg->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) + { + Status = AE_OK; + } + } + + /* Final exception check (may have been changed from code above) */ + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (Path, Status); + + if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) + { + /* Report a control method execution error */ + + Status = AcpiDsMethodError (Status, WalkState); + } + } + + /* Save the namepath */ + + Arg->Common.Value.Name = Path; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextSimpleArg + * + * PARAMETERS: ParserState - Current parser state object + * ArgType - The argument type (AML_*_ARG) + * Arg - Where the argument is returned + * + * RETURN: None + * + * DESCRIPTION: Get the next simple argument (constant, string, or namestring) + * + ******************************************************************************/ + +void +AcpiPsGetNextSimpleArg ( + ACPI_PARSE_STATE *ParserState, + UINT32 ArgType, + ACPI_PARSE_OBJECT *Arg) +{ + UINT32 Length; + UINT16 Opcode; + UINT8 *Aml = ParserState->Aml; + + + ACPI_FUNCTION_TRACE_U32 (PsGetNextSimpleArg, ArgType); + + + switch (ArgType) + { + case ARGP_BYTEDATA: + + /* Get 1 byte from the AML stream */ + + Opcode = AML_BYTE_OP; + Arg->Common.Value.Integer = (UINT64) *Aml; + Length = 1; + break; + + + case ARGP_WORDDATA: + + /* Get 2 bytes from the AML stream */ + + Opcode = AML_WORD_OP; + ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 2; + break; + + + case ARGP_DWORDDATA: + + /* Get 4 bytes from the AML stream */ + + Opcode = AML_DWORD_OP; + ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 4; + break; + + + case ARGP_QWORDDATA: + + /* Get 8 bytes from the AML stream */ + + Opcode = AML_QWORD_OP; + ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 8; + break; + + + case ARGP_CHARLIST: + + /* Get a pointer to the string, point past the string */ + + Opcode = AML_STRING_OP; + Arg->Common.Value.String = ACPI_CAST_PTR (char, Aml); + + /* Find the null terminator */ + + Length = 0; + while (Aml[Length]) + { + Length++; + } + Length++; + break; + + + case ARGP_NAME: + case ARGP_NAMESTRING: + + AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP); + Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState); + return_VOID; + + + default: + + ACPI_ERROR ((AE_INFO, "Invalid ArgType 0x%X", ArgType)); + return_VOID; + } + + AcpiPsInitOp (Arg, Opcode); + ParserState->Aml += Length; + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextField + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: A newly allocated FIELD op + * + * DESCRIPTION: Get next field (NamedField, ReservedField, or AccessField) + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +AcpiPsGetNextField ( + ACPI_PARSE_STATE *ParserState) +{ + UINT32 AmlOffset; + ACPI_PARSE_OBJECT *Field; + ACPI_PARSE_OBJECT *Arg = NULL; + UINT16 Opcode; + UINT32 Name; + UINT8 AccessType; + UINT8 AccessAttribute; + UINT8 AccessLength; + UINT32 PkgLength; + UINT8 *PkgEnd; + UINT32 BufferLength; + + + ACPI_FUNCTION_TRACE (PsGetNextField); + + + AmlOffset = (UINT32) ACPI_PTR_DIFF ( + ParserState->Aml, ParserState->AmlStart); + + /* Determine field type */ + + switch (ACPI_GET8 (ParserState->Aml)) + { + case AML_FIELD_OFFSET_OP: + + Opcode = AML_INT_RESERVEDFIELD_OP; + ParserState->Aml++; + break; + + case AML_FIELD_ACCESS_OP: + + Opcode = AML_INT_ACCESSFIELD_OP; + ParserState->Aml++; + break; + + case AML_FIELD_CONNECTION_OP: + + Opcode = AML_INT_CONNECTION_OP; + ParserState->Aml++; + break; + + case AML_FIELD_EXT_ACCESS_OP: + + Opcode = AML_INT_EXTACCESSFIELD_OP; + ParserState->Aml++; + break; + + default: + + Opcode = AML_INT_NAMEDFIELD_OP; + break; + } + + /* Allocate a new field op */ + + Field = AcpiPsAllocOp (Opcode); + if (!Field) + { + return_PTR (NULL); + } + + Field->Common.AmlOffset = AmlOffset; + + /* Decode the field type */ + + switch (Opcode) + { + case AML_INT_NAMEDFIELD_OP: + + /* Get the 4-character name */ + + ACPI_MOVE_32_TO_32 (&Name, ParserState->Aml); + AcpiPsSetName (Field, Name); + ParserState->Aml += ACPI_NAME_SIZE; + + /* Get the length which is encoded as a package length */ + + Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState); + break; + + + case AML_INT_RESERVEDFIELD_OP: + + /* Get the length which is encoded as a package length */ + + Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState); + break; + + + case AML_INT_ACCESSFIELD_OP: + case AML_INT_EXTACCESSFIELD_OP: + + /* + * Get AccessType and AccessAttrib and merge into the field Op + * AccessType is first operand, AccessAttribute is second. stuff + * these bytes into the node integer value for convenience. + */ + + /* Get the two bytes (Type/Attribute) */ + + AccessType = ACPI_GET8 (ParserState->Aml); + ParserState->Aml++; + AccessAttribute = ACPI_GET8 (ParserState->Aml); + ParserState->Aml++; + + Field->Common.Value.Integer = (UINT8) AccessType; + Field->Common.Value.Integer |= (UINT16) (AccessAttribute << 8); + + /* This opcode has a third byte, AccessLength */ + + if (Opcode == AML_INT_EXTACCESSFIELD_OP) + { + AccessLength = ACPI_GET8 (ParserState->Aml); + ParserState->Aml++; + + Field->Common.Value.Integer |= (UINT32) (AccessLength << 16); + } + break; + + + case AML_INT_CONNECTION_OP: + + /* + * Argument for Connection operator can be either a Buffer + * (resource descriptor), or a NameString. + */ + if (ACPI_GET8 (ParserState->Aml) == AML_BUFFER_OP) + { + ParserState->Aml++; + + PkgEnd = ParserState->Aml; + PkgLength = AcpiPsGetNextPackageLength (ParserState); + PkgEnd += PkgLength; + + if (ParserState->Aml < PkgEnd) + { + /* Non-empty list */ + + Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); + if (!Arg) + { + return_PTR (NULL); + } + + /* Get the actual buffer length argument */ + + Opcode = ACPI_GET8 (ParserState->Aml); + ParserState->Aml++; + + switch (Opcode) + { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + BufferLength = ACPI_GET8 (ParserState->Aml); + ParserState->Aml += 1; + break; + + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + BufferLength = ACPI_GET16 (ParserState->Aml); + ParserState->Aml += 2; + break; + + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + BufferLength = ACPI_GET32 (ParserState->Aml); + ParserState->Aml += 4; + break; + + default: + BufferLength = 0; + break; + } + + /* Fill in bytelist data */ + + Arg->Named.Value.Size = BufferLength; + Arg->Named.Data = ParserState->Aml; + } + + /* Skip to End of byte data */ + + ParserState->Aml = PkgEnd; + } + else + { + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + if (!Arg) + { + return_PTR (NULL); + } + + /* Get the Namestring argument */ + + Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState); + } + + /* Link the buffer/namestring to parent (CONNECTION_OP) */ + + AcpiPsAppendArg (Field, Arg); + break; + + + default: + + /* Opcode was set in previous switch */ + break; + } + + return_PTR (Field); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetNextArg + * + * PARAMETERS: WalkState - Current state + * ParserState - Current parser state object + * ArgType - The argument type (AML_*_ARG) + * ReturnArg - Where the next arg is returned + * + * RETURN: Status, and an op object containing the next argument. + * + * DESCRIPTION: Get next argument (including complex list arguments that require + * pushing the parser stack) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsGetNextArg ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_STATE *ParserState, + UINT32 ArgType, + ACPI_PARSE_OBJECT **ReturnArg) +{ + ACPI_PARSE_OBJECT *Arg = NULL; + ACPI_PARSE_OBJECT *Prev = NULL; + ACPI_PARSE_OBJECT *Field; + UINT32 Subop; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (PsGetNextArg, ParserState); + + + switch (ArgType) + { + case ARGP_BYTEDATA: + case ARGP_WORDDATA: + case ARGP_DWORDDATA: + case ARGP_CHARLIST: + case ARGP_NAME: + case ARGP_NAMESTRING: + + /* Constants, strings, and namestrings are all the same size */ + + Arg = AcpiPsAllocOp (AML_BYTE_OP); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + AcpiPsGetNextSimpleArg (ParserState, ArgType, Arg); + break; + + + case ARGP_PKGLENGTH: + + /* Package length, nothing returned */ + + ParserState->PkgEnd = AcpiPsGetNextPackageEnd (ParserState); + break; + + + case ARGP_FIELDLIST: + + if (ParserState->Aml < ParserState->PkgEnd) + { + /* Non-empty list */ + + while (ParserState->Aml < ParserState->PkgEnd) + { + Field = AcpiPsGetNextField (ParserState); + if (!Field) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + if (Prev) + { + Prev->Common.Next = Field; + } + else + { + Arg = Field; + } + Prev = Field; + } + + /* Skip to End of byte data */ + + ParserState->Aml = ParserState->PkgEnd; + } + break; + + + case ARGP_BYTELIST: + + if (ParserState->Aml < ParserState->PkgEnd) + { + /* Non-empty list */ + + Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Fill in bytelist data */ + + Arg->Common.Value.Size = (UINT32) + ACPI_PTR_DIFF (ParserState->PkgEnd, ParserState->Aml); + Arg->Named.Data = ParserState->Aml; + + /* Skip to End of byte data */ + + ParserState->Aml = ParserState->PkgEnd; + } + break; + + + case ARGP_TARGET: + case ARGP_SUPERNAME: + case ARGP_SIMPLENAME: + + Subop = AcpiPsPeekOpcode (ParserState); + if (Subop == 0 || + AcpiPsIsLeadingChar (Subop) || + AcpiPsIsPrefixChar (Subop)) + { + /* NullName or NameString */ + + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* To support SuperName arg of Unload */ + + if (WalkState->Opcode == AML_UNLOAD_OP) + { + Status = AcpiPsGetNextNamepath (WalkState, ParserState, Arg, 1); + + /* + * If the SuperName arg of Unload is a method call, + * we have restored the AML pointer, just free this Arg + */ + if (Arg->Common.AmlOpcode == AML_INT_METHODCALL_OP) + { + AcpiPsFreeOp (Arg); + Arg = NULL; + } + } + else + { + Status = AcpiPsGetNextNamepath (WalkState, ParserState, Arg, 0); + } + } + else + { + /* Single complex argument, nothing returned */ + + WalkState->ArgCount = 1; + } + break; + + + case ARGP_DATAOBJ: + case ARGP_TERMARG: + + /* Single complex argument, nothing returned */ + + WalkState->ArgCount = 1; + break; + + + case ARGP_DATAOBJLIST: + case ARGP_TERMLIST: + case ARGP_OBJLIST: + + if (ParserState->Aml < ParserState->PkgEnd) + { + /* Non-empty list of variable arguments, nothing returned */ + + WalkState->ArgCount = ACPI_VAR_ARGS; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Invalid ArgType: 0x%X", ArgType)); + Status = AE_AML_OPERAND_TYPE; + break; + } + + *ReturnArg = Arg; + return_ACPI_STATUS (Status); +} diff --git a/source/components/parser/psloop.c b/source/components/parser/psloop.c new file mode 100644 index 000000000000..d578c7e36b38 --- /dev/null +++ b/source/components/parser/psloop.c @@ -0,0 +1,1268 @@ +/****************************************************************************** + * + * Module Name: psloop - Main AML parse loop + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* + * Parse the AML and build an operation tree as most interpreters, (such as + * Perl) do. Parsing is done by hand rather than with a YACC generated parser + * to tightly constrain stack and dynamic memory usage. Parsing is kept + * flexible and the code fairly compact by parsing based on a list of AML + * opcode templates in AmlOpInfo[]. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psloop") + +static UINT32 AcpiGbl_Depth = 0; + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiPsGetAmlOpcode ( + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +AcpiPsBuildNamedOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *UnnamedOp, + ACPI_PARSE_OBJECT **Op); + +static ACPI_STATUS +AcpiPsCreateOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT **NewOp); + +static ACPI_STATUS +AcpiPsGetArguments ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *Op); + +static ACPI_STATUS +AcpiPsCompleteOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **Op, + ACPI_STATUS Status); + +static ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status); + +static void +AcpiPsLinkModuleCode ( + ACPI_PARSE_OBJECT *ParentOp, + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_OWNER_ID OwnerId); + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetAmlOpcode + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Extract the next AML opcode from the input stream. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsGetAmlOpcode ( + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); + + + WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, + WalkState->ParserState.AmlStart); + WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); + + switch (WalkState->OpInfo->Class) + { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + WalkState->Opcode = AML_INT_NAMEPATH_OP; + WalkState->ArgTypes = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Just skip unknown opcodes */ + + ACPI_ERROR ((AE_INFO, + "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring", + WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset)); + + ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128); + + /* Assume one-byte bad opcode */ + + WalkState->ParserState.Aml++; + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + + default: + + /* Found opcode info, this is a normal opcode */ + + WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); + WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; + break; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsBuildNamedOp + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Begin of named Op in AML + * UnnamedOp - Early Op (not a named Op) + * Op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsBuildNamedOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *UnnamedOp, + ACPI_PARSE_OBJECT **Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Arg = NULL; + + + ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); + + + UnnamedOp->Common.Value.Arg = NULL; + UnnamedOp->Common.ArgListLength = 0; + UnnamedOp->Common.AmlOpcode = WalkState->Opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && + (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) + { + Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiPsAppendArg (UnnamedOp, Arg); + INCREMENT_ARG_LIST (WalkState->ArgTypes); + } + + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST (WalkState->ArgTypes); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + WalkState->Op = NULL; + + Status = WalkState->DescendingCallback (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); + return_ACPI_STATUS (Status); + } + + if (!*Op) + { + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + } + + Status = AcpiPsNextParseState (WalkState, *Op, Status); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_PENDING) + { + return_ACPI_STATUS (AE_CTRL_PARSE_PENDING); + } + return_ACPI_STATUS (Status); + } + + AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); + AcpiGbl_Depth++; + + if ((*Op)->Common.AmlOpcode == AML_REGION_OP || + (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP) + { + /* + * Defer final parsing of an OperationRegion body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the TermArg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*Op)->Named.Data = AmlOpStart; + (*Op)->Named.Length = 0; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCreateOp + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Op start in AML + * NewOp - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsCreateOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT **NewOp) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Op; + ACPI_PARSE_OBJECT *NamedOp = NULL; + ACPI_PARSE_OBJECT *ParentScope; + UINT8 ArgumentCount; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); + + + Status = AcpiPsGetAmlOpcode (WalkState); + if (Status == AE_CTRL_PARSE_CONTINUE) + { + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + } + + /* Create Op structure and append to parent's argument list */ + + WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + if (WalkState->OpInfo->Flags & AML_NAMED) + { + Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); + AcpiPsFreeOp (Op); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + *NewOp = NamedOp; + return_ACPI_STATUS (AE_OK); + } + + /* Not a named opcode, just allocate Op and append to parent */ + + if (WalkState->OpInfo->Flags & AML_CREATE) + { + /* + * Backup to beginning of CreateXXXfield declaration + * BodyLength is unknown until we parse the body + */ + Op->Named.Data = AmlOpStart; + Op->Named.Length = 0; + } + + if (WalkState->Opcode == AML_BANK_FIELD_OP) + { + /* + * Backup to beginning of BankField declaration + * BodyLength is unknown until we parse the body + */ + Op->Named.Data = AmlOpStart; + Op->Named.Length = 0; + } + + ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); + AcpiPsAppendArg (ParentScope, Op); + + if (ParentScope) + { + OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); + if (OpInfo->Flags & AML_HAS_TARGET) + { + ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); + if (ParentScope->Common.ArgListLength > ArgumentCount) + { + Op->Common.Flags |= ACPI_PARSEOP_TARGET; + } + } + else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) + { + Op->Common.Flags |= ACPI_PARSEOP_TARGET; + } + } + + if (WalkState->DescendingCallback != NULL) + { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + WalkState->Op = *NewOp = Op; + + Status = WalkState->DescendingCallback (WalkState, &Op); + Status = AcpiPsNextParseState (WalkState, Op, Status); + if (Status == AE_CTRL_PENDING) + { + Status = AE_CTRL_PARSE_PENDING; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetArguments + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Op start in AML + * Op - Current Op + * + * RETURN: Status + * + * DESCRIPTION: Get arguments for passed Op. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsGetArguments ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Arg = NULL; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); + + + switch (Op->Common.AmlOpcode) + { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_QWORD_OP: /* AML_QWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* Fill in constant or string argument directly */ + + AcpiPsGetNextSimpleArg (&(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); + break; + + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + + Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + WalkState->ArgTypes = 0; + break; + + default: + /* + * Op is not a constant or string, append each argument to the Op + */ + while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) + { + WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, + WalkState->ParserState.AmlStart); + + Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Arg) + { + Arg->Common.AmlOffset = WalkState->AmlOffset; + AcpiPsAppendArg (Op, Arg); + } + + INCREMENT_ARG_LIST (WalkState->ArgTypes); + } + + + /* + * Handle executable code at "module-level". This refers to + * executable opcodes that appear outside of any control method. + */ + if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) && + ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0)) + { + /* + * We want to skip If/Else/While constructs during Pass1 because we + * want to actually conditionally execute the code during Pass2. + * + * Except for disassembly, where we always want to walk the + * If/Else/While packages + */ + switch (Op->Common.AmlOpcode) + { + case AML_IF_OP: + case AML_ELSE_OP: + case AML_WHILE_OP: + + /* + * Currently supported module-level opcodes are: + * IF/ELSE/WHILE. These appear to be the most common, + * and easiest to support since they open an AML + * package. + */ + if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) + { + AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart, + (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart), + WalkState->OwnerId); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Pass1: Skipping an If/Else/While body\n")); + + /* Skip body of if/else/while in pass 1 */ + + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; + break; + + default: + /* + * Check for an unsupported executable opcode at module + * level. We must be in PASS1, the parent must be a SCOPE, + * The opcode class must be EXECUTE, and the opcode must + * not be an argument to another opcode. + */ + if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) && + (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) + { + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if ((OpInfo->Class == AML_CLASS_EXECUTE) && + (!Arg)) + { + ACPI_WARNING ((AE_INFO, + "Detected an unsupported executable opcode " + "at module-level: [0x%.4X] at table offset 0x%.4X", + Op->Common.AmlOpcode, + (UINT32) (ACPI_PTR_DIFF (AmlOpStart, + WalkState->ParserState.AmlStart) + + sizeof (ACPI_TABLE_HEADER)))); + } + } + break; + } + } + + /* Special processing for certain opcodes */ + + switch (Op->Common.AmlOpcode) + { + case AML_METHOD_OP: + /* + * Skip parsing of control method because we don't have enough + * info in the first pass to parse it correctly. + * + * Save the length and address of the body + */ + Op->Named.Data = WalkState->ParserState.Aml; + Op->Named.Length = (UINT32) + (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); + + /* Skip body of method */ + + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if ((Op->Common.Parent) && + (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && + (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) + { + /* + * Skip parsing of Buffers and Packages because we don't have + * enough info in the first pass to parse them correctly. + */ + Op->Named.Data = AmlOpStart; + Op->Named.Length = (UINT32) + (WalkState->ParserState.PkgEnd - AmlOpStart); + + /* Skip body */ + + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; + } + break; + + case AML_WHILE_OP: + + if (WalkState->ControlState) + { + WalkState->ControlState->Control.PackageEnd = + WalkState->ParserState.PkgEnd; + } + break; + + default: + + /* No action for all other opcodes */ + break; + } + + break; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsLinkModuleCode + * + * PARAMETERS: ParentOp - Parent parser op + * AmlStart - Pointer to the AML + * AmlLength - Length of executable AML + * OwnerId - OwnerId of module level code + * + * RETURN: None. + * + * DESCRIPTION: Wrap the module-level code with a method object and link the + * object to the global list. Note, the mutex field of the method + * object is used to link multiple module-level code objects. + * + ******************************************************************************/ + +static void +AcpiPsLinkModuleCode ( + ACPI_PARSE_OBJECT *ParentOp, + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_OWNER_ID OwnerId) +{ + ACPI_OPERAND_OBJECT *Prev; + ACPI_OPERAND_OBJECT *Next; + ACPI_OPERAND_OBJECT *MethodObj; + ACPI_NAMESPACE_NODE *ParentNode; + + + /* Get the tail of the list */ + + Prev = Next = AcpiGbl_ModuleCodeList; + while (Next) + { + Prev = Next; + Next = Next->Method.Mutex; + } + + /* + * Insert the module level code into the list. Merge it if it is + * adjacent to the previous element. + */ + if (!Prev || + ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart)) + { + /* Create, initialize, and link a new temporary method object */ + + MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); + if (!MethodObj) + { + return; + } + + if (ParentOp->Common.Node) + { + ParentNode = ParentOp->Common.Node; + } + else + { + ParentNode = AcpiGbl_RootNode; + } + + MethodObj->Method.AmlStart = AmlStart; + MethodObj->Method.AmlLength = AmlLength; + MethodObj->Method.OwnerId = OwnerId; + MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL; + + /* + * Save the parent node in NextObject. This is cheating, but we + * don't want to expand the method object. + */ + MethodObj->Method.NextObject = + ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode); + + if (!Prev) + { + AcpiGbl_ModuleCodeList = MethodObj; + } + else + { + Prev->Method.Mutex = MethodObj; + } + } + else + { + Prev->Method.AmlLength += AmlLength; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCompleteOp + * + * PARAMETERS: WalkState - Current state + * Op - Returned Op + * Status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsCompleteOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **Op, + ACPI_STATUS Status) +{ + ACPI_STATUS Status2; + + + ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); + + + /* + * Finished one argument of the containing scope + */ + WalkState->ParserState.Scope->ParseScope.ArgCount--; + + /* Close this Op (will result in parse subtree deletion) */ + + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + + *Op = NULL; + + switch (Status) + { + case AE_OK: + break; + + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method */ + + WalkState->PrevOp = NULL; + WalkState->PrevArgTypes = WalkState->ArgTypes; + return_ACPI_STATUS (Status); + + + case AE_CTRL_END: + + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + + if (*Op) + { + WalkState->Op = *Op; + WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); + WalkState->Opcode = (*Op)->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, *Op, Status); + + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + } + + Status = AE_OK; + break; + + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) + { + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + } + + /* Close this iteration of the While loop */ + + WalkState->Op = *Op; + WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); + WalkState->Opcode = (*Op)->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, *Op, Status); + + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + + Status = AE_OK; + break; + + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do + { + if (*Op) + { + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + + AcpiUtDeleteGenericState ( + AcpiUtPopGenericState (&WalkState->ControlState)); + } + + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + + } while (*Op); + + return_ACPI_STATUS (AE_OK); + + + default: /* All other non-AE_OK status */ + + do + { + if (*Op) + { + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + } + + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + + } while (*Op); + + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*Op == NULL) + { + AcpiPsPopScope (ParserState, Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + } +#endif + WalkState->PrevOp = NULL; + WalkState->PrevArgTypes = WalkState->ArgTypes; + return_ACPI_STATUS (Status); + } + + /* This scope complete? */ + + if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) + { + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); + } + else + { + *Op = NULL; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCompleteFinalOp + * + * PARAMETERS: WalkState - Current state + * Op - Current Op + * Status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status) +{ + ACPI_STATUS Status2; + + + ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); + + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); + do + { + if (Op) + { + if (WalkState->AscendingCallback != NULL) + { + WalkState->Op = Op; + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + WalkState->Opcode = Op->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, Op, Status); + if (Status == AE_CTRL_PENDING) + { + Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (Status == AE_CTRL_TERMINATE) + { + Status = AE_OK; + + /* Clean up */ + do + { + if (Op) + { + Status2 = AcpiPsCompleteThisOp (WalkState, Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + } + + AcpiPsPopScope (&(WalkState->ParserState), &Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + + } while (Op); + + return_ACPI_STATUS (Status); + } + + else if (ACPI_FAILURE (Status)) + { + /* First error is most important */ + + (void) AcpiPsCompleteThisOp (WalkState, Op); + return_ACPI_STATUS (Status); + } + } + + Status2 = AcpiPsCompleteThisOp (WalkState, Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + } + + AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, + &WalkState->ArgCount); + + } while (Op); + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsParseLoop + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsParseLoop ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Op = NULL; /* current op */ + ACPI_PARSE_STATE *ParserState; + UINT8 *AmlOpStart = NULL; + + + ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); + + + if (WalkState->DescendingCallback == NULL) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + ParserState = &WalkState->ParserState; + WalkState->ArgTypes = 0; + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) + { + /* We are restarting a preempted control method */ + + if (AcpiPsHasCompletedScope (ParserState)) + { + /* + * We must check if a predicate to an IF or WHILE statement + * was just completed + */ + if ((ParserState->Scope->ParseScope.Op) && + ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || + (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && + (WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_PREDICATE_EXECUTING)) + { + /* + * A predicate was just completed, get the value of the + * predicate and branch based on that value + */ + WalkState->Op = NULL; + Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); + if (ACPI_FAILURE (Status) && + ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) + { + if (Status == AE_AML_NO_RETURN_VALUE) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Invoked method did not return a value")); + } + + ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed")); + return_ACPI_STATUS (Status); + } + + Status = AcpiPsNextParseState (WalkState, Op, Status); + } + + AcpiPsPopScope (ParserState, &Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); + } + else if (WalkState->PrevOp) + { + /* We were in the middle of an op */ + + Op = WalkState->PrevOp; + WalkState->ArgTypes = WalkState->PrevArgTypes; + } + } +#endif + + /* Iterative parsing loop, while there is more AML to process: */ + + while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) + { + AmlOpStart = ParserState->Aml; + if (!Op) + { + Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_PARSE_CONTINUE) + { + continue; + } + + if (Status == AE_CTRL_PARSE_PENDING) + { + Status = AE_OK; + } + + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + + Op->Common.AmlOffset = WalkState->AmlOffset; + + if (WalkState->OpInfo) + { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", + (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, + Op, ParserState->Aml, Op->Common.AmlOffset)); + } + } + + + /* + * Start ArgCount at zero because we don't know if there are + * any args yet + */ + WalkState->ArgCount = 0; + + /* Are there any arguments that must be processed? */ + + if (WalkState->ArgTypes) + { + /* Get arguments */ + + Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op); + if (ACPI_FAILURE (Status)) + { + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + } + + /* Check for arguments that need to be processed */ + + if (WalkState->ArgCount) + { + /* + * There are arguments (complex ones), push Op and + * prepare for argument + */ + Status = AcpiPsPushScope (ParserState, Op, + WalkState->ArgTypes, WalkState->ArgCount); + if (ACPI_FAILURE (Status)) + { + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + + Op = NULL; + continue; + } + + /* + * All arguments have been processed -- Op is complete, + * prepare for next + */ + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (WalkState->OpInfo->Flags & AML_NAMED) + { + if (AcpiGbl_Depth) + { + AcpiGbl_Depth--; + } + + if (Op->Common.AmlOpcode == AML_REGION_OP || + Op->Common.AmlOpcode == AML_DATA_REGION_OP) + { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an OpRegion declaration, we now + * know the length. + */ + Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + } + } + + if (WalkState->OpInfo->Flags & AML_CREATE) + { + /* + * Backup to beginning of CreateXXXfield declaration (1 for + * Opcode) + * + * BodyLength is unknown until we parse the body + */ + Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + } + + if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) + { + /* + * Backup to beginning of BankField declaration + * + * BodyLength is unknown until we parse the body + */ + Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + } + + /* This op complete, notify the dispatcher */ + + if (WalkState->AscendingCallback != NULL) + { + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, Op, Status); + if (Status == AE_CTRL_PENDING) + { + Status = AE_OK; + } + } + + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + } /* while ParserState->Aml */ + + Status = AcpiPsCompleteFinalOp (WalkState, Op, Status); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/parser/psopcode.c b/source/components/parser/psopcode.c new file mode 100644 index 000000000000..ef2257e86ff7 --- /dev/null +++ b/source/components/parser/psopcode.c @@ -0,0 +1,522 @@ +/****************************************************************************** + * + * Module Name: psopcode - Parser/Interpreter opcode information table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acopcode.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psopcode") + + +static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6}; + + +/******************************************************************************* + * + * NAME: AcpiGbl_AmlOpInfo + * + * DESCRIPTION: Opcode table. Each entry contains + * The name is a simple ascii string, the operand specifier is an + * ascii string with one letter per operand. The letter specifies + * the operand type. + * + ******************************************************************************/ + +/* + * Summary of opcode types/flags + * + + Opcodes that have associated namespace objects (AML_NSOBJECT flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_INT_NAMEDFIELD_OP + AML_INT_METHODCALL_OP + AML_INT_NAMEPATH_OP + + Opcodes that are "namespace" opcodes (AML_NSOPCODE flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_INT_NAMEDFIELD_OP + + Opcodes that have an associated namespace node (AML_NSNODE flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_INT_NAMEDFIELD_OP + AML_INT_METHODCALL_OP + AML_INT_NAMEPATH_OP + + Opcodes that define named ACPI objects (AML_NAMED flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_INT_NAMEDFIELD_OP + + Opcodes that contain executable AML as part of the definition that + must be deferred until needed + + AML_METHOD_OP + AML_VAR_PACKAGE_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_REGION_OP + AML_BUFFER_OP + + Field opcodes + + AML_CREATE_FIELD_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + + Field "Create" opcodes + + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + + ******************************************************************************/ + + +/* + * Master Opcode information table. A summary of everything we know about each + * opcode, all in one place. + */ +const ACPI_OPCODE_INFO AcpiGbl_AmlOpInfo[AML_NUM_OPCODES] = +{ +/*! [Begin] no source code translation */ +/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ + +/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), +/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), +/* 02 */ ACPI_OP ("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 03 */ ACPI_OP ("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 08 */ ACPI_OP ("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), +/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), +/* 0B */ ACPI_OP ("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER), +/* 0C */ ACPI_OP ("Local0", ARGP_LOCAL0, ARGI_LOCAL0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 0D */ ACPI_OP ("Local1", ARGP_LOCAL1, ARGI_LOCAL1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 0E */ ACPI_OP ("Local2", ARGP_LOCAL2, ARGI_LOCAL2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 0F */ ACPI_OP ("Local3", ARGP_LOCAL3, ARGI_LOCAL3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 10 */ ACPI_OP ("Local4", ARGP_LOCAL4, ARGI_LOCAL4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 11 */ ACPI_OP ("Local5", ARGP_LOCAL5, ARGI_LOCAL5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 12 */ ACPI_OP ("Local6", ARGP_LOCAL6, ARGI_LOCAL6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 13 */ ACPI_OP ("Local7", ARGP_LOCAL7, ARGI_LOCAL7, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), +/* 14 */ ACPI_OP ("Arg0", ARGP_ARG0, ARGI_ARG0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 15 */ ACPI_OP ("Arg1", ARGP_ARG1, ARGI_ARG1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 16 */ ACPI_OP ("Arg2", ARGP_ARG2, ARGI_ARG2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 17 */ ACPI_OP ("Arg3", ARGP_ARG3, ARGI_ARG3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 18 */ ACPI_OP ("Arg4", ARGP_ARG4, ARGI_ARG4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 19 */ ACPI_OP ("Arg5", ARGP_ARG5, ARGI_ARG5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 1A */ ACPI_OP ("Arg6", ARGP_ARG6, ARGI_ARG6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), +/* 1B */ ACPI_OP ("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 1C */ ACPI_OP ("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), +/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), +/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), +/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), +/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), +/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), +/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), +/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), +/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), +/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), +/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), +/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), +/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), +/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), +/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3E */ ACPI_OP ("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 3F */ ACPI_OP ("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 40 */ ACPI_OP ("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 41 */ ACPI_OP ("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 42 */ ACPI_OP ("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 43 */ ACPI_OP ("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 44 */ ACPI_OP ("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + +/* Prefixed opcodes (Two-byte opcodes with a prefix op) */ + +/* 46 */ ACPI_OP ("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 47 */ ACPI_OP ("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ), +/* 48 */ ACPI_OP ("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 49 */ ACPI_OP ("CreateField", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_FIELD | AML_CREATE), +/* 4A */ ACPI_OP ("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, AML_FLAGS_EXEC_1A_1T_0R), +/* 4B */ ACPI_OP ("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 4C */ ACPI_OP ("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 4D */ ACPI_OP ("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), +/* 4E */ ACPI_OP ("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 4F */ ACPI_OP ("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), +/* 50 */ ACPI_OP ("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 51 */ ACPI_OP ("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 54 */ ACPI_OP ("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), +/* 55 */ ACPI_OP ("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), +/* 56 */ ACPI_OP ("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), +/* 57 */ ACPI_OP ("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R), +/* 58 */ ACPI_OP ("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER), +/* 59 */ ACPI_OP ("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), +/* 5A */ ACPI_OP ("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 5B */ ACPI_OP ("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 5C */ ACPI_OP ("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 5D */ ACPI_OP ("ThermalZone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 5E */ ACPI_OP ("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), +/* 5F */ ACPI_OP ("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | AML_DEFER), + +/* Internal opcodes that map to invalid AML opcodes */ + +/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 63 */ ACPI_OP ("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE ), +/* 64 */ ACPI_OP ("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, AML_TYPE_METHOD_CALL, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), +/* 65 */ ACPI_OP ("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), +/* 66 */ ACPI_OP ("-ReservedField-", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 67 */ ACPI_OP ("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ), +/* 68 */ ACPI_OP ("-AccessField-", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 69 */ ACPI_OP ("-StaticString", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 6A */ ACPI_OP ("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, AML_HAS_ARGS | AML_HAS_RETVAL), +/* 6B */ ACPI_OP ("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 6C */ ACPI_OP ("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 6D */ ACPI_OP ("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), + +/* ACPI 2.0 opcodes */ + +/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 6F */ ACPI_OP ("Package", /* Var */ ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), +/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), +/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 78 */ ACPI_OP ("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), +/* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), +/* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER), +/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + +/* ACPI 3.0 opcodes */ + +/* 7E */ ACPI_OP ("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_FLAGS_EXEC_0A_0T_1R), + +/* ACPI 5.0 opcodes */ + +/* 7F */ ACPI_OP ("-ConnectField-", ARGP_CONNECTFIELD_OP, ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 80 */ ACPI_OP ("-ExtAccessField-", ARGP_CONNECTFIELD_OP, ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0) + +/*! [End] no source code translation !*/ +}; + +/* + * This table is directly indexed by the opcodes, and returns an + * index into the table above + */ +static const UINT8 AcpiGbl_ShortOpIndex[256] = +{ +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, +/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (AcpiGbl_AmlOpInfo) + */ +static const UINT8 AcpiGbl_LongOpIndex[NUM_EXTENDED_OPCODE] = +{ +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetOpcodeInfo + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +const ACPI_OPCODE_INFO * +AcpiPsGetOpcodeInfo ( + UINT16 Opcode) +{ + ACPI_FUNCTION_NAME (PsGetOpcodeInfo); + + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + if (!(Opcode & 0xFF00)) + { + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]); + } + + if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE)) + { + /* Valid extended (16-bit) opcode */ + + return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]); + } + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Unknown AML opcode [%4.4X]\n", Opcode)); + + return (&AcpiGbl_AmlOpInfo [_UNK]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetOpcodeName + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char * +AcpiPsGetOpcodeName ( + UINT16 Opcode) +{ +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) + + const ACPI_OPCODE_INFO *Op; + + + Op = AcpiPsGetOpcodeInfo (Opcode); + + /* Always guaranteed to return a valid pointer */ + + return (Op->Name); + +#else + return ("OpcodeName unavailable"); + +#endif +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetArgumentCount + * + * PARAMETERS: OpType - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +UINT8 +AcpiPsGetArgumentCount ( + UINT32 OpType) +{ + + if (OpType <= AML_TYPE_EXEC_6A_0T_1R) + { + return (AcpiGbl_ArgumentCount[OpType]); + } + + return (0); +} diff --git a/source/components/parser/psparse.c b/source/components/parser/psparse.c new file mode 100644 index 000000000000..bcf46adfe566 --- /dev/null +++ b/source/components/parser/psparse.c @@ -0,0 +1,711 @@ +/****************************************************************************** + * + * Module Name: psparse - Parser top level AML parse routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in AmlOpInfo[] + */ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "amlcode.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psparse") + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetOpcodeSize + * + * PARAMETERS: Opcode - An AML opcode + * + * RETURN: Size of the opcode, in bytes (1 or 2) + * + * DESCRIPTION: Get the size of the current opcode. + * + ******************************************************************************/ + +UINT32 +AcpiPsGetOpcodeSize ( + UINT32 Opcode) +{ + + /* Extended (2-byte) opcode if > 255 */ + + if (Opcode > 0x00FF) + { + return (2); + } + + /* Otherwise, just a single byte opcode */ + + return (1); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsPeekOpcode + * + * PARAMETERS: ParserState - A parser state object + * + * RETURN: Next AML opcode + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +UINT16 +AcpiPsPeekOpcode ( + ACPI_PARSE_STATE *ParserState) +{ + UINT8 *Aml; + UINT16 Opcode; + + + Aml = ParserState->Aml; + Opcode = (UINT16) ACPI_GET8 (Aml); + + if (Opcode == AML_EXTENDED_OP_PREFIX) + { + /* Extended opcode, get the second opcode byte */ + + Aml++; + Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml)); + } + + return (Opcode); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCompleteThisOp + * + * PARAMETERS: WalkState - Current State + * Op - Op to complete + * + * RETURN: Status + * + * DESCRIPTION: Perform any cleanup at the completion of an Op. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsCompleteThisOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Prev; + ACPI_PARSE_OBJECT *Next; + const ACPI_OPCODE_INFO *ParentInfo; + ACPI_PARSE_OBJECT *ReplacementOp = NULL; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op); + + + /* Check for null Op, can happen if AML code is corrupt */ + + if (!Op) + { + return_ACPI_STATUS (AE_OK); /* OK for now */ + } + + /* Delete this op and the subtree below it if asked to */ + + if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || + (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT)) + { + return_ACPI_STATUS (AE_OK); + } + + /* Make sure that we only delete this subtree */ + + if (Op->Common.Parent) + { + Prev = Op->Common.Parent->Common.Value.Arg; + if (!Prev) + { + /* Nothing more to do */ + + goto Cleanup; + } + + /* + * Check if we need to replace the operator and its subtree + * with a return value op (placeholder op) + */ + ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); + + switch (ParentInfo->Class) + { + case AML_CLASS_CONTROL: + break; + + case AML_CLASS_CREATE: + + /* + * These opcodes contain TermArg operands. The current + * op must be replaced by a placeholder return op + */ + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + if (!ReplacementOp) + { + Status = AE_NO_MEMORY; + } + break; + + case AML_CLASS_NAMED_OBJECT: + + /* + * These opcodes contain TermArg operands. The current + * op must be replaced by a placeholder return op + */ + if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) + { + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + if (!ReplacementOp) + { + Status = AE_NO_MEMORY; + } + } + else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && + (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) + { + if ((Op->Common.AmlOpcode == AML_BUFFER_OP) || + (Op->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) + { + ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode); + if (!ReplacementOp) + { + Status = AE_NO_MEMORY; + } + else + { + ReplacementOp->Named.Data = Op->Named.Data; + ReplacementOp->Named.Length = Op->Named.Length; + } + } + } + break; + + default: + + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + if (!ReplacementOp) + { + Status = AE_NO_MEMORY; + } + } + + /* We must unlink this op from the parent tree */ + + if (Prev == Op) + { + /* This op is the first in the list */ + + if (ReplacementOp) + { + ReplacementOp->Common.Parent = Op->Common.Parent; + ReplacementOp->Common.Value.Arg = NULL; + ReplacementOp->Common.Node = Op->Common.Node; + Op->Common.Parent->Common.Value.Arg = ReplacementOp; + ReplacementOp->Common.Next = Op->Common.Next; + } + else + { + Op->Common.Parent->Common.Value.Arg = Op->Common.Next; + } + } + + /* Search the parent list */ + + else while (Prev) + { + /* Traverse all siblings in the parent's argument list */ + + Next = Prev->Common.Next; + if (Next == Op) + { + if (ReplacementOp) + { + ReplacementOp->Common.Parent = Op->Common.Parent; + ReplacementOp->Common.Value.Arg = NULL; + ReplacementOp->Common.Node = Op->Common.Node; + Prev->Common.Next = ReplacementOp; + ReplacementOp->Common.Next = Op->Common.Next; + Next = NULL; + } + else + { + Prev->Common.Next = Op->Common.Next; + Next = NULL; + } + } + Prev = Next; + } + } + + +Cleanup: + + /* Now we can actually delete the subtree rooted at Op */ + + AcpiPsDeleteParseTree (Op); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsNextParseState + * + * PARAMETERS: WalkState - Current state + * Op - Current parse op + * CallbackStatus - Status from previous operation + * + * RETURN: Status + * + * DESCRIPTION: Update the parser state based upon the return exception from + * the parser callback. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsNextParseState ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS CallbackStatus) +{ + ACPI_PARSE_STATE *ParserState = &WalkState->ParserState; + ACPI_STATUS Status = AE_CTRL_PENDING; + + + ACPI_FUNCTION_TRACE_PTR (PsNextParseState, Op); + + + switch (CallbackStatus) + { + case AE_CTRL_TERMINATE: + /* + * A control method was terminated via a RETURN statement. + * The walk of this method is complete. + */ + ParserState->Aml = ParserState->AmlEnd; + Status = AE_CTRL_TERMINATE; + break; + + + case AE_CTRL_BREAK: + + ParserState->Aml = WalkState->AmlLastWhile; + WalkState->ControlState->Common.Value = FALSE; + Status = AE_CTRL_BREAK; + break; + + + case AE_CTRL_CONTINUE: + + ParserState->Aml = WalkState->AmlLastWhile; + Status = AE_CTRL_CONTINUE; + break; + + + case AE_CTRL_PENDING: + + ParserState->Aml = WalkState->AmlLastWhile; + break; + +#if 0 + case AE_CTRL_SKIP: + + ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; + Status = AE_OK; + break; +#endif + + case AE_CTRL_TRUE: + /* + * Predicate of an IF was true, and we are at the matching ELSE. + * Just close out this package + */ + ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); + Status = AE_CTRL_PENDING; + break; + + + case AE_CTRL_FALSE: + /* + * Either an IF/WHILE Predicate was false or we encountered a BREAK + * opcode. In both cases, we do not execute the rest of the + * package; We simply close out the parent (finishing the walk of + * this branch of the tree) and continue execution at the parent + * level. + */ + ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; + + /* In the case of a BREAK, just force a predicate (if any) to FALSE */ + + WalkState->ControlState->Common.Value = FALSE; + Status = AE_CTRL_END; + break; + + + case AE_CTRL_TRANSFER: + + /* A method call (invocation) -- transfer control */ + + Status = AE_CTRL_TRANSFER; + WalkState->PrevOp = Op; + WalkState->MethodCallOp = Op; + WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node; + + /* Will return value (if any) be used by the caller? */ + + WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState); + break; + + + default: + + Status = CallbackStatus; + if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL) + { + Status = AE_OK; + } + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsParseAml + * + * PARAMETERS: WalkState - Current state + * + * + * RETURN: Status + * + * DESCRIPTION: Parse raw AML and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsParseAml ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_THREAD_STATE *Thread; + ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList; + ACPI_WALK_STATE *PreviousWalkState; + + + ACPI_FUNCTION_TRACE (PsParseAml); + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Entered with WalkState=%p Aml=%p size=%X\n", + WalkState, WalkState->ParserState.Aml, + WalkState->ParserState.AmlSize)); + + if (!WalkState->ParserState.Aml) + { + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Create and initialize a new thread state */ + + Thread = AcpiUtCreateThreadState (); + if (!Thread) + { + if (WalkState->MethodDesc) + { + /* Executing a control method - additional cleanup */ + + AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); + } + + AcpiDsDeleteWalkState (WalkState); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + WalkState->Thread = Thread; + + /* + * If executing a method, the starting SyncLevel is this method's + * SyncLevel + */ + if (WalkState->MethodDesc) + { + WalkState->Thread->CurrentSyncLevel = WalkState->MethodDesc->Method.SyncLevel; + } + + AcpiDsPushWalkState (WalkState, Thread); + + /* + * This global allows the AML debugger to get a handle to the currently + * executing control method. + */ + AcpiGbl_CurrentWalkList = Thread; + + /* + * Execute the walk loop as long as there is a valid Walk State. This + * handles nested control method invocations without recursion. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState)); + + Status = AE_OK; + while (WalkState) + { + if (ACPI_SUCCESS (Status)) + { + /* + * The ParseLoop executes AML until the method terminates + * or calls another method. + */ + Status = AcpiPsParseLoop (WalkState); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Completed one call to walk loop, %s State=%p\n", + AcpiFormatException (Status), WalkState)); + + if (Status == AE_CTRL_TRANSFER) + { + /* + * A method call was detected. + * Transfer control to the called control method + */ + Status = AcpiDsCallControlMethod (Thread, WalkState, NULL); + if (ACPI_FAILURE (Status)) + { + Status = AcpiDsMethodError (Status, WalkState); + } + + /* + * If the transfer to the new method method call worked, a new walk + * state was created -- get it + */ + WalkState = AcpiDsGetCurrentWalkState (Thread); + continue; + } + else if (Status == AE_CTRL_TERMINATE) + { + Status = AE_OK; + } + else if ((Status != AE_OK) && (WalkState->MethodDesc)) + { + /* Either the method parse or actual execution failed */ + + ACPI_ERROR_METHOD ("Method parse/execution failed", + WalkState->MethodNode, NULL, Status); + + /* Check for possible multi-thread reentrancy problem */ + + if ((Status == AE_ALREADY_EXISTS) && + (!(WalkState->MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED))) + { + /* + * Method is not serialized and tried to create an object + * twice. The probable cause is that the method cannot + * handle reentrancy. Mark as "pending serialized" now, and + * then mark "serialized" when the last thread exits. + */ + WalkState->MethodDesc->Method.InfoFlags |= + ACPI_METHOD_SERIALIZED_PENDING; + } + } + + /* We are done with this walk, move on to the parent if any */ + + WalkState = AcpiDsPopWalkState (Thread); + + /* Reset the current scope to the beginning of scope stack */ + + AcpiDsScopeStackClear (WalkState); + + /* + * If we just returned from the execution of a control method or if we + * encountered an error during the method parse phase, there's lots of + * cleanup to do + */ + if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || + (ACPI_FAILURE (Status))) + { + AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); + } + + /* Delete this walk state and all linked control states */ + + AcpiPsCleanupScope (&WalkState->ParserState); + PreviousWalkState = WalkState; + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "ReturnValue=%p, ImplicitValue=%p State=%p\n", + WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState)); + + /* Check if we have restarted a preempted walk */ + + WalkState = AcpiDsGetCurrentWalkState (Thread); + if (WalkState) + { + if (ACPI_SUCCESS (Status)) + { + /* + * There is another walk state, restart it. + * If the method return value is not used by the parent, + * The object is deleted + */ + if (!PreviousWalkState->ReturnDesc) + { + /* + * In slack mode execution, if there is no return value + * we should implicitly return zero (0) as a default value. + */ + if (AcpiGbl_EnableInterpreterSlack && + !PreviousWalkState->ImplicitReturnObj) + { + PreviousWalkState->ImplicitReturnObj = + AcpiUtCreateIntegerObject ((UINT64) 0); + if (!PreviousWalkState->ImplicitReturnObj) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + /* Restart the calling control method */ + + Status = AcpiDsRestartControlMethod (WalkState, + PreviousWalkState->ImplicitReturnObj); + } + else + { + /* + * We have a valid return value, delete any implicit + * return value. + */ + AcpiDsClearImplicitReturn (PreviousWalkState); + + Status = AcpiDsRestartControlMethod (WalkState, + PreviousWalkState->ReturnDesc); + } + if (ACPI_SUCCESS (Status)) + { + WalkState->WalkType |= ACPI_WALK_METHOD_RESTART; + } + } + else + { + /* On error, delete any return object or implicit return */ + + AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); + AcpiDsClearImplicitReturn (PreviousWalkState); + } + } + + /* + * Just completed a 1st-level method, save the final internal return + * value (if any) + */ + else if (PreviousWalkState->CallerReturnDesc) + { + if (PreviousWalkState->ImplicitReturnObj) + { + *(PreviousWalkState->CallerReturnDesc) = + PreviousWalkState->ImplicitReturnObj; + } + else + { + /* NULL if no return value */ + + *(PreviousWalkState->CallerReturnDesc) = + PreviousWalkState->ReturnDesc; + } + } + else + { + if (PreviousWalkState->ReturnDesc) + { + /* Caller doesn't want it, must delete it */ + + AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); + } + if (PreviousWalkState->ImplicitReturnObj) + { + /* Caller doesn't want it, must delete it */ + + AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj); + } + } + + AcpiDsDeleteWalkState (PreviousWalkState); + } + + /* Normal exit */ + + AcpiExReleaseAllMutexes (Thread); + AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread)); + AcpiGbl_CurrentWalkList = PrevWalkList; + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/parser/psscope.c b/source/components/parser/psscope.c new file mode 100644 index 000000000000..1df5a33af352 --- /dev/null +++ b/source/components/parser/psscope.c @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * Module Name: psscope - Parser scope stack management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psscope") + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetParentScope + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: Pointer to an Op object + * + * DESCRIPTION: Get parent of current op being parsed + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +AcpiPsGetParentScope ( + ACPI_PARSE_STATE *ParserState) +{ + + return (ParserState->Scope->ParseScope.Op); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsHasCompletedScope + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: Boolean, TRUE = scope completed. + * + * DESCRIPTION: Is parsing of current argument complete? Determined by + * 1) AML pointer is at or beyond the end of the scope + * 2) The scope argument count has reached zero. + * + ******************************************************************************/ + +BOOLEAN +AcpiPsHasCompletedScope ( + ACPI_PARSE_STATE *ParserState) +{ + + return ((BOOLEAN) + ((ParserState->Aml >= ParserState->Scope->ParseScope.ArgEnd || + !ParserState->Scope->ParseScope.ArgCount))); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsInitScope + * + * PARAMETERS: ParserState - Current parser state object + * Root - the Root Node of this new scope + * + * RETURN: Status + * + * DESCRIPTION: Allocate and init a new scope object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsInitScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *RootOp) +{ + ACPI_GENERIC_STATE *Scope; + + + ACPI_FUNCTION_TRACE_PTR (PsInitScope, RootOp); + + + Scope = AcpiUtCreateGenericState (); + if (!Scope) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Scope->Common.DescriptorType = ACPI_DESC_TYPE_STATE_RPSCOPE; + Scope->ParseScope.Op = RootOp; + Scope->ParseScope.ArgCount = ACPI_VAR_ARGS; + Scope->ParseScope.ArgEnd = ParserState->AmlEnd; + Scope->ParseScope.PkgEnd = ParserState->AmlEnd; + + ParserState->Scope = Scope; + ParserState->StartOp = RootOp; + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsPushScope + * + * PARAMETERS: ParserState - Current parser state object + * Op - Current op to be pushed + * RemainingArgs - List of args remaining + * ArgCount - Fixed or variable number of args + * + * RETURN: Status + * + * DESCRIPTION: Push current op to begin parsing its argument + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsPushScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *Op, + UINT32 RemainingArgs, + UINT32 ArgCount) +{ + ACPI_GENERIC_STATE *Scope; + + + ACPI_FUNCTION_TRACE_PTR (PsPushScope, Op); + + + Scope = AcpiUtCreateGenericState (); + if (!Scope) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Scope->Common.DescriptorType = ACPI_DESC_TYPE_STATE_PSCOPE; + Scope->ParseScope.Op = Op; + Scope->ParseScope.ArgList = RemainingArgs; + Scope->ParseScope.ArgCount = ArgCount; + Scope->ParseScope.PkgEnd = ParserState->PkgEnd; + + /* Push onto scope stack */ + + AcpiUtPushGenericState (&ParserState->Scope, Scope); + + if (ArgCount == ACPI_VAR_ARGS) + { + /* Multiple arguments */ + + Scope->ParseScope.ArgEnd = ParserState->PkgEnd; + } + else + { + /* Single argument */ + + Scope->ParseScope.ArgEnd = ACPI_TO_POINTER (ACPI_MAX_PTR); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsPopScope + * + * PARAMETERS: ParserState - Current parser state object + * Op - Where the popped op is returned + * ArgList - Where the popped "next argument" is + * returned + * ArgCount - Count of objects in ArgList + * + * RETURN: Status + * + * DESCRIPTION: Return to parsing a previous op + * + ******************************************************************************/ + +void +AcpiPsPopScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT **Op, + UINT32 *ArgList, + UINT32 *ArgCount) +{ + ACPI_GENERIC_STATE *Scope = ParserState->Scope; + + + ACPI_FUNCTION_TRACE (PsPopScope); + + + /* Only pop the scope if there is in fact a next scope */ + + if (Scope->Common.Next) + { + Scope = AcpiUtPopGenericState (&ParserState->Scope); + + /* Return to parsing previous op */ + + *Op = Scope->ParseScope.Op; + *ArgList = Scope->ParseScope.ArgList; + *ArgCount = Scope->ParseScope.ArgCount; + ParserState->PkgEnd = Scope->ParseScope.PkgEnd; + + /* All done with this scope state structure */ + + AcpiUtDeleteGenericState (Scope); + } + else + { + /* Empty parse stack, prepare to fetch next opcode */ + + *Op = NULL; + *ArgList = 0; + *ArgCount = 0; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Popped Op %p Args %X\n", *Op, *ArgCount)); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCleanupScope + * + * PARAMETERS: ParserState - Current parser state object + * + * RETURN: None + * + * DESCRIPTION: Destroy available list, remaining stack levels, and return + * root scope + * + ******************************************************************************/ + +void +AcpiPsCleanupScope ( + ACPI_PARSE_STATE *ParserState) +{ + ACPI_GENERIC_STATE *Scope; + + + ACPI_FUNCTION_TRACE_PTR (PsCleanupScope, ParserState); + + + if (!ParserState) + { + return_VOID; + } + + /* Delete anything on the scope stack */ + + while (ParserState->Scope) + { + Scope = AcpiUtPopGenericState (&ParserState->Scope); + AcpiUtDeleteGenericState (Scope); + } + + return_VOID; +} + diff --git a/source/components/parser/pstree.c b/source/components/parser/pstree.c new file mode 100644 index 000000000000..8271314e16ab --- /dev/null +++ b/source/components/parser/pstree.c @@ -0,0 +1,360 @@ +/****************************************************************************** + * + * Module Name: pstree - Parser op tree manipulation/traversal/search + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __PSTREE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("pstree") + +/* Local prototypes */ + +#ifdef ACPI_OBSOLETE_FUNCTIONS +ACPI_PARSE_OBJECT * +AcpiPsGetChild ( + ACPI_PARSE_OBJECT *op); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetArg + * + * PARAMETERS: Op - Get an argument for this op + * Argn - Nth argument to get + * + * RETURN: The argument (as an Op object). NULL if argument does not exist + * + * DESCRIPTION: Get the specified op's argument. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +AcpiPsGetArg ( + ACPI_PARSE_OBJECT *Op, + UINT32 Argn) +{ + ACPI_PARSE_OBJECT *Arg = NULL; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_ENTRY (); + +/* + if (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP) + { + return (Op->Common.Value.Arg); + } +*/ + /* Get the info structure for this opcode */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (OpInfo->Class == AML_CLASS_UNKNOWN) + { + /* Invalid opcode or ASCII character */ + + return (NULL); + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(OpInfo->Flags & AML_HAS_ARGS)) + { + /* Has no linked argument objects */ + + return (NULL); + } + + /* Get the requested argument object */ + + Arg = Op->Common.Value.Arg; + while (Arg && Argn) + { + Argn--; + Arg = Arg->Common.Next; + } + + return (Arg); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsAppendArg + * + * PARAMETERS: Op - Append an argument to this Op. + * Arg - Argument Op to append + * + * RETURN: None. + * + * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) + * + ******************************************************************************/ + +void +AcpiPsAppendArg ( + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_OBJECT *Arg) +{ + ACPI_PARSE_OBJECT *PrevArg; + const ACPI_OPCODE_INFO *OpInfo; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Op) + { + return; + } + + /* Get the info structure for this opcode */ + + OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (OpInfo->Class == AML_CLASS_UNKNOWN) + { + /* Invalid opcode */ + + ACPI_ERROR ((AE_INFO, "Invalid AML Opcode: 0x%2.2X", + Op->Common.AmlOpcode)); + return; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(OpInfo->Flags & AML_HAS_ARGS)) + { + /* Has no linked argument objects */ + + return; + } + + /* Append the argument to the linked argument list */ + + if (Op->Common.Value.Arg) + { + /* Append to existing argument list */ + + PrevArg = Op->Common.Value.Arg; + while (PrevArg->Common.Next) + { + PrevArg = PrevArg->Common.Next; + } + PrevArg->Common.Next = Arg; + } + else + { + /* No argument list, this will be the first argument */ + + Op->Common.Value.Arg = Arg; + } + + /* Set the parent in this arg and any args linked after it */ + + while (Arg) + { + Arg->Common.Parent = Op; + Arg = Arg->Common.Next; + + Op->Common.ArgListLength++; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsGetDepthNext + * + * PARAMETERS: Origin - Root of subtree to search + * Op - Last (previous) Op that was found + * + * RETURN: Next Op found in the search. + * + * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) + * Return NULL when reaching "origin" or when walking up from root + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +AcpiPsGetDepthNext ( + ACPI_PARSE_OBJECT *Origin, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next = NULL; + ACPI_PARSE_OBJECT *Parent; + ACPI_PARSE_OBJECT *Arg; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Op) + { + return (NULL); + } + + /* Look for an argument or child */ + + Next = AcpiPsGetArg (Op, 0); + if (Next) + { + return (Next); + } + + /* Look for a sibling */ + + Next = Op->Common.Next; + if (Next) + { + return (Next); + } + + /* Look for a sibling of parent */ + + Parent = Op->Common.Parent; + + while (Parent) + { + Arg = AcpiPsGetArg (Parent, 0); + while (Arg && (Arg != Origin) && (Arg != Op)) + { + Arg = Arg->Common.Next; + } + + if (Arg == Origin) + { + /* Reached parent of origin, end search */ + + return (NULL); + } + + if (Parent->Common.Next) + { + /* Found sibling of parent */ + + return (Parent->Common.Next); + } + + Op = Parent; + Parent = Parent->Common.Parent; + } + + return (Next); +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: AcpiPsGetChild + * + * PARAMETERS: Op - Get the child of this Op + * + * RETURN: Child Op, Null if none is found. + * + * DESCRIPTION: Get op's children or NULL if none + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +AcpiPsGetChild ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Child = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + switch (Op->Common.AmlOpcode) + { + case AML_SCOPE_OP: + case AML_ELSE_OP: + case AML_DEVICE_OP: + case AML_THERMAL_ZONE_OP: + case AML_INT_METHODCALL_OP: + + Child = AcpiPsGetArg (Op, 0); + break; + + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_METHOD_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_FIELD_OP: + + Child = AcpiPsGetArg (Op, 1); + break; + + + case AML_POWER_RES_OP: + case AML_INDEX_FIELD_OP: + + Child = AcpiPsGetArg (Op, 2); + break; + + + case AML_PROCESSOR_OP: + case AML_BANK_FIELD_OP: + + Child = AcpiPsGetArg (Op, 3); + break; + + + default: + /* All others have no children */ + break; + } + + return (Child); +} +#endif + + diff --git a/source/components/parser/psutils.c b/source/components/parser/psutils.c new file mode 100644 index 000000000000..e28b75cc8f23 --- /dev/null +++ b/source/components/parser/psutils.c @@ -0,0 +1,290 @@ +/****************************************************************************** + * + * Module Name: psutils - Parser miscellaneous utilities (Parser only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psutils") + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCreateScopeOp + * + * PARAMETERS: None + * + * RETURN: A new Scope object, null on failure + * + * DESCRIPTION: Create a Scope and associated namepath op with the root name + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +AcpiPsCreateScopeOp ( + void) +{ + ACPI_PARSE_OBJECT *ScopeOp; + + + ScopeOp = AcpiPsAllocOp (AML_SCOPE_OP); + if (!ScopeOp) + { + return (NULL); + } + + ScopeOp->Named.Name = ACPI_ROOT_NAME; + return (ScopeOp); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsInitOp + * + * PARAMETERS: Op - A newly allocated Op object + * Opcode - Opcode to store in the Op + * + * RETURN: None + * + * DESCRIPTION: Initialize a parse (Op) object + * + ******************************************************************************/ + +void +AcpiPsInitOp ( + ACPI_PARSE_OBJECT *Op, + UINT16 Opcode) +{ + ACPI_FUNCTION_ENTRY (); + + + Op->Common.DescriptorType = ACPI_DESC_TYPE_PARSER; + Op->Common.AmlOpcode = Opcode; + + ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (Op->Common.AmlOpName, + (AcpiPsGetOpcodeInfo (Opcode))->Name, + sizeof (Op->Common.AmlOpName))); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsAllocOp + * + * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * + * RETURN: Pointer to the new Op, null on failure + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode. A cache of opcodes is available for the pure + * GENERIC_OP, since this is by far the most commonly used. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT* +AcpiPsAllocOp ( + UINT16 Opcode) +{ + ACPI_PARSE_OBJECT *Op; + const ACPI_OPCODE_INFO *OpInfo; + UINT8 Flags = ACPI_PARSEOP_GENERIC; + + + ACPI_FUNCTION_ENTRY (); + + + OpInfo = AcpiPsGetOpcodeInfo (Opcode); + + /* Determine type of ParseOp required */ + + if (OpInfo->Flags & AML_DEFER) + { + Flags = ACPI_PARSEOP_DEFERRED; + } + else if (OpInfo->Flags & AML_NAMED) + { + Flags = ACPI_PARSEOP_NAMED; + } + else if (Opcode == AML_INT_BYTELIST_OP) + { + Flags = ACPI_PARSEOP_BYTELIST; + } + + /* Allocate the minimum required size object */ + + if (Flags == ACPI_PARSEOP_GENERIC) + { + /* The generic op (default) is by far the most common (16 to 1) */ + + Op = AcpiOsAcquireObject (AcpiGbl_PsNodeCache); + } + else + { + /* Extended parseop */ + + Op = AcpiOsAcquireObject (AcpiGbl_PsNodeExtCache); + } + + /* Initialize the Op */ + + if (Op) + { + AcpiPsInitOp (Op, Opcode); + Op->Common.Flags = Flags; + } + + return (Op); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsFreeOp + * + * PARAMETERS: Op - Op to be freed + * + * RETURN: None. + * + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * or actually free it. + * + ******************************************************************************/ + +void +AcpiPsFreeOp ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_FUNCTION_NAME (PsFreeOp); + + + if (Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", Op)); + } + + if (Op->Common.Flags & ACPI_PARSEOP_GENERIC) + { + (void) AcpiOsReleaseObject (AcpiGbl_PsNodeCache, Op); + } + else + { + (void) AcpiOsReleaseObject (AcpiGbl_PsNodeExtCache, Op); + } +} + + +/******************************************************************************* + * + * FUNCTION: Utility functions + * + * DESCRIPTION: Low level character and object functions + * + ******************************************************************************/ + + +/* + * Is "c" a namestring lead character? + */ +BOOLEAN +AcpiPsIsLeadingChar ( + UINT32 c) +{ + return ((BOOLEAN) (c == '_' || (c >= 'A' && c <= 'Z'))); +} + + +/* + * Is "c" a namestring prefix character? + */ +BOOLEAN +AcpiPsIsPrefixChar ( + UINT32 c) +{ + return ((BOOLEAN) (c == '\\' || c == '^')); +} + + +/* + * Get op's name (4-byte name segment) or 0 if unnamed + */ +UINT32 +AcpiPsGetName ( + ACPI_PARSE_OBJECT *Op) +{ + + /* The "generic" object has no name associated with it */ + + if (Op->Common.Flags & ACPI_PARSEOP_GENERIC) + { + return (0); + } + + /* Only the "Extended" parse objects have a name */ + + return (Op->Named.Name); +} + + +/* + * Set op's name + */ +void +AcpiPsSetName ( + ACPI_PARSE_OBJECT *Op, + UINT32 name) +{ + + /* The "generic" object has no name associated with it */ + + if (Op->Common.Flags & ACPI_PARSEOP_GENERIC) + { + return; + } + + Op->Named.Name = name; +} + diff --git a/source/components/parser/pswalk.c b/source/components/parser/pswalk.c new file mode 100644 index 000000000000..9734c4d17711 --- /dev/null +++ b/source/components/parser/pswalk.c @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * Module Name: pswalk - Parser routines to walk parsed op tree(s) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("pswalk") + + +/******************************************************************************* + * + * FUNCTION: AcpiPsDeleteParseTree + * + * PARAMETERS: SubtreeRoot - Root of tree (or subtree) to delete + * + * RETURN: None + * + * DESCRIPTION: Delete a portion of or an entire parse tree. + * + ******************************************************************************/ + +void +AcpiPsDeleteParseTree ( + ACPI_PARSE_OBJECT *SubtreeRoot) +{ + ACPI_PARSE_OBJECT *Op = SubtreeRoot; + ACPI_PARSE_OBJECT *Next = NULL; + ACPI_PARSE_OBJECT *Parent = NULL; + + + ACPI_FUNCTION_TRACE_PTR (PsDeleteParseTree, SubtreeRoot); + + + /* Visit all nodes in the subtree */ + + while (Op) + { + /* Check if we are not ascending */ + + if (Op != Parent) + { + /* Look for an argument or child of the current op */ + + Next = AcpiPsGetArg (Op, 0); + if (Next) + { + /* Still going downward in tree (Op is not completed yet) */ + + Op = Next; + continue; + } + } + + /* No more children, this Op is complete. */ + + Next = Op->Common.Next; + Parent = Op->Common.Parent; + + AcpiPsFreeOp (Op); + + /* If we are back to the starting point, the walk is complete. */ + + if (Op == SubtreeRoot) + { + return_VOID; + } + if (Next) + { + Op = Next; + } + else + { + Op = Parent; + } + } + + return_VOID; +} diff --git a/source/components/parser/psxface.c b/source/components/parser/psxface.c new file mode 100644 index 000000000000..2a012c2915c9 --- /dev/null +++ b/source/components/parser/psxface.c @@ -0,0 +1,442 @@ +/****************************************************************************** + * + * Module Name: psxface - Parser external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __PSXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psxface") + +/* Local Prototypes */ + +static void +AcpiPsStartTrace ( + ACPI_EVALUATE_INFO *Info); + +static void +AcpiPsStopTrace ( + ACPI_EVALUATE_INFO *Info); + +static void +AcpiPsUpdateParameterList ( + ACPI_EVALUATE_INFO *Info, + UINT16 Action); + + +/******************************************************************************* + * + * FUNCTION: AcpiDebugTrace + * + * PARAMETERS: MethodName - Valid ACPI name string + * DebugLevel - Optional level mask. 0 to use default + * DebugLayer - Optional layer mask. 0 to use default + * Flags - bit 1: one shot(1) or persistent(0) + * + * RETURN: Status + * + * DESCRIPTION: External interface to enable debug tracing during control + * method execution + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDebugTrace ( + char *Name, + UINT32 DebugLevel, + UINT32 DebugLayer, + UINT32 Flags) +{ + ACPI_STATUS Status; + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* TBDs: Validate name, allow full path or just nameseg */ + + AcpiGbl_TraceMethodName = *ACPI_CAST_PTR (UINT32, Name); + AcpiGbl_TraceFlags = Flags; + + if (DebugLevel) + { + AcpiGbl_TraceDbgLevel = DebugLevel; + } + if (DebugLayer) + { + AcpiGbl_TraceDbgLayer = DebugLayer; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsStartTrace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +static void +AcpiPsStartTrace ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return; + } + + if ((!AcpiGbl_TraceMethodName) || + (AcpiGbl_TraceMethodName != Info->ResolvedNode->Name.Integer)) + { + goto Exit; + } + + AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; + AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; + + AcpiDbgLevel = 0x00FFFFFF; + AcpiDbgLayer = ACPI_UINT32_MAX; + + if (AcpiGbl_TraceDbgLevel) + { + AcpiDbgLevel = AcpiGbl_TraceDbgLevel; + } + if (AcpiGbl_TraceDbgLayer) + { + AcpiDbgLayer = AcpiGbl_TraceDbgLayer; + } + + +Exit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsStopTrace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +static void +AcpiPsStopTrace ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return; + } + + if ((!AcpiGbl_TraceMethodName) || + (AcpiGbl_TraceMethodName != Info->ResolvedNode->Name.Integer)) + { + goto Exit; + } + + /* Disable further tracing if type is one-shot */ + + if (AcpiGbl_TraceFlags & 1) + { + AcpiGbl_TraceMethodName = 0; + AcpiGbl_TraceDbgLevel = 0; + AcpiGbl_TraceDbgLayer = 0; + } + + AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; + AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; + +Exit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsExecuteMethod + * + * PARAMETERS: Info - Method info block, contains: + * Node - Method Node to execute + * ObjDesc - Method object + * Parameters - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * ReturnObject - Where to put method's return value (if + * any). If NULL, no value is returned. + * ParameterType - Type of Parameter list + * ReturnObject - Where to put method's return value (if + * any). If NULL, no value is returned. + * PassNumber - Parse or execute pass + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsExecuteMethod ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Op; + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_TRACE (PsExecuteMethod); + + + /* Quick validation of DSDT header */ + + AcpiTbCheckDsdtHeader (); + + /* Validate the Info and method Node */ + + if (!Info || !Info->ResolvedNode) + { + return_ACPI_STATUS (AE_NULL_ENTRY); + } + + /* Init for new method, wait on concurrency semaphore */ + + Status = AcpiDsBeginMethodExecution (Info->ResolvedNode, Info->ObjDesc, NULL); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * The caller "owns" the parameters, so give each one an extra reference + */ + AcpiPsUpdateParameterList (Info, REF_INCREMENT); + + /* Begin tracing if requested */ + + AcpiPsStartTrace (Info); + + /* + * Execute the method. Performs parse simultaneously + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", + Info->ResolvedNode->Name.Ascii, Info->ResolvedNode, Info->ObjDesc)); + + /* Create and init a Root Node */ + + Op = AcpiPsCreateScopeOp (); + if (!Op) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Create and initialize a new walk state */ + + Info->PassNumber = ACPI_IMODE_EXECUTE; + WalkState = AcpiDsCreateWalkState ( + Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL); + if (!WalkState) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, Info->ResolvedNode, + Info->ObjDesc->Method.AmlStart, + Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) + { + WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL; + } + + /* Invoke an internal method if necessary */ + + if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) + { + Status = Info->ObjDesc->Method.Dispatch.Implementation (WalkState); + Info->ReturnObject = WalkState->ReturnDesc; + + /* Cleanup states */ + + AcpiDsScopeStackClear (WalkState); + AcpiPsCleanupScope (&WalkState->ParserState); + AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + /* + * Start method evaluation with an implicit return of zero. This is done + * for Windows compatibility. + */ + if (AcpiGbl_EnableInterpreterSlack) + { + WalkState->ImplicitReturnObj = + AcpiUtCreateIntegerObject ((UINT64) 0); + if (!WalkState->ImplicitReturnObj) + { + Status = AE_NO_MEMORY; + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + } + + /* Parse the AML */ + + Status = AcpiPsParseAml (WalkState); + + /* WalkState was deleted by ParseAml */ + +Cleanup: + AcpiPsDeleteParseTree (Op); + + /* End optional tracing */ + + AcpiPsStopTrace (Info); + + /* Take away the extra reference that we gave the parameters above */ + + AcpiPsUpdateParameterList (Info, REF_DECREMENT); + + /* Exit now if error above */ + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * If the method has returned an object, signal this to the caller with + * a control exception code + */ + if (Info->ReturnObject) + { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", + Info->ReturnObject)); + ACPI_DUMP_STACK_ENTRY (Info->ReturnObject); + + Status = AE_CTRL_RETURN_VALUE; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsUpdateParameterList + * + * PARAMETERS: Info - See ACPI_EVALUATE_INFO + * (Used: ParameterType and Parameters) + * Action - Add or Remove reference + * + * RETURN: Status + * + * DESCRIPTION: Update reference count on all method parameter objects + * + ******************************************************************************/ + +static void +AcpiPsUpdateParameterList ( + ACPI_EVALUATE_INFO *Info, + UINT16 Action) +{ + UINT32 i; + + + if (Info->Parameters) + { + /* Update reference count for each parameter */ + + for (i = 0; Info->Parameters[i]; i++) + { + /* Ignore errors, just do them all */ + + (void) AcpiUtUpdateObjectReference (Info->Parameters[i], Action); + } + } +} + + diff --git a/source/components/resources/rsaddr.c b/source/components/resources/rsaddr.c new file mode 100644 index 000000000000..90e7d43b6e01 --- /dev/null +++ b/source/components/resources/rsaddr.c @@ -0,0 +1,407 @@ +/******************************************************************************* + * + * Module Name: rsaddr - Address resource descriptors (16/32/64) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSADDR_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsaddr") + + +/******************************************************************************* + * + * AcpiRsConvertAddress16 - All WORD (16-bit) address resources + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertAddress16[5] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16, + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS16), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertAddress16)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16, + sizeof (AML_RESOURCE_ADDRESS16), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.Address16.Granularity), + AML_OFFSET (Address16.Granularity), + 5}, + + /* Optional ResourceSource (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET (Data.Address16.ResourceSource), + 0, + sizeof (AML_RESOURCE_ADDRESS16)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertAddress32 - All DWORD (32-bit) address resources + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertAddress32[5] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32, + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS32), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertAddress32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32, + sizeof (AML_RESOURCE_ADDRESS32), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.Address32.Granularity), + AML_OFFSET (Address32.Granularity), + 5}, + + /* Optional ResourceSource (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET (Data.Address32.ResourceSource), + 0, + sizeof (AML_RESOURCE_ADDRESS32)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertAddress64 - All QWORD (64-bit) address resources + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertAddress64[5] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64, + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS64), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertAddress64)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64, + sizeof (AML_RESOURCE_ADDRESS64), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET (Data.Address64.Granularity), + AML_OFFSET (Address64.Granularity), + 5}, + + /* Optional ResourceSource (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET (Data.Address64.ResourceSource), + 0, + sizeof (AML_RESOURCE_ADDRESS64)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertExtAddress64 - All Extended (64-bit) address resources + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertExtAddress64[5] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, + ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_ADDRESS64), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertExtAddress64)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64, + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* Revision ID */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.ExtAddress64.RevisionID), + AML_OFFSET (ExtAddress64.RevisionID), + 1}, + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + * Type-Specific Attribute + */ + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET (Data.ExtAddress64.Granularity), + AML_OFFSET (ExtAddress64.Granularity), + 6} +}; + + +/******************************************************************************* + * + * AcpiRsConvertGeneralFlags - Flags common to all address descriptors + * + ******************************************************************************/ + +static ACPI_RSCONVERT_INFO AcpiRsConvertGeneralFlags[6] = +{ + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET (Address.Flags), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertGeneralFlags)}, + + /* Resource Type (Memory, Io, BusNumber, etc.) */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Address.ResourceType), + AML_OFFSET (Address.ResourceType), + 1}, + + /* General Flags - Consume, Decode, MinFixed, MaxFixed */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.ProducerConsumer), + AML_OFFSET (Address.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.Decode), + AML_OFFSET (Address.Flags), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.MinAddressFixed), + AML_OFFSET (Address.Flags), + 2}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.MaxAddressFixed), + AML_OFFSET (Address.Flags), + 3} +}; + + +/******************************************************************************* + * + * AcpiRsConvertMemFlags - Flags common to Memory address descriptors + * + ******************************************************************************/ + +static ACPI_RSCONVERT_INFO AcpiRsConvertMemFlags[5] = +{ + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET (Address.SpecificFlags), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertMemFlags)}, + + /* Memory-specific flags */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Mem.WriteProtect), + AML_OFFSET (Address.SpecificFlags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Mem.Caching), + AML_OFFSET (Address.SpecificFlags), + 1}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Mem.RangeType), + AML_OFFSET (Address.SpecificFlags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Mem.Translation), + AML_OFFSET (Address.SpecificFlags), + 5} +}; + + +/******************************************************************************* + * + * AcpiRsConvertIoFlags - Flags common to I/O address descriptors + * + ******************************************************************************/ + +static ACPI_RSCONVERT_INFO AcpiRsConvertIoFlags[4] = +{ + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET (Address.SpecificFlags), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertIoFlags)}, + + /* I/O-specific flags */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Io.RangeType), + AML_OFFSET (Address.SpecificFlags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Io.Translation), + AML_OFFSET (Address.SpecificFlags), + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Address.Info.Io.TranslationType), + AML_OFFSET (Address.SpecificFlags), + 5} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetAddressCommon + * + * PARAMETERS: Resource - Pointer to the internal resource struct + * Aml - Pointer to the AML resource descriptor + * + * RETURN: TRUE if the ResourceType field is OK, FALSE otherwise + * + * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +BOOLEAN +AcpiRsGetAddressCommon ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Validate the Resource Type */ + + if ((Aml->Address.ResourceType > 2) && (Aml->Address.ResourceType < 0xC0)) + { + return (FALSE); + } + + /* Get the Resource Type and General Flags */ + + (void) AcpiRsConvertAmlToResource (Resource, Aml, AcpiRsConvertGeneralFlags); + + /* Get the Type-Specific Flags (Memory and I/O descriptors only) */ + + if (Resource->Data.Address.ResourceType == ACPI_MEMORY_RANGE) + { + (void) AcpiRsConvertAmlToResource (Resource, Aml, AcpiRsConvertMemFlags); + } + else if (Resource->Data.Address.ResourceType == ACPI_IO_RANGE) + { + (void) AcpiRsConvertAmlToResource (Resource, Aml, AcpiRsConvertIoFlags); + } + else + { + /* Generic resource type, just grab the TypeSpecific byte */ + + Resource->Data.Address.Info.TypeSpecific = Aml->Address.SpecificFlags; + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsSetAddressCommon + * + * PARAMETERS: Aml - Pointer to the AML resource descriptor + * Resource - Pointer to the internal resource struct + * + * RETURN: None + * + * DESCRIPTION: Convert common flag fields from a resource descriptor to an + * AML descriptor + * + ******************************************************************************/ + +void +AcpiRsSetAddressCommon ( + AML_RESOURCE *Aml, + ACPI_RESOURCE *Resource) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Set the Resource Type and General Flags */ + + (void) AcpiRsConvertResourceToAml (Resource, Aml, AcpiRsConvertGeneralFlags); + + /* Set the Type-Specific Flags (Memory and I/O descriptors only) */ + + if (Resource->Data.Address.ResourceType == ACPI_MEMORY_RANGE) + { + (void) AcpiRsConvertResourceToAml (Resource, Aml, AcpiRsConvertMemFlags); + } + else if (Resource->Data.Address.ResourceType == ACPI_IO_RANGE) + { + (void) AcpiRsConvertResourceToAml (Resource, Aml, AcpiRsConvertIoFlags); + } + else + { + /* Generic resource type, just copy the TypeSpecific byte */ + + Aml->Address.SpecificFlags = Resource->Data.Address.Info.TypeSpecific; + } +} + + diff --git a/source/components/resources/rscalc.c b/source/components/resources/rscalc.c new file mode 100644 index 000000000000..845ed69c7dee --- /dev/null +++ b/source/components/resources/rscalc.c @@ -0,0 +1,730 @@ +/******************************************************************************* + * + * Module Name: rscalc - Calculate stream and list lengths + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSCALC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rscalc") + + +/* Local prototypes */ + +static UINT8 +AcpiRsCountSetBits ( + UINT16 BitField); + +static ACPI_RS_LENGTH +AcpiRsStructOptionLength ( + ACPI_RESOURCE_SOURCE *ResourceSource); + +static UINT32 +AcpiRsStreamOptionLength ( + UINT32 ResourceLength, + UINT32 MinimumTotalLength); + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCountSetBits + * + * PARAMETERS: BitField - Field in which to count bits + * + * RETURN: Number of bits set within the field + * + * DESCRIPTION: Count the number of bits set in a resource field. Used for + * (Short descriptor) interrupt and DMA lists. + * + ******************************************************************************/ + +static UINT8 +AcpiRsCountSetBits ( + UINT16 BitField) +{ + UINT8 BitsSet; + + + ACPI_FUNCTION_ENTRY (); + + + for (BitsSet = 0; BitField; BitsSet++) + { + /* Zero the least significant bit that is set */ + + BitField &= (UINT16) (BitField - 1); + } + + return (BitsSet); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsStructOptionLength + * + * PARAMETERS: ResourceSource - Pointer to optional descriptor field + * + * RETURN: Status + * + * DESCRIPTION: Common code to handle optional ResourceSourceIndex and + * ResourceSource fields in some Large descriptors. Used during + * list-to-stream conversion + * + ******************************************************************************/ + +static ACPI_RS_LENGTH +AcpiRsStructOptionLength ( + ACPI_RESOURCE_SOURCE *ResourceSource) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * If the ResourceSource string is valid, return the size of the string + * (StringLength includes the NULL terminator) plus the size of the + * ResourceSourceIndex (1). + */ + if (ResourceSource->StringPtr) + { + return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1)); + } + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsStreamOptionLength + * + * PARAMETERS: ResourceLength - Length from the resource header + * MinimumTotalLength - Minimum length of this resource, before + * any optional fields. Includes header size + * + * RETURN: Length of optional string (0 if no string present) + * + * DESCRIPTION: Common code to handle optional ResourceSourceIndex and + * ResourceSource fields in some Large descriptors. Used during + * stream-to-list conversion + * + ******************************************************************************/ + +static UINT32 +AcpiRsStreamOptionLength ( + UINT32 ResourceLength, + UINT32 MinimumAmlResourceLength) +{ + UINT32 StringLength = 0; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * The ResourceSourceIndex and ResourceSource are optional elements of some + * Large-type resource descriptors. + */ + + /* + * If the length of the actual resource descriptor is greater than the ACPI + * spec-defined minimum length, it means that a ResourceSourceIndex exists + * and is followed by a (required) null terminated string. The string length + * (including the null terminator) is the resource length minus the minimum + * length, minus one byte for the ResourceSourceIndex itself. + */ + if (ResourceLength > MinimumAmlResourceLength) + { + /* Compute the length of the optional string */ + + StringLength = ResourceLength - MinimumAmlResourceLength - 1; + } + + /* + * Round the length up to a multiple of the native word in order to + * guarantee that the entire resource descriptor is native word aligned + */ + return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetAmlLength + * + * PARAMETERS: Resource - Pointer to the resource linked list + * SizeNeeded - Where the required size is returned + * + * RETURN: Status + * + * DESCRIPTION: Takes a linked list of internal resource descriptors and + * calculates the size buffer needed to hold the corresponding + * external resource byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetAmlLength ( + ACPI_RESOURCE *Resource, + ACPI_SIZE *SizeNeeded) +{ + ACPI_SIZE AmlSizeNeeded = 0; + ACPI_RS_LENGTH TotalSize; + + + ACPI_FUNCTION_TRACE (RsGetAmlLength); + + + /* Traverse entire list of internal resource descriptors */ + + while (Resource) + { + /* Validate the descriptor type */ + + if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) + { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Get the base size of the (external stream) resource descriptor */ + + TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type]; + + /* + * Augment the base size for descriptors with optional and/or + * variable-length fields + */ + switch (Resource->Type) + { + case ACPI_RESOURCE_TYPE_IRQ: + + /* Length can be 3 or 2 */ + + if (Resource->Data.Irq.DescriptorLength == 2) + { + TotalSize--; + } + break; + + + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + + /* Length can be 1 or 0 */ + + if (Resource->Data.Irq.DescriptorLength == 0) + { + TotalSize--; + } + break; + + + case ACPI_RESOURCE_TYPE_VENDOR: + /* + * Vendor Defined Resource: + * For a Vendor Specific resource, if the Length is between 1 and 7 + * it will be created as a Small Resource data type, otherwise it + * is a Large Resource data type. + */ + if (Resource->Data.Vendor.ByteLength > 7) + { + /* Base size of a Large resource descriptor */ + + TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER); + } + + /* Add the size of the vendor-specific data */ + + TotalSize = (ACPI_RS_LENGTH) + (TotalSize + Resource->Data.Vendor.ByteLength); + break; + + + case ACPI_RESOURCE_TYPE_END_TAG: + /* + * End Tag: + * We are done -- return the accumulated total size. + */ + *SizeNeeded = AmlSizeNeeded + TotalSize; + + /* Normal exit */ + + return_ACPI_STATUS (AE_OK); + + + case ACPI_RESOURCE_TYPE_ADDRESS16: + /* + * 16-Bit Address Resource: + * Add the size of the optional ResourceSource info + */ + TotalSize = (ACPI_RS_LENGTH) + (TotalSize + AcpiRsStructOptionLength ( + &Resource->Data.Address16.ResourceSource)); + break; + + + case ACPI_RESOURCE_TYPE_ADDRESS32: + /* + * 32-Bit Address Resource: + * Add the size of the optional ResourceSource info + */ + TotalSize = (ACPI_RS_LENGTH) + (TotalSize + AcpiRsStructOptionLength ( + &Resource->Data.Address32.ResourceSource)); + break; + + + case ACPI_RESOURCE_TYPE_ADDRESS64: + /* + * 64-Bit Address Resource: + * Add the size of the optional ResourceSource info + */ + TotalSize = (ACPI_RS_LENGTH) + (TotalSize + AcpiRsStructOptionLength ( + &Resource->Data.Address64.ResourceSource)); + break; + + + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + /* + * Extended IRQ Resource: + * Add the size of each additional optional interrupt beyond the + * required 1 (4 bytes for each UINT32 interrupt number) + */ + TotalSize = (ACPI_RS_LENGTH) + (TotalSize + + ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) + + + /* Add the size of the optional ResourceSource info */ + + AcpiRsStructOptionLength ( + &Resource->Data.ExtendedIrq.ResourceSource)); + break; + + + case ACPI_RESOURCE_TYPE_GPIO: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + (Resource->Data.Gpio.PinTableLength * 2) + + Resource->Data.Gpio.ResourceSource.StringLength + + Resource->Data.Gpio.VendorLength); + + break; + + + case ACPI_RESOURCE_TYPE_SERIAL_BUS: + + TotalSize = AcpiGbl_AmlResourceSerialBusSizes [Resource->Data.CommonSerialBus.Type]; + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + Resource->Data.I2cSerialBus.ResourceSource.StringLength + + Resource->Data.I2cSerialBus.VendorLength); + + break; + + + default: + break; + } + + /* Update the total */ + + AmlSizeNeeded += TotalSize; + + /* Point to the next object */ + + Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length); + } + + /* Did not find an EndTag resource descriptor */ + + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetListLength + * + * PARAMETERS: AmlBuffer - Pointer to the resource byte stream + * AmlBufferLength - Size of AmlBuffer + * SizeNeeded - Where the size needed is returned + * + * RETURN: Status + * + * DESCRIPTION: Takes an external resource byte stream and calculates the size + * buffer needed to hold the corresponding internal resource + * descriptor linked list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetListLength ( + UINT8 *AmlBuffer, + UINT32 AmlBufferLength, + ACPI_SIZE *SizeNeeded) +{ + ACPI_STATUS Status; + UINT8 *EndAml; + UINT8 *Buffer; + UINT32 BufferSize; + UINT16 Temp16; + UINT16 ResourceLength; + UINT32 ExtraStructBytes; + UINT8 ResourceIndex; + UINT8 MinimumAmlResourceLength; + AML_RESOURCE *AmlResource; + + + ACPI_FUNCTION_TRACE (RsGetListLength); + + + *SizeNeeded = ACPI_RS_SIZE_MIN; /* Minimum size is one EndTag */ + EndAml = AmlBuffer + AmlBufferLength; + + /* Walk the list of AML resource descriptors */ + + while (AmlBuffer < EndAml) + { + /* Validate the Resource Type and Resource Length */ + + Status = AcpiUtValidateResource (AmlBuffer, &ResourceIndex); + if (ACPI_FAILURE (Status)) + { + /* + * Exit on failure. Cannot continue because the descriptor length + * may be bogus also. + */ + return_ACPI_STATUS (Status); + } + + AmlResource = (void *) AmlBuffer; + + /* Get the resource length and base (minimum) AML size */ + + ResourceLength = AcpiUtGetResourceLength (AmlBuffer); + MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; + + /* + * Augment the size for descriptors with optional + * and/or variable length fields + */ + ExtraStructBytes = 0; + Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer); + + switch (AcpiUtGetResourceType (AmlBuffer)) + { + case ACPI_RESOURCE_NAME_IRQ: + /* + * IRQ Resource: + * Get the number of bits set in the 16-bit IRQ mask + */ + ACPI_MOVE_16_TO_16 (&Temp16, Buffer); + ExtraStructBytes = AcpiRsCountSetBits (Temp16); + break; + + + case ACPI_RESOURCE_NAME_DMA: + /* + * DMA Resource: + * Get the number of bits set in the 8-bit DMA mask + */ + ExtraStructBytes = AcpiRsCountSetBits (*Buffer); + break; + + + case ACPI_RESOURCE_NAME_VENDOR_SMALL: + case ACPI_RESOURCE_NAME_VENDOR_LARGE: + /* + * Vendor Resource: + * Get the number of vendor data bytes + */ + ExtraStructBytes = ResourceLength; + break; + + + case ACPI_RESOURCE_NAME_END_TAG: + /* + * End Tag: This is the normal exit + */ + return_ACPI_STATUS (AE_OK); + + + case ACPI_RESOURCE_NAME_ADDRESS32: + case ACPI_RESOURCE_NAME_ADDRESS16: + case ACPI_RESOURCE_NAME_ADDRESS64: + /* + * Address Resource: + * Add the size of the optional ResourceSource + */ + ExtraStructBytes = AcpiRsStreamOptionLength ( + ResourceLength, MinimumAmlResourceLength); + break; + + + case ACPI_RESOURCE_NAME_EXTENDED_IRQ: + /* + * Extended IRQ Resource: + * Using the InterruptTableLength, add 4 bytes for each additional + * interrupt. Note: at least one interrupt is required and is + * included in the minimum descriptor size (reason for the -1) + */ + ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32); + + /* Add the size of the optional ResourceSource */ + + ExtraStructBytes += AcpiRsStreamOptionLength ( + ResourceLength - ExtraStructBytes, MinimumAmlResourceLength); + break; + + case ACPI_RESOURCE_NAME_GPIO: + + /* Vendor data is optional */ + + if (AmlResource->Gpio.VendorLength) + { + ExtraStructBytes += AmlResource->Gpio.VendorOffset - + AmlResource->Gpio.PinTableOffset + AmlResource->Gpio.VendorLength; + } + else + { + ExtraStructBytes += AmlResource->LargeHeader.ResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER) - + AmlResource->Gpio.PinTableOffset; + } + break; + + case ACPI_RESOURCE_NAME_SERIAL_BUS: + + MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ + AmlResource->CommonSerialBus.Type]; + ExtraStructBytes += AmlResource->CommonSerialBus.ResourceLength - + MinimumAmlResourceLength; + break; + + default: + break; + } + + /* + * Update the required buffer size for the internal descriptor structs + * + * Important: Round the size up for the appropriate alignment. This + * is a requirement on IA64. + */ + if (AcpiUtGetResourceType (AmlBuffer) == ACPI_RESOURCE_NAME_SERIAL_BUS) + { + BufferSize = AcpiGbl_ResourceStructSerialBusSizes[ + AmlResource->CommonSerialBus.Type] + ExtraStructBytes; + } + else + { + BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] + + ExtraStructBytes; + } + BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize); + + *SizeNeeded += BufferSize; + + ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + AcpiUtGetResourceType (AmlBuffer), + AcpiUtGetDescriptorLength (AmlBuffer), BufferSize)); + + /* + * Point to the next resource within the AML stream using the length + * contained in the resource descriptor header + */ + AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer); + } + + /* Did not find an EndTag resource descriptor */ + + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetPciRoutingTableLength + * + * PARAMETERS: PackageObject - Pointer to the package object + * BufferSizeNeeded - UINT32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status + * + * DESCRIPTION: Given a package representing a PCI routing table, this + * calculates the size of the corresponding linked list of + * descriptions. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetPciRoutingTableLength ( + ACPI_OPERAND_OBJECT *PackageObject, + ACPI_SIZE *BufferSizeNeeded) +{ + UINT32 NumberOfElements; + ACPI_SIZE TempSizeNeeded = 0; + ACPI_OPERAND_OBJECT **TopObjectList; + UINT32 Index; + ACPI_OPERAND_OBJECT *PackageElement; + ACPI_OPERAND_OBJECT **SubObjectList; + BOOLEAN NameFound; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength); + + + NumberOfElements = PackageObject->Package.Count; + + /* + * Calculate the size of the return buffer. + * The base size is the number of elements * the sizes of the + * structures. Additional space for the strings is added below. + * The minus one is to subtract the size of the UINT8 Source[1] + * member because it is added below. + * + * But each PRT_ENTRY structure has a pointer to a string and + * the size of that string must be found. + */ + TopObjectList = PackageObject->Package.Elements; + + for (Index = 0; Index < NumberOfElements; Index++) + { + /* Dereference the sub-package */ + + PackageElement = *TopObjectList; + + /* We must have a valid Package object */ + + if (!PackageElement || + (PackageElement->Common.Type != ACPI_TYPE_PACKAGE)) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * The SubObjectList will now point to an array of the + * four IRQ elements: Address, Pin, Source and SourceIndex + */ + SubObjectList = PackageElement->Package.Elements; + + /* Scan the IrqTableElements for the Source Name String */ + + NameFound = FALSE; + + for (TableIndex = 0; TableIndex < 4 && !NameFound; TableIndex++) + { + if (*SubObjectList && /* Null object allowed */ + + ((ACPI_TYPE_STRING == + (*SubObjectList)->Common.Type) || + + ((ACPI_TYPE_LOCAL_REFERENCE == + (*SubObjectList)->Common.Type) && + + ((*SubObjectList)->Reference.Class == + ACPI_REFCLASS_NAME)))) + { + NameFound = TRUE; + } + else + { + /* Look at the next element */ + + SubObjectList++; + } + } + + TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); + + /* Was a String type found? */ + + if (NameFound) + { + if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING) + { + /* + * The length String.Length field does not include the + * terminating NULL, add 1 + */ + TempSizeNeeded += ((ACPI_SIZE) + (*SubObjectList)->String.Length + 1); + } + else + { + TempSizeNeeded += AcpiNsGetPathnameLength ( + (*SubObjectList)->Reference.Node); + } + } + else + { + /* + * If no name was found, then this is a NULL, which is + * translated as a UINT32 zero. + */ + TempSizeNeeded += sizeof (UINT32); + } + + /* Round up the size since each element must be aligned */ + + TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded); + + /* Point to the next ACPI_OPERAND_OBJECT */ + + TopObjectList++; + } + + /* + * Add an extra element to the end of the list, essentially a + * NULL terminator + */ + *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE); + return_ACPI_STATUS (AE_OK); +} diff --git a/source/components/resources/rscreate.c b/source/components/resources/rscreate.c new file mode 100644 index 000000000000..f06ea0cb4dc2 --- /dev/null +++ b/source/components/resources/rscreate.c @@ -0,0 +1,534 @@ +/******************************************************************************* + * + * Module Name: rscreate - Create resource lists/tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSCREATE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rscreate") + + +/******************************************************************************* + * + * FUNCTION: AcpiBufferToResource + * + * PARAMETERS: AmlBuffer - Pointer to the resource byte stream + * AmlBufferLength - Length of the AmlBuffer + * ResourcePtr - Where the converted resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a raw AML buffer to a resource list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiBufferToResource ( + UINT8 *AmlBuffer, + UINT16 AmlBufferLength, + ACPI_RESOURCE **ResourcePtr) +{ + ACPI_STATUS Status; + ACPI_SIZE ListSizeNeeded; + void *Resource; + void *CurrentResourcePtr; + + /* + * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag + * is not required here. + */ + + /* Get the required length for the converted resource */ + + Status = AcpiRsGetListLength (AmlBuffer, AmlBufferLength, + &ListSizeNeeded); + if (Status == AE_AML_NO_RESOURCE_END_TAG) + { + Status = AE_OK; + } + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Allocate a buffer for the converted resource */ + + Resource = ACPI_ALLOCATE_ZEROED (ListSizeNeeded); + CurrentResourcePtr = Resource; + if (!Resource) + { + return (AE_NO_MEMORY); + } + + /* Perform the AML-to-Resource conversion */ + + Status = AcpiUtWalkAmlResources (AmlBuffer, AmlBufferLength, + AcpiRsConvertAmlToResources, &CurrentResourcePtr); + if (Status == AE_AML_NO_RESOURCE_END_TAG) + { + Status = AE_OK; + } + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (Resource); + } + else + { + *ResourcePtr = Resource; + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreateResourceList + * + * PARAMETERS: AmlBuffer - Pointer to the resource byte stream + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status: AE_OK if okay, else a valid ACPI_STATUS code + * If OutputBuffer is not large enough, OutputBufferLength + * indicates how large OutputBuffer should be, else it + * indicates how may UINT8 elements of OutputBuffer are valid. + * + * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method + * execution and parses the stream to create a linked list + * of device resources. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsCreateResourceList ( + ACPI_OPERAND_OBJECT *AmlBuffer, + ACPI_BUFFER *OutputBuffer) +{ + + ACPI_STATUS Status; + UINT8 *AmlStart; + ACPI_SIZE ListSizeNeeded = 0; + UINT32 AmlBufferLength; + void *Resource; + + + ACPI_FUNCTION_TRACE (RsCreateResourceList); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlBuffer = %p\n", + AmlBuffer)); + + /* Params already validated, so we don't re-validate here */ + + AmlBufferLength = AmlBuffer->Buffer.Length; + AmlStart = AmlBuffer->Buffer.Pointer; + + /* + * Pass the AmlBuffer into a module that can calculate + * the buffer size needed for the linked list + */ + Status = AcpiRsGetListLength (AmlStart, AmlBufferLength, + &ListSizeNeeded); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", + Status, (UINT32) ListSizeNeeded)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, ListSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Do the conversion */ + + Resource = OutputBuffer->Pointer; + Status = AcpiUtWalkAmlResources (AmlStart, AmlBufferLength, + AcpiRsConvertAmlToResources, &Resource); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreatePciRoutingTable + * + * PARAMETERS: PackageObject - Pointer to an ACPI_OPERAND_OBJECT + * package + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the OutputBuffer is too small, the error will be + * AE_BUFFER_OVERFLOW and OutputBuffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT package and creates a + * linked list of PCI interrupt descriptions + * + * NOTE: It is the caller's responsibility to ensure that the start of the + * output buffer is aligned properly (if necessary). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsCreatePciRoutingTable ( + ACPI_OPERAND_OBJECT *PackageObject, + ACPI_BUFFER *OutputBuffer) +{ + UINT8 *Buffer; + ACPI_OPERAND_OBJECT **TopObjectList; + ACPI_OPERAND_OBJECT **SubObjectList; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_SIZE BufferSizeNeeded = 0; + UINT32 NumberOfElements; + UINT32 Index; + ACPI_PCI_ROUTING_TABLE *UserPrt; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_BUFFER PathBuffer; + + + ACPI_FUNCTION_TRACE (RsCreatePciRoutingTable); + + + /* Params already validated, so we don't re-validate here */ + + /* Get the required buffer length */ + + Status = AcpiRsGetPciRoutingTableLength (PackageObject, + &BufferSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", + (UINT32) BufferSizeNeeded)); + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, BufferSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a + * package that in turn contains an UINT64 Address, a UINT8 Pin, + * a Name, and a UINT8 SourceIndex. + */ + TopObjectList = PackageObject->Package.Elements; + NumberOfElements = PackageObject->Package.Count; + Buffer = OutputBuffer->Pointer; + UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer); + + for (Index = 0; Index < NumberOfElements; Index++) + { + /* + * Point UserPrt past this current structure + * + * NOTE: On the first iteration, UserPrt->Length will + * be zero because we cleared the return buffer earlier + */ + Buffer += UserPrt->Length; + UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer); + + /* + * Fill in the Length field with the information we have at this point. + * The minus four is to subtract the size of the UINT8 Source[4] member + * because it is added below. + */ + UserPrt->Length = (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); + + /* Each element of the top-level package must also be a package */ + + if ((*TopObjectList)->Common.Type != ACPI_TYPE_PACKAGE) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u]) Need sub-package, found %s", + Index, AcpiUtGetObjectTypeName (*TopObjectList))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Each sub-package must be of length 4 */ + + if ((*TopObjectList)->Package.Count != 4) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u]) Need package of length 4, found length %u", + Index, (*TopObjectList)->Package.Count)); + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + + /* + * Dereference the sub-package. + * The SubObjectList will now point to an array of the four IRQ + * elements: [Address, Pin, Source, SourceIndex] + */ + SubObjectList = (*TopObjectList)->Package.Elements; + + /* 1) First subobject: Dereference the PRT.Address */ + + ObjDesc = SubObjectList[0]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "(PRT[%u].Address) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->Address = ObjDesc->Integer.Value; + + /* 2) Second subobject: Dereference the PRT.Pin */ + + ObjDesc = SubObjectList[1]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->Pin = (UINT32) ObjDesc->Integer.Value; + + /* + * If the BIOS has erroneously reversed the _PRT SourceName (index 2) + * and the SourceIndex (index 3), fix it. _PRT is important enough to + * workaround this BIOS error. This also provides compatibility with + * other ACPI implementations. + */ + ObjDesc = SubObjectList[3]; + if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) + { + SubObjectList[3] = SubObjectList[2]; + SubObjectList[2] = ObjDesc; + + ACPI_WARNING ((AE_INFO, + "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", + Index)); + } + + /* + * 3) Third subobject: Dereference the PRT.SourceName + * The name may be unresolved (slack mode), so allow a null object + */ + ObjDesc = SubObjectList[2]; + if (ObjDesc) + { + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + + if (ObjDesc->Reference.Class != ACPI_REFCLASS_NAME) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u].Source) Need name, found Reference Class 0x%X", + Index, ObjDesc->Reference.Class)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + Node = ObjDesc->Reference.Node; + + /* Use *remaining* length of the buffer as max for pathname */ + + PathBuffer.Length = OutputBuffer->Length - + (UINT32) ((UINT8 *) UserPrt->Source - + (UINT8 *) OutputBuffer->Pointer); + PathBuffer.Pointer = UserPrt->Source; + + Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, &PathBuffer); + + /* +1 to include null terminator */ + + UserPrt->Length += (UINT32) ACPI_STRLEN (UserPrt->Source) + 1; + break; + + + case ACPI_TYPE_STRING: + + ACPI_STRCPY (UserPrt->Source, ObjDesc->String.Pointer); + + /* + * Add to the Length field the length of the string + * (add 1 for terminator) + */ + UserPrt->Length += ObjDesc->String.Length + 1; + break; + + + case ACPI_TYPE_INTEGER: + /* + * If this is a number, then the Source Name is NULL, since the + * entire buffer was zeroed out, we can leave this alone. + * + * Add to the Length field the length of the UINT32 NULL + */ + UserPrt->Length += sizeof (UINT32); + break; + + + default: + + ACPI_ERROR ((AE_INFO, + "(PRT[%u].Source) Need Ref/String/Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + } + + /* Now align the current length */ + + UserPrt->Length = (UINT32) ACPI_ROUND_UP_TO_64BIT (UserPrt->Length); + + /* 4) Fourth subobject: Dereference the PRT.SourceIndex */ + + ObjDesc = SubObjectList[3]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u].SourceIndex) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->SourceIndex = (UINT32) ObjDesc->Integer.Value; + + /* Point to the next ACPI_OPERAND_OBJECT in the top level package */ + + TopObjectList++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreateAmlResources + * + * PARAMETERS: LinkedListBuffer - Pointer to the resource linked list + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the OutputBuffer is too small, the error will be + * AE_BUFFER_OVERFLOW and OutputBuffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the linked list of device resources and + * creates a bytestream to be used as input for the + * _SRS control method. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsCreateAmlResources ( + ACPI_RESOURCE *LinkedListBuffer, + ACPI_BUFFER *OutputBuffer) +{ + ACPI_STATUS Status; + ACPI_SIZE AmlSizeNeeded = 0; + + + ACPI_FUNCTION_TRACE (RsCreateAmlResources); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "LinkedListBuffer = %p\n", + LinkedListBuffer)); + + /* + * Params already validated, so we don't re-validate here + * + * Pass the LinkedListBuffer into a module that calculates + * the buffer size needed for the byte stream. + */ + Status = AcpiRsGetAmlLength (LinkedListBuffer, + &AmlSizeNeeded); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", + (UINT32) AmlSizeNeeded, AcpiFormatException (Status))); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, AmlSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Do the conversion */ + + Status = AcpiRsConvertResourcesToAml (LinkedListBuffer, AmlSizeNeeded, + OutputBuffer->Pointer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + diff --git a/source/components/resources/rsdump.c b/source/components/resources/rsdump.c new file mode 100644 index 000000000000..68564739eb5e --- /dev/null +++ b/source/components/resources/rsdump.c @@ -0,0 +1,946 @@ +/******************************************************************************* + * + * Module Name: rsdump - Functions to display the resource structures. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __RSDUMP_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsdump") + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Local prototypes */ + +static void +AcpiRsOutString ( + char *Title, + char *Value); + +static void +AcpiRsOutInteger8 ( + char *Title, + UINT8 Value); + +static void +AcpiRsOutInteger16 ( + char *Title, + UINT16 Value); + +static void +AcpiRsOutInteger32 ( + char *Title, + UINT32 Value); + +static void +AcpiRsOutInteger64 ( + char *Title, + UINT64 Value); + +static void +AcpiRsOutTitle ( + char *Title); + +static void +AcpiRsDumpByteList ( + UINT16 Length, + UINT8 *Data); + +static void +AcpiRsDumpWordList ( + UINT16 Length, + UINT16 *Data); + +static void +AcpiRsDumpDwordList ( + UINT8 Length, + UINT32 *Data); + +static void +AcpiRsDumpShortByteList ( + UINT8 Length, + UINT8 *Data); + +static void +AcpiRsDumpResourceSource ( + ACPI_RESOURCE_SOURCE *ResourceSource); + +static void +AcpiRsDumpAddressCommon ( + ACPI_RESOURCE_DATA *Resource); + +static void +AcpiRsDumpDescriptor ( + void *Resource, + ACPI_RSDUMP_INFO *Table); + + +#define ACPI_RSD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE_DATA,f) +#define ACPI_PRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_PCI_ROUTING_TABLE,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_RSDUMP_INFO)) + + +/******************************************************************************* + * + * Resource Descriptor info tables + * + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) + * + ******************************************************************************/ + +ACPI_RSDUMP_INFO AcpiRsDumpIrq[7] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIrq), "IRQ", NULL}, + {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.DescriptorLength), "Descriptor Length", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Triggering), "Triggering", AcpiGbl_HeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Polarity), "Polarity", AcpiGbl_LlDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Sharable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.InterruptCount), "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Irq.Interrupts[0]), "Interrupt List", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpDma[6] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpDma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Type), "Speed", AcpiGbl_TypDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Dma.BusMaster), "Mastering", AcpiGbl_BmDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Transfer), "Transfer Type", AcpiGbl_SizDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Dma.ChannelCount), "Channel Count", NULL}, + {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Dma.Channels[0]), "Channel List", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[4] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpStartDpf), "Start-Dependent-Functions",NULL}, + {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (StartDpf.DescriptorLength), "Descriptor Length", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.CompatibilityPriority), "Compatibility Priority", AcpiGbl_ConfigDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.PerformanceRobustness), "Performance/Robustness", AcpiGbl_ConfigDecode} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[1] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndDpf), "End-Dependent-Functions", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpIo[6] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIo), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Io.IoDecode), "Address Decoding", AcpiGbl_IoDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.Alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.AddressLength), "Address Length", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[3] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedIo), "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedIo.Address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedIo.AddressLength), "Address Length", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpVendor[3] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpVendor), "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Vendor.ByteLength), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET (Vendor.ByteData[0]), "Vendor Data", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpEndTag[1] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndTag), "EndTag", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpMemory24[6] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory24), "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory24.WriteProtect), "Write Protect", AcpiGbl_RwDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Alignment), "Alignment", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.AddressLength), "Address Length", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpMemory32[6] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory32), "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Alignment), "Alignment", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.AddressLength), "Address Length", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[4] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedMemory32), "32-Bit Fixed Memory Range",NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (FixedMemory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.Address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.AddressLength), "Address Length", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpAddress16[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress16), "16-Bit WORD Address Space",NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.TranslationOffset), "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.AddressLength), "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address16.ResourceSource), NULL, NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpAddress32[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress32), "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.TranslationOffset), "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.AddressLength), "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address32.ResourceSource), NULL, NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpAddress64[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress64), "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.TranslationOffset), "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.AddressLength), "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address64.ResourceSource), NULL, NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtAddress64), "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TranslationOffset), "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.AddressLength), "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TypeSpecific), "Type-Specific Attribute", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtIrq), "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.ProducerConsumer), "Type", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Triggering), "Triggering", AcpiGbl_HeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Polarity), "Polarity", AcpiGbl_LlDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Sharable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ExtendedIrq.ResourceSource), NULL, NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ExtendedIrq.InterruptCount), "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST,ACPI_RSD_OFFSET (ExtendedIrq.Interrupts[0]), "Interrupt List", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[6] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGenericReg), "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.SpaceId), "Space ID", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitWidth), "Bit Width", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitOffset), "Bit Offset", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.AccessSize), "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (GenericReg.Address), "Address", NULL} +}; + +ACPI_RSDUMP_INFO AcpiRsDumpGpio[16] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGpio), "GPIO", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.ConnectionType), "ConnectionType", AcpiGbl_CtDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.PinConfig), "PinConfig", AcpiGbl_PpcDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Sharable), "Sharable", AcpiGbl_ShrDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.IoRestriction), "IoRestriction", AcpiGbl_IorDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.Triggering), "Triggering", AcpiGbl_HeDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Polarity), "Polarity", AcpiGbl_LlDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DriveStrength), "DriveStrength", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DebounceTimeout), "DebounceTimeout", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Gpio.ResourceSource), "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.PinTableLength), "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (Gpio.PinTable), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Gpio.VendorData), "VendorData", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[4] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedDma), "FixedDma", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.RequestLines), "RequestLines", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.Channels), "Channels", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedDma.Width), "TransferWidth", AcpiGbl_DtsDecode}, +}; + +#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.RevisionId), "RevisionId", NULL}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.Type), "Type", AcpiGbl_SbtDecode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.TypeRevisionId), "TypeRevisionId", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.TypeDataLength), "TypeDataLength", NULL}, \ + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (CommonSerialBus.ResourceSource), "ResourceSource", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.VendorLength), "VendorLength", NULL}, \ + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (CommonSerialBus.VendorData), "VendorData", NULL}, + +ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[10] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS +}; + +ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[13] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpI2cSerialBus), "I2C Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (I2cSerialBus.AccessMode), "AccessMode", AcpiGbl_AmDecode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (I2cSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (I2cSerialBus.SlaveAddress), "SlaveAddress", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[17] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpSpiSerialBus), "Spi Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.WireMode), "WireMode", AcpiGbl_WmDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.DevicePolarity), "DevicePolarity", AcpiGbl_DpDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.DataBitLength), "DataBitLength", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPhase), "ClockPhase", AcpiGbl_CphDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPolarity), "ClockPolarity", AcpiGbl_CpoDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (SpiSerialBus.DeviceSelection), "DeviceSelection", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (SpiSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[19] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpUartSerialBus), "Uart Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.FlowControl), "FlowControl", AcpiGbl_FcDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.StopBits), "StopBits", AcpiGbl_SbDecode}, + {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.DataBits), "DataBits", AcpiGbl_BpbDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.Endian), "Endian", AcpiGbl_EdDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.Parity), "Parity", AcpiGbl_PtDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.LinesEnabled), "LinesEnabled", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.RxFifoSize), "RxFifoSize", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.TxFifoSize), "TxFifoSize", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (UartSerialBus.DefaultBaudRate), "ConnectionSpeed", NULL}, +}; + +/* + * Tables used for common address descriptor flag fields + */ +static ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[5] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGeneralFlags), NULL, NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.ProducerConsumer), "Consumer/Producer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Decode), "Address Decode", AcpiGbl_DecDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MinAddressFixed), "Min Relocatability", AcpiGbl_MinDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MaxAddressFixed), "Max Relocatability", AcpiGbl_MaxDecode} +}; + +static ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[5] = +{ + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemoryFlags), "Resource Type", (void *) "Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.WriteProtect), "Write Protect", AcpiGbl_RwDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Caching), "Caching", AcpiGbl_MemDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.RangeType), "Range Type", AcpiGbl_MtpDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Translation), "Translation", AcpiGbl_TtpDecode} +}; + +static ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[4] = +{ + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIoFlags), "Resource Type", (void *) "I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.RangeType), "Range Type", AcpiGbl_RngDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.Translation), "Translation", AcpiGbl_TtpDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.TranslationType), "Translation Type", AcpiGbl_TrsDecode} +}; + + +/* + * Table used to dump _PRT contents + */ +static ACPI_RSDUMP_INFO AcpiRsDumpPrt[5] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPrt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET (Address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (Pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET (Source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (SourceIndex), "Source Index", NULL} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpDescriptor + * + * PARAMETERS: Resource + * + * RETURN: None + * + * DESCRIPTION: + * + ******************************************************************************/ + +static void +AcpiRsDumpDescriptor ( + void *Resource, + ACPI_RSDUMP_INFO *Table) +{ + UINT8 *Target = NULL; + UINT8 *PreviousTarget; + char *Name; + UINT8 Count; + + + /* First table entry must contain the table length (# of table entries) */ + + Count = Table->Offset; + + while (Count) + { + PreviousTarget = Target; + Target = ACPI_ADD_PTR (UINT8, Resource, Table->Offset); + Name = Table->Name; + + switch (Table->Opcode) + { + case ACPI_RSD_TITLE: + /* + * Optional resource title + */ + if (Table->Name) + { + AcpiOsPrintf ("%s Resource\n", Name); + } + break; + + /* Strings */ + + case ACPI_RSD_LITERAL: + AcpiRsOutString (Name, ACPI_CAST_PTR (char, Table->Pointer)); + break; + + case ACPI_RSD_STRING: + AcpiRsOutString (Name, ACPI_CAST_PTR (char, Target)); + break; + + /* Data items, 8/16/32/64 bit */ + + case ACPI_RSD_UINT8: + if (Table->Pointer) + { + AcpiRsOutString (Name, ACPI_CAST_PTR (char, + Table->Pointer [*Target])); + } + else + { + AcpiRsOutInteger8 (Name, ACPI_GET8 (Target)); + } + break; + + case ACPI_RSD_UINT16: + AcpiRsOutInteger16 (Name, ACPI_GET16 (Target)); + break; + + case ACPI_RSD_UINT32: + AcpiRsOutInteger32 (Name, ACPI_GET32 (Target)); + break; + + case ACPI_RSD_UINT64: + AcpiRsOutInteger64 (Name, ACPI_GET64 (Target)); + break; + + /* Flags: 1-bit and 2-bit flags supported */ + + case ACPI_RSD_1BITFLAG: + AcpiRsOutString (Name, ACPI_CAST_PTR (char, + Table->Pointer [*Target & 0x01])); + break; + + case ACPI_RSD_2BITFLAG: + AcpiRsOutString (Name, ACPI_CAST_PTR (char, + Table->Pointer [*Target & 0x03])); + break; + + case ACPI_RSD_3BITFLAG: + AcpiRsOutString (Name, ACPI_CAST_PTR (char, + Table->Pointer [*Target & 0x07])); + break; + + case ACPI_RSD_SHORTLIST: + /* + * Short byte list (single line output) for DMA and IRQ resources + * Note: The list length is obtained from the previous table entry + */ + if (PreviousTarget) + { + AcpiRsOutTitle (Name); + AcpiRsDumpShortByteList (*PreviousTarget, Target); + } + break; + + case ACPI_RSD_SHORTLISTX: + /* + * Short byte list (single line output) for GPIO vendor data + * Note: The list length is obtained from the previous table entry + */ + if (PreviousTarget) + { + AcpiRsOutTitle (Name); + AcpiRsDumpShortByteList (*PreviousTarget, + *(ACPI_CAST_INDIRECT_PTR (UINT8, Target))); + } + break; + + case ACPI_RSD_LONGLIST: + /* + * Long byte list for Vendor resource data + * Note: The list length is obtained from the previous table entry + */ + if (PreviousTarget) + { + AcpiRsDumpByteList (ACPI_GET16 (PreviousTarget), Target); + } + break; + + case ACPI_RSD_DWORDLIST: + /* + * Dword list for Extended Interrupt resources + * Note: The list length is obtained from the previous table entry + */ + if (PreviousTarget) + { + AcpiRsDumpDwordList (*PreviousTarget, + ACPI_CAST_PTR (UINT32, Target)); + } + break; + + case ACPI_RSD_WORDLIST: + /* + * Word list for GPIO Pin Table + * Note: The list length is obtained from the previous table entry + */ + if (PreviousTarget) + { + AcpiRsDumpWordList (*PreviousTarget, + *(ACPI_CAST_INDIRECT_PTR (UINT16, Target))); + } + break; + + case ACPI_RSD_ADDRESS: + /* + * Common flags for all Address resources + */ + AcpiRsDumpAddressCommon (ACPI_CAST_PTR (ACPI_RESOURCE_DATA, Target)); + break; + + case ACPI_RSD_SOURCE: + /* + * Optional ResourceSource for Address resources + */ + AcpiRsDumpResourceSource (ACPI_CAST_PTR (ACPI_RESOURCE_SOURCE, Target)); + break; + + default: + AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n", + Table->Opcode); + return; + } + + Table++; + Count--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpResourceSource + * + * PARAMETERS: ResourceSource - Pointer to a Resource Source struct + * + * RETURN: None + * + * DESCRIPTION: Common routine for dumping the optional ResourceSource and the + * corresponding ResourceSourceIndex. + * + ******************************************************************************/ + +static void +AcpiRsDumpResourceSource ( + ACPI_RESOURCE_SOURCE *ResourceSource) +{ + ACPI_FUNCTION_ENTRY (); + + + if (ResourceSource->Index == 0xFF) + { + return; + } + + AcpiRsOutInteger8 ("Resource Source Index", + ResourceSource->Index); + + AcpiRsOutString ("Resource Source", + ResourceSource->StringPtr ? + ResourceSource->StringPtr : "[Not Specified]"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpAddressCommon + * + * PARAMETERS: Resource - Pointer to an internal resource descriptor + * + * RETURN: None + * + * DESCRIPTION: Dump the fields that are common to all Address resource + * descriptors + * + ******************************************************************************/ + +static void +AcpiRsDumpAddressCommon ( + ACPI_RESOURCE_DATA *Resource) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Decode the type-specific flags */ + + switch (Resource->Address.ResourceType) + { + case ACPI_MEMORY_RANGE: + + AcpiRsDumpDescriptor (Resource, AcpiRsDumpMemoryFlags); + break; + + case ACPI_IO_RANGE: + + AcpiRsDumpDescriptor (Resource, AcpiRsDumpIoFlags); + break; + + case ACPI_BUS_NUMBER_RANGE: + + AcpiRsOutString ("Resource Type", "Bus Number Range"); + break; + + default: + + AcpiRsOutInteger8 ("Resource Type", + (UINT8) Resource->Address.ResourceType); + break; + } + + /* Decode the general flags */ + + AcpiRsDumpDescriptor (Resource, AcpiRsDumpGeneralFlags); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpResourceList + * + * PARAMETERS: ResourceList - Pointer to a resource descriptor list + * + * RETURN: None + * + * DESCRIPTION: Dispatches the structure to the correct dump routine. + * + ******************************************************************************/ + +void +AcpiRsDumpResourceList ( + ACPI_RESOURCE *ResourceList) +{ + UINT32 Count = 0; + UINT32 Type; + + + ACPI_FUNCTION_ENTRY (); + + + if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer)) + { + return; + } + + /* Walk list and dump all resource descriptors (END_TAG terminates) */ + + do + { + AcpiOsPrintf ("\n[%02X] ", Count); + Count++; + + /* Validate Type before dispatch */ + + Type = ResourceList->Type; + if (Type > ACPI_RESOURCE_TYPE_MAX) + { + AcpiOsPrintf ( + "Invalid descriptor type (%X) in resource list\n", + ResourceList->Type); + return; + } + + /* Dump the resource descriptor */ + + if (Type == ACPI_RESOURCE_TYPE_SERIAL_BUS) + { + AcpiRsDumpDescriptor (&ResourceList->Data, + AcpiGbl_DumpSerialBusDispatch[ResourceList->Data.CommonSerialBus.Type]); + } + else + { + AcpiRsDumpDescriptor (&ResourceList->Data, + AcpiGbl_DumpResourceDispatch[Type]); + } + + /* Point to the next resource structure */ + + ResourceList = ACPI_NEXT_RESOURCE (ResourceList); + + /* Exit when END_TAG descriptor is reached */ + + } while (Type != ACPI_RESOURCE_TYPE_END_TAG); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpIrqList + * + * PARAMETERS: RouteTable - Pointer to the routing table to dump. + * + * RETURN: None + * + * DESCRIPTION: Print IRQ routing table + * + ******************************************************************************/ + +void +AcpiRsDumpIrqList ( + UINT8 *RouteTable) +{ + ACPI_PCI_ROUTING_TABLE *PrtElement; + UINT8 Count; + + + ACPI_FUNCTION_ENTRY (); + + + if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer)) + { + return; + } + + PrtElement = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, RouteTable); + + /* Dump all table elements, Exit on zero length element */ + + for (Count = 0; PrtElement->Length; Count++) + { + AcpiOsPrintf ("\n[%02X] PCI IRQ Routing Table Package\n", Count); + AcpiRsDumpDescriptor (PrtElement, AcpiRsDumpPrt); + + PrtElement = ACPI_ADD_PTR (ACPI_PCI_ROUTING_TABLE, + PrtElement, PrtElement->Length); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsOut* + * + * PARAMETERS: Title - Name of the resource field + * Value - Value of the resource field + * + * RETURN: None + * + * DESCRIPTION: Miscellaneous helper functions to consistently format the + * output of the resource dump routines + * + ******************************************************************************/ + +static void +AcpiRsOutString ( + char *Title, + char *Value) +{ + AcpiOsPrintf ("%27s : %s", Title, Value); + if (!*Value) + { + AcpiOsPrintf ("[NULL NAMESTRING]"); + } + AcpiOsPrintf ("\n"); +} + +static void +AcpiRsOutInteger8 ( + char *Title, + UINT8 Value) +{ + AcpiOsPrintf ("%27s : %2.2X\n", Title, Value); +} + +static void +AcpiRsOutInteger16 ( + char *Title, + UINT16 Value) +{ + AcpiOsPrintf ("%27s : %4.4X\n", Title, Value); +} + +static void +AcpiRsOutInteger32 ( + char *Title, + UINT32 Value) +{ + AcpiOsPrintf ("%27s : %8.8X\n", Title, Value); +} + +static void +AcpiRsOutInteger64 ( + char *Title, + UINT64 Value) +{ + AcpiOsPrintf ("%27s : %8.8X%8.8X\n", Title, + ACPI_FORMAT_UINT64 (Value)); +} + +static void +AcpiRsOutTitle ( + char *Title) +{ + AcpiOsPrintf ("%27s : ", Title); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDump*List + * + * PARAMETERS: Length - Number of elements in the list + * Data - Start of the list + * + * RETURN: None + * + * DESCRIPTION: Miscellaneous functions to dump lists of raw data + * + ******************************************************************************/ + +static void +AcpiRsDumpByteList ( + UINT16 Length, + UINT8 *Data) +{ + UINT8 i; + + + for (i = 0; i < Length; i++) + { + AcpiOsPrintf ("%25s%2.2X : %2.2X\n", + "Byte", i, Data[i]); + } +} + +static void +AcpiRsDumpShortByteList ( + UINT8 Length, + UINT8 *Data) +{ + UINT8 i; + + + for (i = 0; i < Length; i++) + { + AcpiOsPrintf ("%X ", Data[i]); + } + AcpiOsPrintf ("\n"); +} + +static void +AcpiRsDumpDwordList ( + UINT8 Length, + UINT32 *Data) +{ + UINT8 i; + + + for (i = 0; i < Length; i++) + { + AcpiOsPrintf ("%25s%2.2X : %8.8X\n", + "Dword", i, Data[i]); + } +} + +static void +AcpiRsDumpWordList ( + UINT16 Length, + UINT16 *Data) +{ + UINT16 i; + + + for (i = 0; i < Length; i++) + { + AcpiOsPrintf ("%25s%2.2X : %4.4X\n", + "Word", i, Data[i]); + } +} + +#endif + diff --git a/source/components/resources/rsinfo.c b/source/components/resources/rsinfo.c new file mode 100644 index 000000000000..e7287d54557c --- /dev/null +++ b/source/components/resources/rsinfo.c @@ -0,0 +1,265 @@ +/******************************************************************************* + * + * Module Name: rsinfo - Dispatch and Info tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSINFO_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsinfo") + +/* + * Resource dispatch and information tables. Any new resource types (either + * Large or Small) must be reflected in each of these tables, so they are here + * in one place. + * + * The tables for Large descriptors are indexed by bits 6:0 of the AML + * descriptor type byte. The tables for Small descriptors are indexed by + * bits 6:3 of the descriptor byte. The tables for internal resource + * descriptors are indexed by the ACPI_RESOURCE_TYPE field. + */ + + +/* Dispatch table for resource-to-AML (Set Resource) conversion functions */ + +ACPI_RSCONVERT_INFO *AcpiGbl_SetResourceDispatch[] = +{ + AcpiRsSetIrq, /* 0x00, ACPI_RESOURCE_TYPE_IRQ */ + AcpiRsConvertDma, /* 0x01, ACPI_RESOURCE_TYPE_DMA */ + AcpiRsSetStartDpf, /* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */ + AcpiRsConvertEndDpf, /* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */ + AcpiRsConvertIo, /* 0x04, ACPI_RESOURCE_TYPE_IO */ + AcpiRsConvertFixedIo, /* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */ + AcpiRsSetVendor, /* 0x06, ACPI_RESOURCE_TYPE_VENDOR */ + AcpiRsConvertEndTag, /* 0x07, ACPI_RESOURCE_TYPE_END_TAG */ + AcpiRsConvertMemory24, /* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */ + AcpiRsConvertMemory32, /* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */ + AcpiRsConvertFixedMemory32, /* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + AcpiRsConvertAddress16, /* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */ + AcpiRsConvertAddress32, /* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */ + AcpiRsConvertAddress64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */ + AcpiRsConvertExtAddress64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + AcpiRsConvertExtIrq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + AcpiRsConvertGenericReg, /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ + AcpiRsConvertGpio, /* 0x11, ACPI_RESOURCE_TYPE_GPIO */ + AcpiRsConvertFixedDma, /* 0x12, ACPI_RESOURCE_TYPE_FIXED_DMA */ + NULL, /* 0x13, ACPI_RESOURCE_TYPE_SERIAL_BUS - Use subtype table below */ +}; + +/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */ + +ACPI_RSCONVERT_INFO *AcpiGbl_GetResourceDispatch[] = +{ + /* Small descriptors */ + + NULL, /* 0x00, Reserved */ + NULL, /* 0x01, Reserved */ + NULL, /* 0x02, Reserved */ + NULL, /* 0x03, Reserved */ + AcpiRsGetIrq, /* 0x04, ACPI_RESOURCE_NAME_IRQ */ + AcpiRsConvertDma, /* 0x05, ACPI_RESOURCE_NAME_DMA */ + AcpiRsGetStartDpf, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ + AcpiRsConvertEndDpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ + AcpiRsConvertIo, /* 0x08, ACPI_RESOURCE_NAME_IO */ + AcpiRsConvertFixedIo, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */ + AcpiRsConvertFixedDma, /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */ + NULL, /* 0x0B, Reserved */ + NULL, /* 0x0C, Reserved */ + NULL, /* 0x0D, Reserved */ + AcpiRsGetVendorSmall, /* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */ + AcpiRsConvertEndTag, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG */ + + /* Large descriptors */ + + NULL, /* 0x00, Reserved */ + AcpiRsConvertMemory24, /* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */ + AcpiRsConvertGenericReg, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ + NULL, /* 0x03, Reserved */ + AcpiRsGetVendorLarge, /* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */ + AcpiRsConvertMemory32, /* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */ + AcpiRsConvertFixedMemory32, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */ + AcpiRsConvertAddress32, /* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */ + AcpiRsConvertAddress16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */ + AcpiRsConvertExtIrq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */ + AcpiRsConvertAddress64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */ + AcpiRsConvertExtAddress64, /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ + AcpiRsConvertGpio, /* 0x0C, ACPI_RESOURCE_NAME_GPIO */ + NULL, /* 0x0D, Reserved */ + NULL, /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use subtype table below */ +}; + +/* Subtype table for SerialBus -- I2C, SPI, and UART */ + +ACPI_RSCONVERT_INFO *AcpiGbl_ConvertResourceSerialBusDispatch[] = +{ + NULL, + AcpiRsConvertI2cSerialBus, + AcpiRsConvertSpiSerialBus, + AcpiRsConvertUartSerialBus, +}; + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Dispatch table for resource dump functions */ + +ACPI_RSDUMP_INFO *AcpiGbl_DumpResourceDispatch[] = +{ + AcpiRsDumpIrq, /* ACPI_RESOURCE_TYPE_IRQ */ + AcpiRsDumpDma, /* ACPI_RESOURCE_TYPE_DMA */ + AcpiRsDumpStartDpf, /* ACPI_RESOURCE_TYPE_START_DEPENDENT */ + AcpiRsDumpEndDpf, /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + AcpiRsDumpIo, /* ACPI_RESOURCE_TYPE_IO */ + AcpiRsDumpFixedIo, /* ACPI_RESOURCE_TYPE_FIXED_IO */ + AcpiRsDumpVendor, /* ACPI_RESOURCE_TYPE_VENDOR */ + AcpiRsDumpEndTag, /* ACPI_RESOURCE_TYPE_END_TAG */ + AcpiRsDumpMemory24, /* ACPI_RESOURCE_TYPE_MEMORY24 */ + AcpiRsDumpMemory32, /* ACPI_RESOURCE_TYPE_MEMORY32 */ + AcpiRsDumpFixedMemory32, /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + AcpiRsDumpAddress16, /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + AcpiRsDumpAddress32, /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + AcpiRsDumpAddress64, /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + AcpiRsDumpExtAddress64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + AcpiRsDumpExtIrq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + AcpiRsDumpGenericReg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ + AcpiRsDumpGpio, /* ACPI_RESOURCE_TYPE_GPIO */ + AcpiRsDumpFixedDma, /* ACPI_RESOURCE_TYPE_FIXED_DMA */ + NULL, /* ACPI_RESOURCE_TYPE_SERIAL_BUS */ +}; + +ACPI_RSDUMP_INFO *AcpiGbl_DumpSerialBusDispatch[] = +{ + NULL, + AcpiRsDumpI2cSerialBus, /* AML_RESOURCE_I2C_BUS_TYPE */ + AcpiRsDumpSpiSerialBus, /* AML_RESOURCE_SPI_BUS_TYPE */ + AcpiRsDumpUartSerialBus, /* AML_RESOURCE_UART_BUS_TYPE */ +}; +#endif + + +/* + * Base sizes for external AML resource descriptors, indexed by internal type. + * Includes size of the descriptor header (1 byte for small descriptors, + * 3 bytes for large descriptors) + */ +const UINT8 AcpiGbl_AmlResourceSizes[] = +{ + sizeof (AML_RESOURCE_IRQ), /* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */ + sizeof (AML_RESOURCE_DMA), /* ACPI_RESOURCE_TYPE_DMA */ + sizeof (AML_RESOURCE_START_DEPENDENT), /* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */ + sizeof (AML_RESOURCE_END_DEPENDENT), /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + sizeof (AML_RESOURCE_IO), /* ACPI_RESOURCE_TYPE_IO */ + sizeof (AML_RESOURCE_FIXED_IO), /* ACPI_RESOURCE_TYPE_FIXED_IO */ + sizeof (AML_RESOURCE_VENDOR_SMALL), /* ACPI_RESOURCE_TYPE_VENDOR */ + sizeof (AML_RESOURCE_END_TAG), /* ACPI_RESOURCE_TYPE_END_TAG */ + sizeof (AML_RESOURCE_MEMORY24), /* ACPI_RESOURCE_TYPE_MEMORY24 */ + sizeof (AML_RESOURCE_MEMORY32), /* ACPI_RESOURCE_TYPE_MEMORY32 */ + sizeof (AML_RESOURCE_FIXED_MEMORY32), /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + sizeof (AML_RESOURCE_ADDRESS16), /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + sizeof (AML_RESOURCE_ADDRESS32), /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + sizeof (AML_RESOURCE_ADDRESS64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64),/*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + sizeof (AML_RESOURCE_EXTENDED_IRQ), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + sizeof (AML_RESOURCE_GENERIC_REGISTER), /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ + sizeof (AML_RESOURCE_GPIO), /* ACPI_RESOURCE_TYPE_GPIO */ + sizeof (AML_RESOURCE_FIXED_DMA), /* ACPI_RESOURCE_TYPE_FIXED_DMA */ + sizeof (AML_RESOURCE_COMMON_SERIALBUS), /* ACPI_RESOURCE_TYPE_SERIAL_BUS */ +}; + + +const UINT8 AcpiGbl_ResourceStructSizes[] = +{ + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_RS_SIZE (ACPI_RESOURCE_IRQ), + ACPI_RS_SIZE (ACPI_RESOURCE_DMA), + ACPI_RS_SIZE (ACPI_RESOURCE_START_DEPENDENT), + ACPI_RS_SIZE_MIN, + ACPI_RS_SIZE (ACPI_RESOURCE_IO), + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_IO), + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_DMA), + 0, + 0, + 0, + ACPI_RS_SIZE (ACPI_RESOURCE_VENDOR), + ACPI_RS_SIZE_MIN, + + /* Large descriptors */ + + 0, + ACPI_RS_SIZE (ACPI_RESOURCE_MEMORY24), + ACPI_RS_SIZE (ACPI_RESOURCE_GENERIC_REGISTER), + 0, + ACPI_RS_SIZE (ACPI_RESOURCE_VENDOR), + ACPI_RS_SIZE (ACPI_RESOURCE_MEMORY32), + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_MEMORY32), + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS32), + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS16), + ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_IRQ), + ACPI_RS_SIZE (ACPI_RESOURCE_ADDRESS64), + ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_ADDRESS64), + ACPI_RS_SIZE (ACPI_RESOURCE_GPIO), + ACPI_RS_SIZE (ACPI_RESOURCE_COMMON_SERIALBUS) +}; + +const UINT8 AcpiGbl_AmlResourceSerialBusSizes[] = +{ + 0, + sizeof (AML_RESOURCE_I2C_SERIALBUS), + sizeof (AML_RESOURCE_SPI_SERIALBUS), + sizeof (AML_RESOURCE_UART_SERIALBUS), +}; + +const UINT8 AcpiGbl_ResourceStructSerialBusSizes[] = +{ + 0, + ACPI_RS_SIZE (ACPI_RESOURCE_I2C_SERIALBUS), + ACPI_RS_SIZE (ACPI_RESOURCE_SPI_SERIALBUS), + ACPI_RS_SIZE (ACPI_RESOURCE_UART_SERIALBUS), +}; diff --git a/source/components/resources/rsio.c b/source/components/resources/rsio.c new file mode 100644 index 000000000000..065108cfa1f7 --- /dev/null +++ b/source/components/resources/rsio.c @@ -0,0 +1,304 @@ +/******************************************************************************* + * + * Module Name: rsio - IO and DMA resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSIO_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsio") + + +/******************************************************************************* + * + * AcpiRsConvertIo + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertIo[5] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO, + ACPI_RS_SIZE (ACPI_RESOURCE_IO), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertIo)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO, + sizeof (AML_RESOURCE_IO), + 0}, + + /* Decode flag */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Io.IoDecode), + AML_OFFSET (Io.Flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Alignment + * Length + * Minimum Base Address + * Maximum Base Address + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Io.Alignment), + AML_OFFSET (Io.Alignment), + 2}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.Io.Minimum), + AML_OFFSET (Io.Minimum), + 2} +}; + + +/******************************************************************************* + * + * AcpiRsConvertFixedIo + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertFixedIo[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO, + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_IO), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertFixedIo)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO, + sizeof (AML_RESOURCE_FIXED_IO), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Base Address + * Length + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.FixedIo.AddressLength), + AML_OFFSET (FixedIo.AddressLength), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.FixedIo.Address), + AML_OFFSET (FixedIo.Address), + 1} +}; + + +/******************************************************************************* + * + * AcpiRsConvertGenericReg + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertGenericReg[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER, + ACPI_RS_SIZE (ACPI_RESOURCE_GENERIC_REGISTER), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertGenericReg)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER, + sizeof (AML_RESOURCE_GENERIC_REGISTER), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Space ID + * Register Bit Width + * Register Bit Offset + * Access Size + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.GenericReg.SpaceId), + AML_OFFSET (GenericReg.AddressSpaceId), + 4}, + + /* Get the Register Address */ + + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET (Data.GenericReg.Address), + AML_OFFSET (GenericReg.Address), + 1} +}; + + +/******************************************************************************* + * + * AcpiRsConvertEndDpf + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertEndDpf[2] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE (AcpiRsConvertEndDpf)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT, + sizeof (AML_RESOURCE_END_DEPENDENT), + 0} +}; + + +/******************************************************************************* + * + * AcpiRsConvertEndTag + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertEndTag[2] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE (AcpiRsConvertEndTag)}, + + /* + * Note: The checksum field is set to zero, meaning that the resource + * data is treated as if the checksum operation succeeded. + * (ACPI Spec 1.0b Section 6.4.2.8) + */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG, + sizeof (AML_RESOURCE_END_TAG), + 0} +}; + + +/******************************************************************************* + * + * AcpiRsGetStartDpf + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsGetStartDpf[6] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, + ACPI_RS_SIZE (ACPI_RESOURCE_START_DEPENDENT), + ACPI_RSC_TABLE_SIZE (AcpiRsGetStartDpf)}, + + /* Defaults for Compatibility and Performance priorities */ + + {ACPI_RSC_SET8, ACPI_RS_OFFSET (Data.StartDpf.CompatibilityPriority), + ACPI_ACCEPTABLE_CONFIGURATION, + 2}, + + /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.StartDpf.DescriptorLength), + AML_OFFSET (StartDpf.DescriptorType), + 0}, + + /* All done if there is no flag byte present in the descriptor */ + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, + + /* Flag byte is present, get the flags */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.StartDpf.CompatibilityPriority), + AML_OFFSET (StartDpf.Flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.StartDpf.PerformanceRobustness), + AML_OFFSET (StartDpf.Flags), + 2} +}; + + +/******************************************************************************* + * + * AcpiRsSetStartDpf + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsSetStartDpf[10] = +{ + /* Start with a default descriptor of length 1 */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, + sizeof (AML_RESOURCE_START_DEPENDENT), + ACPI_RSC_TABLE_SIZE (AcpiRsSetStartDpf)}, + + /* Set the default flag values */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.StartDpf.CompatibilityPriority), + AML_OFFSET (StartDpf.Flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.StartDpf.PerformanceRobustness), + AML_OFFSET (StartDpf.Flags), + 2}, + /* + * All done if the output descriptor length is required to be 1 + * (i.e., optimization to 0 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(Data.StartDpf.DescriptorLength), + 1}, + + /* Set length to 0 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_START_DEPENDENT_NOPRIO)}, + + /* + * All done if the output descriptor length is required to be 0. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 0-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(Data.StartDpf.DescriptorLength), + 0}, + + /* Reset length to 1 byte (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_START_DEPENDENT)}, + + + /* + * All done if flags byte is necessary -- if either priority value + * is not ACPI_ACCEPTABLE_CONFIGURATION + */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET (Data.StartDpf.CompatibilityPriority), + ACPI_ACCEPTABLE_CONFIGURATION}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET (Data.StartDpf.PerformanceRobustness), + ACPI_ACCEPTABLE_CONFIGURATION}, + + /* Flag byte is not necessary */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_START_DEPENDENT_NOPRIO)} +}; + + diff --git a/source/components/resources/rsirq.c b/source/components/resources/rsirq.c new file mode 100644 index 000000000000..c2a88ee89a14 --- /dev/null +++ b/source/components/resources/rsirq.c @@ -0,0 +1,308 @@ +/******************************************************************************* + * + * Module Name: rsirq - IRQ resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSIRQ_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsirq") + + +/******************************************************************************* + * + * AcpiRsGetIrq + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, + ACPI_RS_SIZE (ACPI_RESOURCE_IRQ), + ACPI_RSC_TABLE_SIZE (AcpiRsGetIrq)}, + + /* Get the IRQ mask (bytes 1:2) */ + + {ACPI_RSC_BITMASK16,ACPI_RS_OFFSET (Data.Irq.Interrupts[0]), + AML_OFFSET (Irq.IrqMask), + ACPI_RS_OFFSET (Data.Irq.InterruptCount)}, + + /* Set default flags (others are zero) */ + + {ACPI_RSC_SET8, ACPI_RS_OFFSET (Data.Irq.Triggering), + ACPI_EDGE_SENSITIVE, + 1}, + + /* Get the descriptor length (2 or 3 for IRQ descriptor) */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Irq.DescriptorLength), + AML_OFFSET (Irq.DescriptorType), + 0}, + + /* All done if no flag byte present in descriptor */ + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, + + /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering), + AML_OFFSET (Irq.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Polarity), + AML_OFFSET (Irq.Flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Sharable), + AML_OFFSET (Irq.Flags), + 4} +}; + + +/******************************************************************************* + * + * AcpiRsSetIrq + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] = +{ + /* Start with a default descriptor of length 3 */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, + sizeof (AML_RESOURCE_IRQ), + ACPI_RSC_TABLE_SIZE (AcpiRsSetIrq)}, + + /* Convert interrupt list to 16-bit IRQ bitmask */ + + {ACPI_RSC_BITMASK16,ACPI_RS_OFFSET (Data.Irq.Interrupts[0]), + AML_OFFSET (Irq.IrqMask), + ACPI_RS_OFFSET (Data.Irq.InterruptCount)}, + + /* Set the flags byte */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering), + AML_OFFSET (Irq.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Polarity), + AML_OFFSET (Irq.Flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Sharable), + AML_OFFSET (Irq.Flags), + 4}, + + /* + * All done if the output descriptor length is required to be 3 + * (i.e., optimization to 2 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(Data.Irq.DescriptorLength), + 3}, + + /* Set length to 2 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_IRQ_NOFLAGS)}, + + /* + * All done if the output descriptor length is required to be 2. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 2-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(Data.Irq.DescriptorLength), + 2}, + + /* Reset length to 3 bytes (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_IRQ)}, + + /* + * Check if the flags byte is necessary. Not needed if the flags are: + * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE + */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET (Data.Irq.Triggering), + ACPI_EDGE_SENSITIVE}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET (Data.Irq.Polarity), + ACPI_ACTIVE_HIGH}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET (Data.Irq.Sharable), + ACPI_EXCLUSIVE}, + + /* We can optimize to a 2-byte IrqNoFlags() descriptor */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof (AML_RESOURCE_IRQ_NOFLAGS)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertExtIrq + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, + ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_IRQ), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertExtIrq)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ, + sizeof (AML_RESOURCE_EXTENDED_IRQ), + 0}, + + /* Flag bits */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.ProducerConsumer), + AML_OFFSET (ExtendedIrq.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.Triggering), + AML_OFFSET (ExtendedIrq.Flags), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.Polarity), + AML_OFFSET (ExtendedIrq.Flags), + 2}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.Sharable), + AML_OFFSET (ExtendedIrq.Flags), + 3}, + + /* IRQ Table length (Byte4) */ + + {ACPI_RSC_COUNT, ACPI_RS_OFFSET (Data.ExtendedIrq.InterruptCount), + AML_OFFSET (ExtendedIrq.InterruptCount), + sizeof (UINT32)}, + + /* Copy every IRQ in the table, each is 32 bits */ + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.ExtendedIrq.Interrupts[0]), + AML_OFFSET (ExtendedIrq.Interrupts[0]), + 0}, + + /* Optional ResourceSource (Index and String) */ + + {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET (Data.ExtendedIrq.ResourceSource), + ACPI_RS_OFFSET (Data.ExtendedIrq.Interrupts[0]), + sizeof (AML_RESOURCE_EXTENDED_IRQ)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertDma + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertDma[6] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA, + ACPI_RS_SIZE (ACPI_RESOURCE_DMA), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertDma)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA, + sizeof (AML_RESOURCE_DMA), + 0}, + + /* Flags: transfer preference, bus mastering, channel speed */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Dma.Transfer), + AML_OFFSET (Dma.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Dma.BusMaster), + AML_OFFSET (Dma.Flags), + 2}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Dma.Type), + AML_OFFSET (Dma.Flags), + 5}, + + /* DMA channel mask bits */ + + {ACPI_RSC_BITMASK, ACPI_RS_OFFSET (Data.Dma.Channels[0]), + AML_OFFSET (Dma.DmaChannelMask), + ACPI_RS_OFFSET (Data.Dma.ChannelCount)} +}; + + +/******************************************************************************* + * + * AcpiRsConvertFixedDma + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_DMA, + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_DMA), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertFixedDma)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_DMA, + sizeof (AML_RESOURCE_FIXED_DMA), + 0}, + + /* + * These fields are contiguous in both the source and destination: + * RequestLines + * Channels + */ + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.FixedDma.RequestLines), + AML_OFFSET (FixedDma.RequestLines), + 2}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.FixedDma.Width), + AML_OFFSET (FixedDma.Width), + 1}, + +}; diff --git a/source/components/resources/rslist.c b/source/components/resources/rslist.c new file mode 100644 index 000000000000..187d56cd42b2 --- /dev/null +++ b/source/components/resources/rslist.c @@ -0,0 +1,275 @@ +/******************************************************************************* + * + * Module Name: rslist - Linked list utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSLIST_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rslist") + + +/******************************************************************************* + * + * FUNCTION: AcpiRsConvertAmlToResources + * + * PARAMETERS: ACPI_WALK_AML_CALLBACK + * ResourcePtr - Pointer to the buffer that will + * contain the output structures + * + * RETURN: Status + * + * DESCRIPTION: Convert an AML resource to an internal representation of the + * resource that is aligned and easier to access. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsConvertAmlToResources ( + UINT8 *Aml, + UINT32 Length, + UINT32 Offset, + UINT8 ResourceIndex, + void *Context) +{ + ACPI_RESOURCE **ResourcePtr = ACPI_CAST_INDIRECT_PTR ( + ACPI_RESOURCE, Context); + ACPI_RESOURCE *Resource; + AML_RESOURCE *AmlResource; + ACPI_RSCONVERT_INFO *ConversionTable; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsConvertAmlToResources); + + + /* + * Check that the input buffer and all subsequent pointers into it + * are aligned on a native word boundary. Most important on IA64 + */ + Resource = *ResourcePtr; + if (ACPI_IS_MISALIGNED (Resource)) + { + ACPI_WARNING ((AE_INFO, + "Misaligned resource pointer %p", Resource)); + } + + /* Get the appropriate conversion info table */ + + AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml); + if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) + { + if (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE) + { + ConversionTable = NULL; + } + else + { + /* This is an I2C, SPI, or UART SerialBus descriptor */ + + ConversionTable = + AcpiGbl_ConvertResourceSerialBusDispatch[ + AmlResource->CommonSerialBus.Type]; + } + } + else + { + ConversionTable = + AcpiGbl_GetResourceDispatch[ResourceIndex]; + } + + if (!ConversionTable) + { + ACPI_ERROR ((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + ResourceIndex)); + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Convert the AML byte stream resource to a local resource struct */ + + Status = AcpiRsConvertAmlToResource ( + Resource, AmlResource, ConversionTable); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not convert AML resource (Type 0x%X)", *Aml)); + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + AcpiUtGetResourceType (Aml), Length, + Resource->Length)); + + /* Point to the next structure in the output buffer */ + + *ResourcePtr = ACPI_NEXT_RESOURCE (Resource); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsConvertResourcesToAml + * + * PARAMETERS: Resource - Pointer to the resource linked list + * AmlSizeNeeded - Calculated size of the byte stream + * needed from calling AcpiRsGetAmlLength() + * The size of the OutputBuffer is + * guaranteed to be >= AmlSizeNeeded + * OutputBuffer - Pointer to the buffer that will + * contain the byte stream + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource linked list and parses it, creating a + * byte stream of resources in the caller's output buffer + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsConvertResourcesToAml ( + ACPI_RESOURCE *Resource, + ACPI_SIZE AmlSizeNeeded, + UINT8 *OutputBuffer) +{ + UINT8 *Aml = OutputBuffer; + UINT8 *EndAml = OutputBuffer + AmlSizeNeeded; + ACPI_RSCONVERT_INFO *ConversionTable; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsConvertResourcesToAml); + + + /* Walk the resource descriptor list, convert each descriptor */ + + while (Aml < EndAml) + { + /* Validate the (internal) Resource Type */ + + if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) + { + ACPI_ERROR ((AE_INFO, + "Invalid descriptor type (0x%X) in resource list", + Resource->Type)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* Perform the conversion */ + + if (Resource->Type == ACPI_RESOURCE_TYPE_SERIAL_BUS) + { + if (Resource->Data.CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE) + { + ConversionTable = NULL; + } + else + { + /* This is an I2C, SPI, or UART SerialBus descriptor */ + + ConversionTable = AcpiGbl_ConvertResourceSerialBusDispatch[ + Resource->Data.CommonSerialBus.Type]; + } + } + else + { + ConversionTable = AcpiGbl_SetResourceDispatch[Resource->Type]; + } + + if (!ConversionTable) + { + ACPI_ERROR ((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + Resource->Type)); + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + Status = AcpiRsConvertResourceToAml (Resource, + ACPI_CAST_PTR (AML_RESOURCE, Aml), + ConversionTable); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not convert resource (type 0x%X) to AML", + Resource->Type)); + return_ACPI_STATUS (Status); + } + + /* Perform final sanity check on the new AML resource descriptor */ + + Status = AcpiUtValidateResource ( + ACPI_CAST_PTR (AML_RESOURCE, Aml), NULL); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Check for end-of-list, normal exit */ + + if (Resource->Type == ACPI_RESOURCE_TYPE_END_TAG) + { + /* An End Tag indicates the end of the input Resource Template */ + + return_ACPI_STATUS (AE_OK); + } + + /* + * Extract the total length of the new descriptor and set the + * Aml to point to the next (output) resource descriptor + */ + Aml += AcpiUtGetDescriptorLength (Aml); + + /* Point to the next input resource descriptor */ + + Resource = ACPI_NEXT_RESOURCE (Resource); + } + + /* Completed buffer, but did not find an EndTag resource descriptor */ + + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +} + diff --git a/source/components/resources/rsmemory.c b/source/components/resources/rsmemory.c new file mode 100644 index 000000000000..83d131956ff7 --- /dev/null +++ b/source/components/resources/rsmemory.c @@ -0,0 +1,251 @@ +/******************************************************************************* + * + * Module Name: rsmem24 - Memory resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSMEMORY_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsmemory") + + +/******************************************************************************* + * + * AcpiRsConvertMemory24 + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertMemory24[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24, + ACPI_RS_SIZE (ACPI_RESOURCE_MEMORY24), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertMemory24)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24, + sizeof (AML_RESOURCE_MEMORY24), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Memory24.WriteProtect), + AML_OFFSET (Memory24.Flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.Memory24.Minimum), + AML_OFFSET (Memory24.Minimum), + 4} +}; + + +/******************************************************************************* + * + * AcpiRsConvertMemory32 + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertMemory32[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32, + ACPI_RS_SIZE (ACPI_RESOURCE_MEMORY32), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertMemory32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32, + sizeof (AML_RESOURCE_MEMORY32), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Memory32.WriteProtect), + AML_OFFSET (Memory32.Flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.Memory32.Minimum), + AML_OFFSET (Memory32.Minimum), + 4} +}; + + +/******************************************************************************* + * + * AcpiRsConvertFixedMemory32 + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertFixedMemory32[4] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32, + ACPI_RS_SIZE (ACPI_RESOURCE_FIXED_MEMORY32), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertFixedMemory32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32, + sizeof (AML_RESOURCE_FIXED_MEMORY32), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.FixedMemory32.WriteProtect), + AML_OFFSET (FixedMemory32.Flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Base Address + * Range Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.FixedMemory32.Address), + AML_OFFSET (FixedMemory32.Address), + 2} +}; + + +/******************************************************************************* + * + * AcpiRsGetVendorSmall + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsGetVendorSmall[3] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE (ACPI_RESOURCE_VENDOR), + ACPI_RSC_TABLE_SIZE (AcpiRsGetVendorSmall)}, + + /* Length of the vendor data (byte count) */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET (Data.Vendor.ByteLength), + 0, + sizeof (UINT8)}, + + /* Vendor data */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Vendor.ByteData[0]), + sizeof (AML_RESOURCE_SMALL_HEADER), + 0} +}; + + +/******************************************************************************* + * + * AcpiRsGetVendorLarge + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsGetVendorLarge[3] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE (ACPI_RESOURCE_VENDOR), + ACPI_RSC_TABLE_SIZE (AcpiRsGetVendorLarge)}, + + /* Length of the vendor data (byte count) */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET (Data.Vendor.ByteLength), + 0, + sizeof (UINT8)}, + + /* Vendor data */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Vendor.ByteData[0]), + sizeof (AML_RESOURCE_LARGE_HEADER), + 0} +}; + + +/******************************************************************************* + * + * AcpiRsSetVendor + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsSetVendor[7] = +{ + /* Default is a small vendor descriptor */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL, + sizeof (AML_RESOURCE_SMALL_HEADER), + ACPI_RSC_TABLE_SIZE (AcpiRsSetVendor)}, + + /* Get the length and copy the data */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET (Data.Vendor.ByteLength), + 0, + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Vendor.ByteData[0]), + sizeof (AML_RESOURCE_SMALL_HEADER), + 0}, + + /* + * All done if the Vendor byte length is 7 or less, meaning that it will + * fit within a small descriptor + */ + {ACPI_RSC_EXIT_LE, 0, 0, 7}, + + /* Must create a large vendor descriptor */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE, + sizeof (AML_RESOURCE_LARGE_HEADER), + 0}, + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET (Data.Vendor.ByteLength), + 0, + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Vendor.ByteData[0]), + sizeof (AML_RESOURCE_LARGE_HEADER), + 0} +}; + + diff --git a/source/components/resources/rsmisc.c b/source/components/resources/rsmisc.c new file mode 100644 index 000000000000..dfad696ca1d1 --- /dev/null +++ b/source/components/resources/rsmisc.c @@ -0,0 +1,869 @@ +/******************************************************************************* + * + * Module Name: rsmisc - Miscellaneous resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSMISC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsmisc") + + +#define INIT_RESOURCE_TYPE(i) i->ResourceOffset +#define INIT_RESOURCE_LENGTH(i) i->AmlOffset +#define INIT_TABLE_LENGTH(i) i->Value + +#define COMPARE_OPCODE(i) i->ResourceOffset +#define COMPARE_TARGET(i) i->AmlOffset +#define COMPARE_VALUE(i) i->Value + + +/******************************************************************************* + * + * FUNCTION: AcpiRsConvertAmlToResource + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table + * + * RETURN: Status + * + * DESCRIPTION: Convert an external AML resource descriptor to the corresponding + * internal resource descriptor + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsConvertAmlToResource ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml, + ACPI_RSCONVERT_INFO *Info) +{ + ACPI_RS_LENGTH AmlResourceLength; + void *Source; + void *Destination; + char *Target; + UINT8 Count; + UINT8 FlagsMode = FALSE; + UINT16 ItemCount = 0; + UINT16 Temp16 = 0; + + + ACPI_FUNCTION_TRACE (RsConvertAmlToResource); + + + if (!Info) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (((ACPI_SIZE) Resource) & 0x3) + { + /* Each internal resource struct is expected to be 32-bit aligned */ + + ACPI_WARNING ((AE_INFO, + "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u", + Resource, Resource->Type, Resource->Length)); + } + + /* Extract the resource Length field (does not include header length) */ + + AmlResourceLength = AcpiUtGetResourceLength (Aml); + + /* + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) + */ + Count = INIT_TABLE_LENGTH (Info); + while (Count) + { + /* + * Source is the external AML byte stream buffer, + * destination is the internal resource descriptor + */ + Source = ACPI_ADD_PTR (void, Aml, Info->AmlOffset); + Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset); + + switch (Info->Opcode) + { + case ACPI_RSC_INITGET: + /* + * Get the resource type and the initial (minimum) length + */ + ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info)); + Resource->Type = INIT_RESOURCE_TYPE (Info); + Resource->Length = INIT_RESOURCE_LENGTH (Info); + break; + + + case ACPI_RSC_INITSET: + break; + + + case ACPI_RSC_FLAGINIT: + + FlagsMode = TRUE; + break; + + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8 (Destination) = (UINT8) + ((ACPI_GET8 (Source) >> Info->Value) & 0x01); + break; + + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination) = (UINT8) + ((ACPI_GET8 (Source) >> Info->Value) & 0x03); + break; + + + case ACPI_RSC_3BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination) = (UINT8) + ((ACPI_GET8 (Source) >> Info->Value) & 0x07); + break; + + + case ACPI_RSC_COUNT: + + ItemCount = ACPI_GET8 (Source); + ACPI_SET8 (Destination) = (UINT8) ItemCount; + + Resource->Length = Resource->Length + + (Info->Value * (ItemCount - 1)); + break; + + + case ACPI_RSC_COUNT16: + + ItemCount = AmlResourceLength; + ACPI_SET16 (Destination) = ItemCount; + + Resource->Length = Resource->Length + + (Info->Value * (ItemCount - 1)); + break; + + + case ACPI_RSC_COUNT_GPIO_PIN: + + Target = ACPI_ADD_PTR (void, Aml, Info->Value); + ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source); + + Resource->Length = Resource->Length + ItemCount; + ItemCount = ItemCount / 2; + ACPI_SET16 (Destination) = ItemCount; + break; + + + case ACPI_RSC_COUNT_GPIO_VEN: + + ItemCount = ACPI_GET8 (Source); + ACPI_SET8 (Destination) = (UINT8) ItemCount; + + Resource->Length = Resource->Length + + (Info->Value * ItemCount); + break; + + + case ACPI_RSC_COUNT_GPIO_RES: + + /* + * Vendor data is optional (length/offset may both be zero) + * Examine vendor data length field first + */ + Target = ACPI_ADD_PTR (void, Aml, (Info->Value + 2)); + if (ACPI_GET16 (Target)) + { + /* Use vendor offset to get resource source length */ + + Target = ACPI_ADD_PTR (void, Aml, Info->Value); + ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source); + } + else + { + /* No vendor data to worry about */ + + ItemCount = Aml->LargeHeader.ResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER) - + ACPI_GET16 (Source); + } + + Resource->Length = Resource->Length + ItemCount; + ACPI_SET16 (Destination) = ItemCount; + break; + + + case ACPI_RSC_COUNT_SERIAL_VEN: + + ItemCount = ACPI_GET16 (Source) - Info->Value; + + Resource->Length = Resource->Length + ItemCount; + ACPI_SET16 (Destination) = ItemCount; + break; + + + case ACPI_RSC_COUNT_SERIAL_RES: + + ItemCount = (AmlResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER)) - + ACPI_GET16 (Source) - Info->Value; + + Resource->Length = Resource->Length + ItemCount; + ACPI_SET16 (Destination) = ItemCount; + break; + + + case ACPI_RSC_LENGTH: + + Resource->Length = Resource->Length + Info->Value; + break; + + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + /* + * Raw data move. Use the Info value field unless ItemCount has + * been previously initialized via a COUNT opcode + */ + if (Info->Value) + { + ItemCount = Info->Value; + } + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_GPIO_PIN: + + /* Generate and set the PIN data pointer */ + + Target = (char *) ACPI_ADD_PTR (void, Resource, + (Resource->Length - ItemCount * 2)); + *(UINT16 **) Destination = ACPI_CAST_PTR (UINT16, Target); + + /* Copy the PIN data */ + + Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source)); + AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_GPIO_RES: + + /* Generate and set the ResourceSource string pointer */ + + Target = (char *) ACPI_ADD_PTR (void, Resource, + (Resource->Length - ItemCount)); + *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target); + + /* Copy the ResourceSource string */ + + Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source)); + AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_SERIAL_VEN: + + /* Generate and set the Vendor Data pointer */ + + Target = (char *) ACPI_ADD_PTR (void, Resource, + (Resource->Length - ItemCount)); + *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target); + + /* Copy the Vendor Data */ + + Source = ACPI_ADD_PTR (void, Aml, Info->Value); + AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_SERIAL_RES: + + /* Generate and set the ResourceSource string pointer */ + + Target = (char *) ACPI_ADD_PTR (void, Resource, + (Resource->Length - ItemCount)); + *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target); + + /* Copy the ResourceSource string */ + + Source = ACPI_ADD_PTR (void, Aml, (ACPI_GET16 (Source) + Info->Value)); + AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_SET8: + + ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value); + break; + + + case ACPI_RSC_DATA8: + + Target = ACPI_ADD_PTR (char, Resource, Info->Value); + ACPI_MEMCPY (Destination, Source, ACPI_GET16 (Target)); + break; + + + case ACPI_RSC_ADDRESS: + /* + * Common handler for address descriptor flags + */ + if (!AcpiRsGetAddressCommon (Resource, Aml)) + { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + break; + + + case ACPI_RSC_SOURCE: + /* + * Optional ResourceSource (Index and String) + */ + Resource->Length += + AcpiRsGetResourceSource (AmlResourceLength, Info->Value, + Destination, Aml, NULL); + break; + + + case ACPI_RSC_SOURCEX: + /* + * Optional ResourceSource (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + Target = ACPI_ADD_PTR (char, Resource, + Info->AmlOffset + (ItemCount * 4)); + + Resource->Length += + AcpiRsGetResourceSource (AmlResourceLength, (ACPI_RS_LENGTH) + (((ItemCount - 1) * sizeof (UINT32)) + Info->Value), + Destination, Aml, Target); + break; + + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination); + if (ItemCount) + { + Resource->Length += (ItemCount - 1); + } + + Target = ACPI_ADD_PTR (char, Resource, Info->Value); + ACPI_SET8 (Target) = (UINT8) ItemCount; + break; + + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + ACPI_MOVE_16_TO_16 (&Temp16, Source); + + ItemCount = AcpiRsDecodeBitmask (Temp16, Destination); + if (ItemCount) + { + Resource->Length += (ItemCount - 1); + } + + Target = ACPI_ADD_PTR (char, Resource, Info->Value); + ACPI_SET8 (Target) = (UINT8) ItemCount; + break; + + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (Info->ResourceOffset) + { + case ACPI_RSC_COMPARE_AML_LENGTH: + if (AmlResourceLength != Info->Value) + { + goto Exit; + } + break; + + case ACPI_RSC_COMPARE_VALUE: + if (ACPI_GET8 (Source) != Info->Value) + { + goto Exit; + } + break; + + default: + + ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Count--; + Info++; + } + +Exit: + if (!FlagsMode) + { + /* Round the resource struct length up to the next boundary (32 or 64) */ + + Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length); + } + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsConvertResourceToAml + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table + * + * RETURN: Status + * + * DESCRIPTION: Convert an internal resource descriptor to the corresponding + * external AML resource descriptor. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsConvertResourceToAml ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml, + ACPI_RSCONVERT_INFO *Info) +{ + void *Source = NULL; + void *Destination; + char *Target; + ACPI_RSDESC_SIZE AmlLength = 0; + UINT8 Count; + UINT16 Temp16 = 0; + UINT16 ItemCount = 0; + + + ACPI_FUNCTION_TRACE (RsConvertResourceToAml); + + + if (!Info) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) + */ + Count = INIT_TABLE_LENGTH (Info); + + while (Count) + { + /* + * Source is the internal resource descriptor, + * destination is the external AML byte stream buffer + */ + Source = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset); + Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset); + + switch (Info->Opcode) + { + case ACPI_RSC_INITSET: + + ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info)); + AmlLength = INIT_RESOURCE_LENGTH (Info); + AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml); + break; + + + case ACPI_RSC_INITGET: + break; + + + case ACPI_RSC_FLAGINIT: + /* + * Clear the flag byte + */ + ACPI_SET8 (Destination) = 0; + break; + + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8 (Destination) |= (UINT8) + ((ACPI_GET8 (Source) & 0x01) << Info->Value); + break; + + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination) |= (UINT8) + ((ACPI_GET8 (Source) & 0x03) << Info->Value); + break; + + + case ACPI_RSC_3BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination) |= (UINT8) + ((ACPI_GET8 (Source) & 0x07) << Info->Value); + break; + + + case ACPI_RSC_COUNT: + + ItemCount = ACPI_GET8 (Source); + ACPI_SET8 (Destination) = (UINT8) ItemCount; + + AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1))); + break; + + + case ACPI_RSC_COUNT16: + + ItemCount = ACPI_GET16 (Source); + AmlLength = (UINT16) (AmlLength + ItemCount); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_COUNT_GPIO_PIN: + + ItemCount = ACPI_GET16 (Source); + ACPI_SET16 (Destination) = (UINT16) AmlLength; + + AmlLength = (UINT16) (AmlLength + ItemCount * 2); + Target = ACPI_ADD_PTR (void, Aml, Info->Value); + ACPI_SET16 (Target) = (UINT16) AmlLength; + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_COUNT_GPIO_VEN: + + ItemCount = ACPI_GET16 (Source); + ACPI_SET16 (Destination) = (UINT16) ItemCount; + + AmlLength = (UINT16) (AmlLength + (Info->Value * ItemCount)); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_COUNT_GPIO_RES: + + /* Set resource source string length */ + + ItemCount = ACPI_GET16 (Source); + ACPI_SET16 (Destination) = (UINT16) AmlLength; + + /* Compute offset for the Vendor Data */ + + AmlLength = (UINT16) (AmlLength + ItemCount); + Target = ACPI_ADD_PTR (void, Aml, Info->Value); + + /* Set vendor offset only if there is vendor data */ + + if (Resource->Data.Gpio.VendorLength) + { + ACPI_SET16 (Target) = (UINT16) AmlLength; + } + + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_COUNT_SERIAL_VEN: + + ItemCount = ACPI_GET16 (Source); + ACPI_SET16 (Destination) = ItemCount + Info->Value; + AmlLength = (UINT16) (AmlLength + ItemCount); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_COUNT_SERIAL_RES: + + ItemCount = ACPI_GET16 (Source); + AmlLength = (UINT16) (AmlLength + ItemCount); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_LENGTH: + + AcpiRsSetResourceLength (Info->Value, Aml); + break; + + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + + if (Info->Value) + { + ItemCount = Info->Value; + } + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_GPIO_PIN: + + Destination = (char *) ACPI_ADD_PTR (void, Aml, + ACPI_GET16 (Destination)); + Source = * (UINT16 **) Source; + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_GPIO_RES: + + /* Used for both ResourceSource string and VendorData */ + + Destination = (char *) ACPI_ADD_PTR (void, Aml, + ACPI_GET16 (Destination)); + Source = * (UINT8 **) Source; + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_SERIAL_VEN: + + Destination = (char *) ACPI_ADD_PTR (void, Aml, + (AmlLength - ItemCount)); + Source = * (UINT8 **) Source; + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_MOVE_SERIAL_RES: + + Destination = (char *) ACPI_ADD_PTR (void, Aml, + (AmlLength - ItemCount)); + Source = * (UINT8 **) Source; + AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); + break; + + + case ACPI_RSC_ADDRESS: + + /* Set the Resource Type, General Flags, and Type-Specific Flags */ + + AcpiRsSetAddressCommon (Aml, Resource); + break; + + + case ACPI_RSC_SOURCEX: + /* + * Optional ResourceSource (Index and String) + */ + AmlLength = AcpiRsSetResourceSource ( + Aml, (ACPI_RS_LENGTH) AmlLength, Source); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_SOURCE: + /* + * Optional ResourceSource (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + ACPI_SET8 (Destination) = (UINT8) + AcpiRsEncodeBitmask (Source, + *ACPI_ADD_PTR (UINT8, Resource, Info->Value)); + break; + + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + Temp16 = AcpiRsEncodeBitmask (Source, + *ACPI_ADD_PTR (UINT8, Resource, Info->Value)); + ACPI_MOVE_16_TO_16 (Destination, &Temp16); + break; + + + case ACPI_RSC_EXIT_LE: + /* + * Control - Exit conversion if less than or equal + */ + if (ItemCount <= Info->Value) + { + goto Exit; + } + break; + + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (COMPARE_OPCODE (Info)) + { + case ACPI_RSC_COMPARE_VALUE: + + if (*ACPI_ADD_PTR (UINT8, Resource, + COMPARE_TARGET (Info)) != COMPARE_VALUE (Info)) + { + goto Exit; + } + break; + + default: + + ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + break; + + + case ACPI_RSC_EXIT_EQ: + /* + * Control - Exit conversion if equal + */ + if (*ACPI_ADD_PTR (UINT8, Resource, + COMPARE_TARGET (Info)) == COMPARE_VALUE (Info)) + { + goto Exit; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Count--; + Info++; + } + +Exit: + return_ACPI_STATUS (AE_OK); +} + + +#if 0 +/* Previous resource validations */ + + if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) + { + return_ACPI_STATUS (AE_SUPPORT); + } + + if (Resource->Data.StartDpf.PerformanceRobustness >= 3) + { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); + } + + if (((Aml->Irq.Flags & 0x09) == 0x00) || + ((Aml->Irq.Flags & 0x09) == 0x09)) + { + /* + * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive] + * polarity/trigger interrupts are allowed (ACPI spec, section + * "IRQ Format"), so 0x00 and 0x09 are illegal. + */ + ACPI_ERROR ((AE_INFO, + "Invalid interrupt polarity/trigger in resource list, 0x%X", + Aml->Irq.Flags)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + Resource->Data.ExtendedIrq.InterruptCount = Temp8; + if (Temp8 < 1) + { + /* Must have at least one IRQ */ + + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + if (Resource->Data.Dma.Transfer == 0x03) + { + ACPI_ERROR ((AE_INFO, + "Invalid DMA.Transfer preference (3)")); + return_ACPI_STATUS (AE_BAD_DATA); + } +#endif + + diff --git a/source/components/resources/rsserial.c b/source/components/resources/rsserial.c new file mode 100644 index 000000000000..3a7784e96c8c --- /dev/null +++ b/source/components/resources/rsserial.c @@ -0,0 +1,425 @@ +/******************************************************************************* + * + * Module Name: rsserial - GPIO/SerialBus resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __RSIRQ_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsserial") + + +/******************************************************************************* + * + * AcpiRsConvertGpio + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertGpio[17] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO, + ACPI_RS_SIZE (ACPI_RESOURCE_GPIO), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertGpio)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GPIO, + sizeof (AML_RESOURCE_GPIO), + 0}, + + /* + * These fields are contiguous in both the source and destination: + * RevisionId + * ConnectionType + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Gpio.RevisionId), + AML_OFFSET (Gpio.RevisionId), + 2}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.ProducerConsumer), + AML_OFFSET (Gpio.Flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Sharable), + AML_OFFSET (Gpio.IntFlags), + 3}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.IoRestriction), + AML_OFFSET (Gpio.IntFlags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Triggering), + AML_OFFSET (Gpio.IntFlags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Polarity), + AML_OFFSET (Gpio.IntFlags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Gpio.PinConfig), + AML_OFFSET (Gpio.PinConfig), + 1}, + + /* + * These fields are contiguous in both the source and destination: + * DriveStrength + * DebounceTimeout + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.Gpio.DriveStrength), + AML_OFFSET (Gpio.DriveStrength), + 2}, + + /* Pin Table */ + + {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET (Data.Gpio.PinTableLength), + AML_OFFSET (Gpio.PinTableOffset), + AML_OFFSET (Gpio.ResSourceOffset)}, + + {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET (Data.Gpio.PinTable), + AML_OFFSET (Gpio.PinTableOffset), + 0}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Gpio.ResourceSource.Index), + AML_OFFSET (Gpio.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.Gpio.ResourceSource.StringLength), + AML_OFFSET (Gpio.ResSourceOffset), + AML_OFFSET (Gpio.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.Gpio.ResourceSource.StringPtr), + AML_OFFSET (Gpio.ResSourceOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.Gpio.VendorLength), + AML_OFFSET (Gpio.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.Gpio.VendorData), + AML_OFFSET (Gpio.VendorOffset), + 0}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertI2cSerialBus + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[16] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, + ACPI_RS_SIZE (ACPI_RESOURCE_I2C_SERIALBUS), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertI2cSerialBus)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, + sizeof (AML_RESOURCE_I2C_SERIALBUS), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.RevisionId), + AML_OFFSET (CommonSerialBus.RevisionId), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.Type), + AML_OFFSET (CommonSerialBus.Type), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.SlaveMode), + AML_OFFSET (CommonSerialBus.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ProducerConsumer), + AML_OFFSET (CommonSerialBus.Flags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeRevisionId), + AML_OFFSET (CommonSerialBus.TypeRevisionId), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeDataLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + 1}, + + /* Vendor data */ + + {ACPI_RSC_COUNT_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + AML_RESOURCE_I2C_MIN_DATA_LEN}, + + {ACPI_RSC_MOVE_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorData), + 0, + sizeof (AML_RESOURCE_I2C_SERIALBUS)}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.Index), + AML_OFFSET (CommonSerialBus.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + {ACPI_RSC_MOVE_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringPtr), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + /* I2C bus type specific */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.I2cSerialBus.AccessMode), + AML_OFFSET (I2cSerialBus.TypeSpecificFlags), + 0}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.I2cSerialBus.ConnectionSpeed), + AML_OFFSET (I2cSerialBus.ConnectionSpeed), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.I2cSerialBus.SlaveAddress), + AML_OFFSET (I2cSerialBus.SlaveAddress), + 1}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertSpiSerialBus + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertSpiSerialBus[20] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, + ACPI_RS_SIZE (ACPI_RESOURCE_SPI_SERIALBUS), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertSpiSerialBus)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, + sizeof (AML_RESOURCE_SPI_SERIALBUS), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.RevisionId), + AML_OFFSET (CommonSerialBus.RevisionId), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.Type), + AML_OFFSET (CommonSerialBus.Type), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.SlaveMode), + AML_OFFSET (CommonSerialBus.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ProducerConsumer), + AML_OFFSET (CommonSerialBus.Flags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeRevisionId), + AML_OFFSET (CommonSerialBus.TypeRevisionId), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeDataLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + 1}, + + /* Vendor data */ + + {ACPI_RSC_COUNT_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + AML_RESOURCE_SPI_MIN_DATA_LEN}, + + {ACPI_RSC_MOVE_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorData), + 0, + sizeof (AML_RESOURCE_SPI_SERIALBUS)}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.Index), + AML_OFFSET (CommonSerialBus.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + {ACPI_RSC_MOVE_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringPtr), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + /* Spi bus type specific */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.SpiSerialBus.WireMode), + AML_OFFSET (SpiSerialBus.TypeSpecificFlags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.SpiSerialBus.DevicePolarity), + AML_OFFSET (SpiSerialBus.TypeSpecificFlags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.SpiSerialBus.DataBitLength), + AML_OFFSET (SpiSerialBus.DataBitLength), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.SpiSerialBus.ClockPhase), + AML_OFFSET (SpiSerialBus.ClockPhase), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.SpiSerialBus.ClockPolarity), + AML_OFFSET (SpiSerialBus.ClockPolarity), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.SpiSerialBus.DeviceSelection), + AML_OFFSET (SpiSerialBus.DeviceSelection), + 1}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.SpiSerialBus.ConnectionSpeed), + AML_OFFSET (SpiSerialBus.ConnectionSpeed), + 1}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertUartSerialBus + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertUartSerialBus[22] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, + ACPI_RS_SIZE (ACPI_RESOURCE_UART_SERIALBUS), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertUartSerialBus)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, + sizeof (AML_RESOURCE_UART_SERIALBUS), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.RevisionId), + AML_OFFSET (CommonSerialBus.RevisionId), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.Type), + AML_OFFSET (CommonSerialBus.Type), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.SlaveMode), + AML_OFFSET (CommonSerialBus.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ProducerConsumer), + AML_OFFSET (CommonSerialBus.Flags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeRevisionId), + AML_OFFSET (CommonSerialBus.TypeRevisionId), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.CommonSerialBus.TypeDataLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + 1}, + + /* Vendor data */ + + {ACPI_RSC_COUNT_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + AML_RESOURCE_UART_MIN_DATA_LEN}, + + {ACPI_RSC_MOVE_SERIAL_VEN, ACPI_RS_OFFSET (Data.CommonSerialBus.VendorData), + 0, + sizeof (AML_RESOURCE_UART_SERIALBUS)}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.Index), + AML_OFFSET (CommonSerialBus.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringLength), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + {ACPI_RSC_MOVE_SERIAL_RES, ACPI_RS_OFFSET (Data.CommonSerialBus.ResourceSource.StringPtr), + AML_OFFSET (CommonSerialBus.TypeDataLength), + sizeof (AML_RESOURCE_COMMON_SERIALBUS)}, + + /* Uart bus type specific */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.UartSerialBus.FlowControl), + AML_OFFSET (UartSerialBus.TypeSpecificFlags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.UartSerialBus.StopBits), + AML_OFFSET (UartSerialBus.TypeSpecificFlags), + 2}, + + {ACPI_RSC_3BITFLAG, ACPI_RS_OFFSET (Data.UartSerialBus.DataBits), + AML_OFFSET (UartSerialBus.TypeSpecificFlags), + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.UartSerialBus.Endian), + AML_OFFSET (UartSerialBus.TypeSpecificFlags), + 7}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.UartSerialBus.Parity), + AML_OFFSET (UartSerialBus.Parity), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.UartSerialBus.LinesEnabled), + AML_OFFSET (UartSerialBus.LinesEnabled), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.UartSerialBus.RxFifoSize), + AML_OFFSET (UartSerialBus.RxFifoSize), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.UartSerialBus.TxFifoSize), + AML_OFFSET (UartSerialBus.TxFifoSize), + 1}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.UartSerialBus.DefaultBaudRate), + AML_OFFSET (UartSerialBus.DefaultBaudRate), + 1}, +}; diff --git a/source/components/resources/rsutils.c b/source/components/resources/rsutils.c new file mode 100644 index 000000000000..062678651ec1 --- /dev/null +++ b/source/components/resources/rsutils.c @@ -0,0 +1,861 @@ +/******************************************************************************* + * + * Module Name: rsutils - Utilities for the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __RSUTILS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsutils") + + +/******************************************************************************* + * + * FUNCTION: AcpiRsDecodeBitmask + * + * PARAMETERS: Mask - Bitmask to decode + * List - Where the converted list is returned + * + * RETURN: Count of bits set (length of list) + * + * DESCRIPTION: Convert a bit mask into a list of values + * + ******************************************************************************/ + +UINT8 +AcpiRsDecodeBitmask ( + UINT16 Mask, + UINT8 *List) +{ + UINT8 i; + UINT8 BitCount; + + + ACPI_FUNCTION_ENTRY (); + + + /* Decode the mask bits */ + + for (i = 0, BitCount = 0; Mask; i++) + { + if (Mask & 0x0001) + { + List[BitCount] = i; + BitCount++; + } + + Mask >>= 1; + } + + return (BitCount); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsEncodeBitmask + * + * PARAMETERS: List - List of values to encode + * Count - Length of list + * + * RETURN: Encoded bitmask + * + * DESCRIPTION: Convert a list of values to an encoded bitmask + * + ******************************************************************************/ + +UINT16 +AcpiRsEncodeBitmask ( + UINT8 *List, + UINT8 Count) +{ + UINT32 i; + UINT16 Mask; + + + ACPI_FUNCTION_ENTRY (); + + + /* Encode the list into a single bitmask */ + + for (i = 0, Mask = 0; i < Count; i++) + { + Mask |= (0x1 << List[i]); + } + + return (Mask); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsMoveData + * + * PARAMETERS: Destination - Pointer to the destination descriptor + * Source - Pointer to the source descriptor + * ItemCount - How many items to move + * MoveType - Byte width + * + * RETURN: None + * + * DESCRIPTION: Move multiple data items from one descriptor to another. Handles + * alignment issues and endian issues if necessary, as configured + * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) + * + ******************************************************************************/ + +void +AcpiRsMoveData ( + void *Destination, + void *Source, + UINT16 ItemCount, + UINT8 MoveType) +{ + UINT32 i; + + + ACPI_FUNCTION_ENTRY (); + + + /* One move per item */ + + for (i = 0; i < ItemCount; i++) + { + switch (MoveType) + { + /* + * For the 8-bit case, we can perform the move all at once + * since there are no alignment or endian issues + */ + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE_GPIO_RES: + case ACPI_RSC_MOVE_SERIAL_VEN: + case ACPI_RSC_MOVE_SERIAL_RES: + ACPI_MEMCPY (Destination, Source, ItemCount); + return; + + /* + * 16-, 32-, and 64-bit cases must use the move macros that perform + * endian conversion and/or accomodate hardware that cannot perform + * misaligned memory transfers + */ + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE_GPIO_PIN: + ACPI_MOVE_16_TO_16 (&ACPI_CAST_PTR (UINT16, Destination)[i], + &ACPI_CAST_PTR (UINT16, Source)[i]); + break; + + case ACPI_RSC_MOVE32: + ACPI_MOVE_32_TO_32 (&ACPI_CAST_PTR (UINT32, Destination)[i], + &ACPI_CAST_PTR (UINT32, Source)[i]); + break; + + case ACPI_RSC_MOVE64: + ACPI_MOVE_64_TO_64 (&ACPI_CAST_PTR (UINT64, Destination)[i], + &ACPI_CAST_PTR (UINT64, Source)[i]); + break; + + default: + return; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsSetResourceLength + * + * PARAMETERS: TotalLength - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the ResourceLength field of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically. Note: Descriptor Type field must + * be valid. + * + ******************************************************************************/ + +void +AcpiRsSetResourceLength ( + ACPI_RSDESC_SIZE TotalLength, + AML_RESOURCE *Aml) +{ + ACPI_RS_LENGTH ResourceLength; + + + ACPI_FUNCTION_ENTRY (); + + + /* Length is the total descriptor length minus the header length */ + + ResourceLength = (ACPI_RS_LENGTH) + (TotalLength - AcpiUtGetResourceHeaderLength (Aml)); + + /* Length is stored differently for large and small descriptors */ + + if (Aml->SmallHeader.DescriptorType & ACPI_RESOURCE_NAME_LARGE) + { + /* Large descriptor -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16 (&Aml->LargeHeader.ResourceLength, &ResourceLength); + } + else + { + /* Small descriptor -- bits 2:0 of byte 0 contain the length */ + + Aml->SmallHeader.DescriptorType = (UINT8) + + /* Clear any existing length, preserving descriptor type bits */ + + ((Aml->SmallHeader.DescriptorType & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK) + + | ResourceLength); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsSetResourceHeader + * + * PARAMETERS: DescriptorType - Byte to be inserted as the type + * TotalLength - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the DescriptorType and ResourceLength fields of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically + * + ******************************************************************************/ + +void +AcpiRsSetResourceHeader ( + UINT8 DescriptorType, + ACPI_RSDESC_SIZE TotalLength, + AML_RESOURCE *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Set the Resource Type */ + + Aml->SmallHeader.DescriptorType = DescriptorType; + + /* Set the Resource Length */ + + AcpiRsSetResourceLength (TotalLength, Aml); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsStrcpy + * + * PARAMETERS: Destination - Pointer to the destination string + * Source - Pointer to the source string + * + * RETURN: String length, including NULL terminator + * + * DESCRIPTION: Local string copy that returns the string length, saving a + * strcpy followed by a strlen. + * + ******************************************************************************/ + +static UINT16 +AcpiRsStrcpy ( + char *Destination, + char *Source) +{ + UINT16 i; + + + ACPI_FUNCTION_ENTRY (); + + + for (i = 0; Source[i]; i++) + { + Destination[i] = Source[i]; + } + + Destination[i] = 0; + + /* Return string length including the NULL terminator */ + + return ((UINT16) (i + 1)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetResourceSource + * + * PARAMETERS: ResourceLength - Length field of the descriptor + * MinimumLength - Minimum length of the descriptor (minus + * any optional fields) + * ResourceSource - Where the ResourceSource is returned + * Aml - Pointer to the raw AML descriptor + * StringPtr - (optional) where to store the actual + * ResourceSource string + * + * RETURN: Length of the string plus NULL terminator, rounded up to native + * word boundary + * + * DESCRIPTION: Copy the optional ResourceSource data from a raw AML descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +ACPI_RS_LENGTH +AcpiRsGetResourceSource ( + ACPI_RS_LENGTH ResourceLength, + ACPI_RS_LENGTH MinimumLength, + ACPI_RESOURCE_SOURCE *ResourceSource, + AML_RESOURCE *Aml, + char *StringPtr) +{ + ACPI_RSDESC_SIZE TotalLength; + UINT8 *AmlResourceSource; + + + ACPI_FUNCTION_ENTRY (); + + + TotalLength = ResourceLength + sizeof (AML_RESOURCE_LARGE_HEADER); + AmlResourceSource = ACPI_ADD_PTR (UINT8, Aml, MinimumLength); + + /* + * ResourceSource is present if the length of the descriptor is longer than + * the minimum length. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the minimum length. + */ + if (TotalLength > (ACPI_RSDESC_SIZE) (MinimumLength + 1)) + { + /* Get the ResourceSourceIndex */ + + ResourceSource->Index = AmlResourceSource[0]; + + ResourceSource->StringPtr = StringPtr; + if (!StringPtr) + { + /* + * String destination pointer is not specified; Set the String + * pointer to the end of the current ResourceSource structure. + */ + ResourceSource->StringPtr = ACPI_ADD_PTR (char, ResourceSource, + sizeof (ACPI_RESOURCE_SOURCE)); + } + + /* + * In order for the Resource length to be a multiple of the native + * word, calculate the length of the string (+1 for NULL terminator) + * and expand to the next word multiple. + * + * Zero the entire area of the buffer. + */ + TotalLength = (UINT32) ACPI_STRLEN ( + ACPI_CAST_PTR (char, &AmlResourceSource[1])) + 1; + TotalLength = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (TotalLength); + + ACPI_MEMSET (ResourceSource->StringPtr, 0, TotalLength); + + /* Copy the ResourceSource string to the destination */ + + ResourceSource->StringLength = AcpiRsStrcpy (ResourceSource->StringPtr, + ACPI_CAST_PTR (char, &AmlResourceSource[1])); + + return ((ACPI_RS_LENGTH) TotalLength); + } + + /* ResourceSource is not present */ + + ResourceSource->Index = 0; + ResourceSource->StringLength = 0; + ResourceSource->StringPtr = NULL; + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsSetResourceSource + * + * PARAMETERS: Aml - Pointer to the raw AML descriptor + * MinimumLength - Minimum length of the descriptor (minus + * any optional fields) + * ResourceSource - Internal ResourceSource + + * + * RETURN: Total length of the AML descriptor + * + * DESCRIPTION: Convert an optional ResourceSource from internal format to a + * raw AML resource descriptor + * + ******************************************************************************/ + +ACPI_RSDESC_SIZE +AcpiRsSetResourceSource ( + AML_RESOURCE *Aml, + ACPI_RS_LENGTH MinimumLength, + ACPI_RESOURCE_SOURCE *ResourceSource) +{ + UINT8 *AmlResourceSource; + ACPI_RSDESC_SIZE DescriptorLength; + + + ACPI_FUNCTION_ENTRY (); + + + DescriptorLength = MinimumLength; + + /* Non-zero string length indicates presence of a ResourceSource */ + + if (ResourceSource->StringLength) + { + /* Point to the end of the AML descriptor */ + + AmlResourceSource = ACPI_ADD_PTR (UINT8, Aml, MinimumLength); + + /* Copy the ResourceSourceIndex */ + + AmlResourceSource[0] = (UINT8) ResourceSource->Index; + + /* Copy the ResourceSource string */ + + ACPI_STRCPY (ACPI_CAST_PTR (char, &AmlResourceSource[1]), + ResourceSource->StringPtr); + + /* + * Add the length of the string (+ 1 for null terminator) to the + * final descriptor length + */ + DescriptorLength += ((ACPI_RSDESC_SIZE) ResourceSource->StringLength + 1); + } + + /* Return the new total length of the AML descriptor */ + + return (DescriptorLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetPrtMethodData + * + * PARAMETERS: Node - Device node + * RetBuffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRT value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetPrtMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsGetPrtMethodData); + + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + Status = AcpiUtEvaluateObject (Node, METHOD_NAME__PRT, + ACPI_BTYPE_PACKAGE, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Create a resource linked list from the byte stream buffer that comes + * back from the _CRS method execution. + */ + Status = AcpiRsCreatePciRoutingTable (ObjDesc, RetBuffer); + + /* On exit, we must delete the object returned by EvaluateObject */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetCrsMethodData + * + * PARAMETERS: Node - Device node + * RetBuffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetCrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsGetCrsMethodData); + + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + Status = AcpiUtEvaluateObject (Node, METHOD_NAME__CRS, + ACPI_BTYPE_BUFFER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + Status = AcpiRsCreateResourceList (ObjDesc, RetBuffer); + + /* On exit, we must delete the object returned by evaluateObject */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetPrsMethodData + * + * PARAMETERS: Node - Device node + * RetBuffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetPrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsGetPrsMethodData); + + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + Status = AcpiUtEvaluateObject (Node, METHOD_NAME__PRS, + ACPI_BTYPE_BUFFER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + Status = AcpiRsCreateResourceList (ObjDesc, RetBuffer); + + /* On exit, we must delete the object returned by evaluateObject */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetAeiMethodData + * + * PARAMETERS: Node - Device node + * RetBuffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _AEI value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetAeiMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsGetAeiMethodData); + + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + Status = AcpiUtEvaluateObject (Node, METHOD_NAME__AEI, + ACPI_BTYPE_BUFFER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + Status = AcpiRsCreateResourceList (ObjDesc, RetBuffer); + + /* On exit, we must delete the object returned by evaluateObject */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsGetMethodData + * + * PARAMETERS: Handle - Handle to the containing object + * Path - Path to method, relative to Handle + * RetBuffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS or _PRS value of an + * object contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsGetMethodData ( + ACPI_HANDLE Handle, + char *Path, + ACPI_BUFFER *RetBuffer) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (RsGetMethodData); + + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + Status = AcpiUtEvaluateObject (Handle, Path, ACPI_BTYPE_BUFFER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the method + * execution. + */ + Status = AcpiRsCreateResourceList (ObjDesc, RetBuffer); + + /* On exit, we must delete the object returned by EvaluateObject */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsSetSrsMethodData + * + * PARAMETERS: Node - Device node + * InBuffer - Pointer to a buffer structure of the + * parameter + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the _SRS of an object contained + * in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + * Note: Parameters guaranteed valid by caller + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsSetSrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *InBuffer) +{ + ACPI_EVALUATE_INFO *Info; + ACPI_OPERAND_OBJECT *Args[2]; + ACPI_STATUS Status; + ACPI_BUFFER Buffer; + + + ACPI_FUNCTION_TRACE (RsSetSrsMethodData); + + + /* Allocate and initialize the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->PrefixNode = Node; + Info->Pathname = METHOD_NAME__SRS; + Info->Parameters = Args; + Info->Flags = ACPI_IGNORE_RETURN_VALUE; + + /* + * The InBuffer parameter will point to a linked list of + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter to _SRS + * + * Convert the linked list into a byte stream + */ + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiRsCreateAmlResources (InBuffer->Pointer, &Buffer); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Create and initialize the method parameter object */ + + Args[0] = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); + if (!Args[0]) + { + /* + * Must free the buffer allocated above (otherwise it is freed + * later) + */ + ACPI_FREE (Buffer.Pointer); + Status = AE_NO_MEMORY; + goto Cleanup; + } + + Args[0]->Buffer.Length = (UINT32) Buffer.Length; + Args[0]->Buffer.Pointer = Buffer.Pointer; + Args[0]->Common.Flags = AOPOBJ_DATA_VALID; + Args[1] = NULL; + + /* Execute the method, no return value is expected */ + + Status = AcpiNsEvaluate (Info); + + /* Clean up and return the status from AcpiNsEvaluate */ + + AcpiUtRemoveReference (Args[0]); + +Cleanup: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/resources/rsxface.c b/source/components/resources/rsxface.c new file mode 100644 index 000000000000..d8c3938b31bc --- /dev/null +++ b/source/components/resources/rsxface.c @@ -0,0 +1,689 @@ +/******************************************************************************* + * + * Module Name: rsxface - Public interfaces to the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __RSXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsxface") + +/* Local macros for 16,32-bit to 64-bit conversion */ + +#define ACPI_COPY_FIELD(Out, In, Field) ((Out)->Field = (In)->Field) +#define ACPI_COPY_ADDRESS(Out, In) \ + ACPI_COPY_FIELD(Out, In, ResourceType); \ + ACPI_COPY_FIELD(Out, In, ProducerConsumer); \ + ACPI_COPY_FIELD(Out, In, Decode); \ + ACPI_COPY_FIELD(Out, In, MinAddressFixed); \ + ACPI_COPY_FIELD(Out, In, MaxAddressFixed); \ + ACPI_COPY_FIELD(Out, In, Info); \ + ACPI_COPY_FIELD(Out, In, Granularity); \ + ACPI_COPY_FIELD(Out, In, Minimum); \ + ACPI_COPY_FIELD(Out, In, Maximum); \ + ACPI_COPY_FIELD(Out, In, TranslationOffset); \ + ACPI_COPY_FIELD(Out, In, AddressLength); \ + ACPI_COPY_FIELD(Out, In, ResourceSource); + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiRsMatchVendorResource ( + ACPI_RESOURCE *Resource, + void *Context); + +static ACPI_STATUS +AcpiRsValidateParameters ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *Buffer, + ACPI_NAMESPACE_NODE **ReturnNode); + + +/******************************************************************************* + * + * FUNCTION: AcpiRsValidateParameters + * + * PARAMETERS: DeviceHandle - Handle to a device + * Buffer - Pointer to a data buffer + * ReturnNode - Pointer to where the device node is returned + * + * RETURN: Status + * + * DESCRIPTION: Common parameter validation for resource interfaces + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiRsValidateParameters ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *Buffer, + ACPI_NAMESPACE_NODE **ReturnNode) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (RsValidateParameters); + + + /* + * Must have a valid handle to an ACPI device + */ + if (!DeviceHandle) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Node = AcpiNsValidateHandle (DeviceHandle); + if (!Node) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (Node->Type != ACPI_TYPE_DEVICE) + { + return_ACPI_STATUS (AE_TYPE); + } + + /* + * Validate the user buffer object + * + * if there is a non-zero buffer length we also need a valid pointer in + * the buffer. If it's a zero buffer length, we'll be returning the + * needed buffer size (later), so keep going. + */ + Status = AcpiUtValidateBuffer (Buffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + *ReturnNode = Node; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiGetIrqRoutingTable + * + * PARAMETERS: DeviceHandle - Handle to the Bus device we are querying + * RetBuffer - Pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the RetBuffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of RetBuffer is undefined. + * + * This function attempts to execute the _PRT method contained in + * the object indicated by the passed DeviceHandle. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetIrqRoutingTable ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiGetIrqRoutingTable); + + + /* Validate parameters then dispatch to internal routine */ + + Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiRsGetPrtMethodData (Node, RetBuffer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetIrqRoutingTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetCurrentResources + * + * PARAMETERS: DeviceHandle - Handle to the device object for the + * device we are querying + * RetBuffer - Pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the RetBuffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of RetBuffer is undefined. + * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed DeviceHandle. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetCurrentResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiGetCurrentResources); + + + /* Validate parameters then dispatch to internal routine */ + + Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiRsGetCrsMethodData (Node, RetBuffer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetCurrentResources) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetPossibleResources + * + * PARAMETERS: DeviceHandle - Handle to the device object for the + * device we are querying + * RetBuffer - Pointer to a buffer to receive the + * resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the RetBuffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of RetBuffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetPossibleResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiGetPossibleResources); + + + /* Validate parameters then dispatch to internal routine */ + + Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiRsGetPrsMethodData (Node, RetBuffer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetPossibleResources) + + +/******************************************************************************* + * + * FUNCTION: AcpiSetCurrentResources + * + * PARAMETERS: DeviceHandle - Handle to the device object for the + * device we are setting resources + * InBuffer - Pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the InBuffer variable. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetCurrentResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *InBuffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiSetCurrentResources); + + + /* Validate the buffer, don't allow zero length */ + + if ((!InBuffer) || + (!InBuffer->Pointer) || + (!InBuffer->Length)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Validate parameters then dispatch to internal routine */ + + Status = AcpiRsValidateParameters (DeviceHandle, InBuffer, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiRsSetSrsMethodData (Node, InBuffer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiSetCurrentResources) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetEventResources + * + * PARAMETERS: DeviceHandle - Handle to the device object for the + * device we are getting resources + * InBuffer - Pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the event resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the InBuffer variable. Uses the + * _AEI method. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetEventResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (AcpiGetEventResources); + + + /* Validate parameters then dispatch to internal routine */ + + Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiRsGetAeiMethodData (Node, RetBuffer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetEventResources) + + +/****************************************************************************** + * + * FUNCTION: AcpiResourceToAddress64 + * + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return buffer + * (a struct acpi_resource_address64) + * + * RETURN: Status + * + * DESCRIPTION: If the resource is an address16, address32, or address64, + * copy it to the address64 return buffer. This saves the + * caller from having to duplicate code for different-sized + * addresses. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiResourceToAddress64 ( + ACPI_RESOURCE *Resource, + ACPI_RESOURCE_ADDRESS64 *Out) +{ + ACPI_RESOURCE_ADDRESS16 *Address16; + ACPI_RESOURCE_ADDRESS32 *Address32; + + + if (!Resource || !Out) + { + return (AE_BAD_PARAMETER); + } + + /* Convert 16 or 32 address descriptor to 64 */ + + switch (Resource->Type) + { + case ACPI_RESOURCE_TYPE_ADDRESS16: + + Address16 = ACPI_CAST_PTR (ACPI_RESOURCE_ADDRESS16, &Resource->Data); + ACPI_COPY_ADDRESS (Out, Address16); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS32: + + Address32 = ACPI_CAST_PTR (ACPI_RESOURCE_ADDRESS32, &Resource->Data); + ACPI_COPY_ADDRESS (Out, Address32); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS64: + + /* Simple copy for 64 bit source */ + + ACPI_MEMCPY (Out, &Resource->Data, sizeof (ACPI_RESOURCE_ADDRESS64)); + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiResourceToAddress64) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetVendorResource + * + * PARAMETERS: DeviceHandle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * RetBuffer - Where the vendor resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Walk a resource template for the specified evice to find a + * vendor-defined resource that matches the supplied UUID and + * UUID subtype. Returns a ACPI_RESOURCE of type Vendor. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetVendorResource ( + ACPI_HANDLE DeviceHandle, + char *Name, + ACPI_VENDOR_UUID *Uuid, + ACPI_BUFFER *RetBuffer) +{ + ACPI_VENDOR_WALK_INFO Info; + ACPI_STATUS Status; + + + /* Other parameters are validated by AcpiWalkResources */ + + if (!Uuid || !RetBuffer) + { + return (AE_BAD_PARAMETER); + } + + Info.Uuid = Uuid; + Info.Buffer = RetBuffer; + Info.Status = AE_NOT_EXIST; + + /* Walk the _CRS or _PRS resource list for this device */ + + Status = AcpiWalkResources (DeviceHandle, Name, AcpiRsMatchVendorResource, + &Info); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + return (Info.Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetVendorResource) + + +/******************************************************************************* + * + * FUNCTION: AcpiRsMatchVendorResource + * + * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiRsMatchVendorResource ( + ACPI_RESOURCE *Resource, + void *Context) +{ + ACPI_VENDOR_WALK_INFO *Info = Context; + ACPI_RESOURCE_VENDOR_TYPED *Vendor; + ACPI_BUFFER *Buffer; + ACPI_STATUS Status; + + + /* Ignore all descriptors except Vendor */ + + if (Resource->Type != ACPI_RESOURCE_TYPE_VENDOR) + { + return (AE_OK); + } + + Vendor = &Resource->Data.VendorTyped; + + /* + * For a valid match, these conditions must hold: + * + * 1) Length of descriptor data must be at least as long as a UUID struct + * 2) The UUID subtypes must match + * 3) The UUID data must match + */ + if ((Vendor->ByteLength < (ACPI_UUID_LENGTH + 1)) || + (Vendor->UuidSubtype != Info->Uuid->Subtype) || + (ACPI_MEMCMP (Vendor->Uuid, Info->Uuid->Data, ACPI_UUID_LENGTH))) + { + return (AE_OK); + } + + /* Validate/Allocate/Clear caller buffer */ + + Buffer = Info->Buffer; + Status = AcpiUtInitializeBuffer (Buffer, Resource->Length); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Found the correct resource, copy and return it */ + + ACPI_MEMCPY (Buffer->Pointer, Resource, Resource->Length); + Buffer->Length = Resource->Length; + + /* Found the desired descriptor, terminate resource walk */ + + Info->Status = AE_OK; + return (AE_CTRL_TERMINATE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiWalkResources + * + * PARAMETERS: DeviceHandle - Handle to the device object for the + * device we are querying + * Name - Method name of the resources we want. + * (METHOD_NAME__CRS, METHOD_NAME__PRS, or + * METHOD_NAME__AEI) + * UserFunction - Called for each resource + * Context - Passed to UserFunction + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The UserFunction is called once for + * each resource in the list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiWalkResources ( + ACPI_HANDLE DeviceHandle, + char *Name, + ACPI_WALK_RESOURCE_CALLBACK UserFunction, + void *Context) +{ + ACPI_STATUS Status; + ACPI_BUFFER Buffer; + ACPI_RESOURCE *Resource; + ACPI_RESOURCE *ResourceEnd; + + + ACPI_FUNCTION_TRACE (AcpiWalkResources); + + + /* Parameter validation */ + + if (!DeviceHandle || !UserFunction || !Name || + (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS) && + !ACPI_COMPARE_NAME (Name, METHOD_NAME__AEI))) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the _CRS/_PRS/_AEI resource list */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Buffer now contains the resource list */ + + Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer.Pointer); + ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer.Pointer, Buffer.Length); + + /* Walk the resource list until the EndTag is found (or buffer end) */ + + while (Resource < ResourceEnd) + { + /* Sanity check the resource */ + + if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) + { + Status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + /* Invoke the user function, abort on any error returned */ + + Status = UserFunction (Resource, Context); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_TERMINATE) + { + /* This is an OK termination by the user function */ + + Status = AE_OK; + } + break; + } + + /* EndTag indicates end-of-list */ + + if (Resource->Type == ACPI_RESOURCE_TYPE_END_TAG) + { + break; + } + + /* Get the next resource descriptor */ + + Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length); + } + + ACPI_FREE (Buffer.Pointer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWalkResources) diff --git a/source/components/tables/tbfadt.c b/source/components/tables/tbfadt.c new file mode 100644 index 000000000000..ae4052099fe5 --- /dev/null +++ b/source/components/tables/tbfadt.c @@ -0,0 +1,704 @@ +/****************************************************************************** + * + * Module Name: tbfadt - FADT table utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __TBFADT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbfadt") + +/* Local prototypes */ + +static ACPI_INLINE void +AcpiTbInitGenericAddress ( + ACPI_GENERIC_ADDRESS *GenericAddress, + UINT8 SpaceId, + UINT8 ByteWidth, + UINT64 Address); + +static void +AcpiTbConvertFadt ( + void); + +static void +AcpiTbValidateFadt ( + void); + +static void +AcpiTbSetupFadtRegisters ( + void); + + +/* Table for conversion of FADT to common internal format and FADT validation */ + +typedef struct acpi_fadt_info +{ + char *Name; + UINT16 Address64; + UINT16 Address32; + UINT16 Length; + UINT8 DefaultLength; + UINT8 Type; + +} ACPI_FADT_INFO; + +#define ACPI_FADT_OPTIONAL 0 +#define ACPI_FADT_REQUIRED 1 +#define ACPI_FADT_SEPARATE_LENGTH 2 + +static ACPI_FADT_INFO FadtInfoTable[] = +{ + {"Pm1aEventBlock", + ACPI_FADT_OFFSET (XPm1aEventBlock), + ACPI_FADT_OFFSET (Pm1aEventBlock), + ACPI_FADT_OFFSET (Pm1EventLength), + ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ + ACPI_FADT_REQUIRED}, + + {"Pm1bEventBlock", + ACPI_FADT_OFFSET (XPm1bEventBlock), + ACPI_FADT_OFFSET (Pm1bEventBlock), + ACPI_FADT_OFFSET (Pm1EventLength), + ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ + ACPI_FADT_OPTIONAL}, + + {"Pm1aControlBlock", + ACPI_FADT_OFFSET (XPm1aControlBlock), + ACPI_FADT_OFFSET (Pm1aControlBlock), + ACPI_FADT_OFFSET (Pm1ControlLength), + ACPI_PM1_REGISTER_WIDTH, + ACPI_FADT_REQUIRED}, + + {"Pm1bControlBlock", + ACPI_FADT_OFFSET (XPm1bControlBlock), + ACPI_FADT_OFFSET (Pm1bControlBlock), + ACPI_FADT_OFFSET (Pm1ControlLength), + ACPI_PM1_REGISTER_WIDTH, + ACPI_FADT_OPTIONAL}, + + {"Pm2ControlBlock", + ACPI_FADT_OFFSET (XPm2ControlBlock), + ACPI_FADT_OFFSET (Pm2ControlBlock), + ACPI_FADT_OFFSET (Pm2ControlLength), + ACPI_PM2_REGISTER_WIDTH, + ACPI_FADT_SEPARATE_LENGTH}, + + {"PmTimerBlock", + ACPI_FADT_OFFSET (XPmTimerBlock), + ACPI_FADT_OFFSET (PmTimerBlock), + ACPI_FADT_OFFSET (PmTimerLength), + ACPI_PM_TIMER_WIDTH, + ACPI_FADT_REQUIRED}, + + {"Gpe0Block", + ACPI_FADT_OFFSET (XGpe0Block), + ACPI_FADT_OFFSET (Gpe0Block), + ACPI_FADT_OFFSET (Gpe0BlockLength), + 0, + ACPI_FADT_SEPARATE_LENGTH}, + + {"Gpe1Block", + ACPI_FADT_OFFSET (XGpe1Block), + ACPI_FADT_OFFSET (Gpe1Block), + ACPI_FADT_OFFSET (Gpe1BlockLength), + 0, + ACPI_FADT_SEPARATE_LENGTH} +}; + +#define ACPI_FADT_INFO_ENTRIES \ + (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO)) + + +/* Table used to split Event Blocks into separate status/enable registers */ + +typedef struct acpi_fadt_pm_info +{ + ACPI_GENERIC_ADDRESS *Target; + UINT16 Source; + UINT8 RegisterNum; + +} ACPI_FADT_PM_INFO; + +static ACPI_FADT_PM_INFO FadtPmInfoTable[] = +{ + {&AcpiGbl_XPm1aStatus, + ACPI_FADT_OFFSET (XPm1aEventBlock), + 0}, + + {&AcpiGbl_XPm1aEnable, + ACPI_FADT_OFFSET (XPm1aEventBlock), + 1}, + + {&AcpiGbl_XPm1bStatus, + ACPI_FADT_OFFSET (XPm1bEventBlock), + 0}, + + {&AcpiGbl_XPm1bEnable, + ACPI_FADT_OFFSET (XPm1bEventBlock), + 1} +}; + +#define ACPI_FADT_PM_INFO_ENTRIES \ + (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO)) + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInitGenericAddress + * + * PARAMETERS: GenericAddress - GAS struct to be initialized + * SpaceId - ACPI Space ID for this register + * ByteWidth - Width of this register, in bytes + * Address - Address of the register + * + * RETURN: None + * + * DESCRIPTION: Initialize a Generic Address Structure (GAS) + * See the ACPI specification for a full description and + * definition of this structure. + * + ******************************************************************************/ + +static ACPI_INLINE void +AcpiTbInitGenericAddress ( + ACPI_GENERIC_ADDRESS *GenericAddress, + UINT8 SpaceId, + UINT8 ByteWidth, + UINT64 Address) +{ + + /* + * The 64-bit Address field is non-aligned in the byte packed + * GAS struct. + */ + ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address); + + /* All other fields are byte-wide */ + + GenericAddress->SpaceId = SpaceId; + GenericAddress->BitWidth = (UINT8) ACPI_MUL_8 (ByteWidth); + GenericAddress->BitOffset = 0; + GenericAddress->AccessWidth = 0; /* Access width ANY */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbParseFadt + * + * PARAMETERS: TableIndex - Index for the FADT + * + * RETURN: None + * + * DESCRIPTION: Initialize the FADT, DSDT and FACS tables + * (FADT contains the addresses of the DSDT and FACS) + * + ******************************************************************************/ + +void +AcpiTbParseFadt ( + UINT32 TableIndex) +{ + UINT32 Length; + ACPI_TABLE_HEADER *Table; + + + /* + * The FADT has multiple versions with different lengths, + * and it contains pointers to both the DSDT and FACS tables. + * + * Get a local copy of the FADT and convert it to a common format + * Map entire FADT, assumed to be smaller than one page. + */ + Length = AcpiGbl_RootTableList.Tables[TableIndex].Length; + + Table = AcpiOsMapMemory ( + AcpiGbl_RootTableList.Tables[TableIndex].Address, Length); + if (!Table) + { + return; + } + + /* + * Validate the FADT checksum before we copy the table. Ignore + * checksum error as we want to try to get the DSDT and FACS. + */ + (void) AcpiTbVerifyChecksum (Table, Length); + + /* Create a local copy of the FADT in common ACPI 2.0+ format */ + + AcpiTbCreateLocalFadt (Table, Length); + + /* All done with the real FADT, unmap it */ + + AcpiOsUnmapMemory (Table, Length); + + /* Obtain the DSDT and FACS tables via their addresses within the FADT */ + + AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, + ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + + /* If Hardware Reduced flag is set, there is no FACS */ + + if (!AcpiGbl_ReducedHardware) + { + AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, + ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCreateLocalFadt + * + * PARAMETERS: Table - Pointer to BIOS FADT + * Length - Length of the table + * + * RETURN: None + * + * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. + * Performs validation on some important FADT fields. + * + * NOTE: We create a local copy of the FADT regardless of the version. + * + ******************************************************************************/ + +void +AcpiTbCreateLocalFadt ( + ACPI_TABLE_HEADER *Table, + UINT32 Length) +{ + + /* + * Check if the FADT is larger than the largest table that we expect + * (the ACPI 5.0 version). If so, truncate the table, and issue + * a warning. + */ + if (Length > sizeof (ACPI_TABLE_FADT)) + { + ACPI_WARNING ((AE_INFO, + "FADT (revision %u) is longer than ACPI 5.0 version, " + "truncating length %u to %u", + Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT))); + } + + /* Clear the entire local FADT */ + + ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); + + /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */ + + ACPI_MEMCPY (&AcpiGbl_FADT, Table, + ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT))); + + /* Take a copy of the Hardware Reduced flag */ + + AcpiGbl_ReducedHardware = FALSE; + if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED) + { + AcpiGbl_ReducedHardware = TRUE; + } + + /* Convert the local copy of the FADT to the common internal format */ + + AcpiTbConvertFadt (); + + /* Validate FADT values now, before we make any changes */ + + AcpiTbValidateFadt (); + + /* Initialize the global ACPI register structures */ + + AcpiTbSetupFadtRegisters (); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbConvertFadt + * + * PARAMETERS: None, uses AcpiGbl_FADT + * + * RETURN: None + * + * DESCRIPTION: Converts all versions of the FADT to a common internal format. + * Expand 32-bit addresses to 64-bit as necessary. + * + * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), + * and must contain a copy of the actual FADT. + * + * Notes on 64-bit register addresses: + * + * After this FADT conversion, later ACPICA code will only use the 64-bit "X" + * fields of the FADT for all ACPI register addresses. + * + * The 64-bit "X" fields are optional extensions to the original 32-bit FADT + * V1.0 fields. Even if they are present in the FADT, they are optional and + * are unused if the BIOS sets them to zero. Therefore, we must copy/expand + * 32-bit V1.0 fields if the corresponding X field is zero. + * + * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the + * corresponding "X" fields in the internal FADT. + * + * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded + * to the corresponding 64-bit X fields. For compatibility with other ACPI + * implementations, we ignore the 64-bit field if the 32-bit field is valid, + * regardless of whether the host OS is 32-bit or 64-bit. + * + ******************************************************************************/ + +static void +AcpiTbConvertFadt ( + void) +{ + ACPI_GENERIC_ADDRESS *Address64; + UINT32 Address32; + UINT32 i; + + + /* Update the local FADT table header length */ + + AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); + + /* + * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Later code will always use the X 64-bit field. + */ + if (!AcpiGbl_FADT.XFacs) + { + AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs; + } + if (!AcpiGbl_FADT.XDsdt) + { + AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt; + } + + /* + * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which + * should be zero are indeed zero. This will workaround BIOSs that + * inadvertently place values in these fields. + * + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located + * at offset 45, 55, 95, and the word located at offset 109, 110. + * + * Note: The FADT revision value is unreliable. Only the length can be + * trusted. + */ + if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE) + { + AcpiGbl_FADT.PreferredProfile = 0; + AcpiGbl_FADT.PstateControl = 0; + AcpiGbl_FADT.CstControl = 0; + AcpiGbl_FADT.BootFlags = 0; + } + + /* + * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. Later code will always use + * the 64-bit address structures. + * + * March 2009: + * We now always use the 32-bit address if it is valid (non-null). This + * is not in accordance with the ACPI specification which states that + * the 64-bit address supersedes the 32-bit version, but we do this for + * compatibility with other ACPI implementations. Most notably, in the + * case where both the 32 and 64 versions are non-null, we use the 32-bit + * version. This is the only address that is guaranteed to have been + * tested by the BIOS manufacturer. + */ + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) + { + Address32 = *ACPI_ADD_PTR (UINT32, + &AcpiGbl_FADT, FadtInfoTable[i].Address32); + + Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, + &AcpiGbl_FADT, FadtInfoTable[i].Address64); + + /* + * If both 32- and 64-bit addresses are valid (non-zero), + * they must match. + */ + if (Address64->Address && Address32 && + (Address64->Address != (UINT64) Address32)) + { + ACPI_ERROR ((AE_INFO, + "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32", + FadtInfoTable[i].Name, Address32, + ACPI_FORMAT_UINT64 (Address64->Address))); + } + + /* Always use 32-bit address if it is valid (non-null) */ + + if (Address32) + { + /* + * Copy the 32-bit address to the 64-bit GAS structure. The + * Space ID is always I/O for 32-bit legacy address fields + */ + AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO, + *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length), + (UINT64) Address32); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbValidateFadt + * + * PARAMETERS: Table - Pointer to the FADT to be validated + * + * RETURN: None + * + * DESCRIPTION: Validate various important fields within the FADT. If a problem + * is found, issue a message, but no status is returned. + * Used by both the table manager and the disassembler. + * + * Possible additional checks: + * (AcpiGbl_FADT.Pm1EventLength >= 4) + * (AcpiGbl_FADT.Pm1ControlLength >= 2) + * (AcpiGbl_FADT.PmTimerLength >= 4) + * Gpe block lengths must be multiple of 2 + * + ******************************************************************************/ + +static void +AcpiTbValidateFadt ( + void) +{ + char *Name; + ACPI_GENERIC_ADDRESS *Address64; + UINT8 Length; + UINT32 i; + + + /* + * Check for FACS and DSDT address mismatches. An address mismatch between + * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and + * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. + */ + if (AcpiGbl_FADT.Facs && + (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs)) + { + ACPI_WARNING ((AE_INFO, + "32/64X FACS address mismatch in FADT - " + "0x%8.8X/0x%8.8X%8.8X, using 32", + AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs))); + + AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs; + } + + if (AcpiGbl_FADT.Dsdt && + (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt)) + { + ACPI_WARNING ((AE_INFO, + "32/64X DSDT address mismatch in FADT - " + "0x%8.8X/0x%8.8X%8.8X, using 32", + AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt))); + + AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt; + } + + /* If Hardware Reduced flag is set, we are all done */ + + if (AcpiGbl_ReducedHardware) + { + return; + } + + /* Examine all of the 64-bit extended address fields (X fields) */ + + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) + { + /* + * Generate pointer to the 64-bit address, get the register + * length (width) and the register name + */ + Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, + &AcpiGbl_FADT, FadtInfoTable[i].Address64); + Length = *ACPI_ADD_PTR (UINT8, + &AcpiGbl_FADT, FadtInfoTable[i].Length); + Name = FadtInfoTable[i].Name; + + /* + * For each extended field, check for length mismatch between the + * legacy length field and the corresponding 64-bit X length field. + */ + if (Address64->Address && + (Address64->BitWidth != ACPI_MUL_8 (Length))) + { + ACPI_WARNING ((AE_INFO, + "32/64X length mismatch in %s: %u/%u", + Name, ACPI_MUL_8 (Length), Address64->BitWidth)); + } + + if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED) + { + /* + * Field is required (PM1aEvent, PM1aControl, PmTimer). + * Both the address and length must be non-zero. + */ + if (!Address64->Address || !Length) + { + ACPI_ERROR ((AE_INFO, + "Required field %s has zero address and/or length:" + " 0x%8.8X%8.8X/0x%X", + Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); + } + } + else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH) + { + /* + * Field is optional (PM2Control, GPE0, GPE1) AND has its own + * length field. If present, both the address and length must + * be valid. + */ + if ((Address64->Address && !Length) || + (!Address64->Address && Length)) + { + ACPI_WARNING ((AE_INFO, + "Optional field %s has zero address or length: " + "0x%8.8X%8.8X/0x%X", + Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); + } + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbSetupFadtRegisters + * + * PARAMETERS: None, uses AcpiGbl_FADT. + * + * RETURN: None + * + * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, + * force FADT register definitions to their default lengths. + * + ******************************************************************************/ + +static void +AcpiTbSetupFadtRegisters ( + void) +{ + ACPI_GENERIC_ADDRESS *Target64; + ACPI_GENERIC_ADDRESS *Source64; + UINT8 Pm1RegisterByteWidth; + UINT32 i; + + + /* + * Optionally check all register lengths against the default values and + * update them if they are incorrect. + */ + if (AcpiGbl_UseDefaultRegisterWidths) + { + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) + { + Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, + FadtInfoTable[i].Address64); + + /* + * If a valid register (Address != 0) and the (DefaultLength > 0) + * (Not a GPE register), then check the width against the default. + */ + if ((Target64->Address) && + (FadtInfoTable[i].DefaultLength > 0) && + (FadtInfoTable[i].DefaultLength != Target64->BitWidth)) + { + ACPI_WARNING ((AE_INFO, + "Invalid length for %s: %u, using default %u", + FadtInfoTable[i].Name, Target64->BitWidth, + FadtInfoTable[i].DefaultLength)); + + /* Incorrect size, set width to the default */ + + Target64->BitWidth = FadtInfoTable[i].DefaultLength; + } + } + } + + /* + * Get the length of the individual PM1 registers (enable and status). + * Each register is defined to be (event block length / 2). Extra divide + * by 8 converts bits to bytes. + */ + Pm1RegisterByteWidth = (UINT8) + ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth); + + /* + * Calculate separate GAS structs for the PM1x (A/B) Status and Enable + * registers. These addresses do not appear (directly) in the FADT, so it + * is useful to pre-calculate them from the PM1 Event Block definitions. + * + * The PM event blocks are split into two register blocks, first is the + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (Pm1EventLength/2) + * + * Note: The PM1A event block is required by the ACPI specification. + * However, the PM1B event block is optional and is rarely, if ever, + * used. + */ + + for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) + { + Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, + FadtPmInfoTable[i].Source); + + if (Source64->Address) + { + AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target, + Source64->SpaceId, Pm1RegisterByteWidth, + Source64->Address + + (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth)); + } + } +} + diff --git a/source/components/tables/tbfind.c b/source/components/tables/tbfind.c new file mode 100644 index 000000000000..d7e2440b32ac --- /dev/null +++ b/source/components/tables/tbfind.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * Module Name: tbfind - find table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __TBFIND_C__ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbfind") + + +/******************************************************************************* + * + * FUNCTION: AcpiTbFindTable + * + * PARAMETERS: Signature - String with ACPI table signature + * OemId - String with the table OEM ID + * OemTableId - String with the OEM Table ID + * TableIndex - Where the table index is returned + * + * RETURN: Status and table index + * + * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the + * Signature, OEM ID and OEM Table ID. Returns an index that can + * be used to get the table header or entire table. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbFindTable ( + char *Signature, + char *OemId, + char *OemTableId, + UINT32 *TableIndex) +{ + UINT32 i; + ACPI_STATUS Status; + ACPI_TABLE_HEADER Header; + + + ACPI_FUNCTION_TRACE (TbFindTable); + + + /* Normalize the input strings */ + + ACPI_MEMSET (&Header, 0, sizeof (ACPI_TABLE_HEADER)); + ACPI_STRNCPY (Header.Signature, Signature, ACPI_NAME_SIZE); + ACPI_STRNCPY (Header.OemId, OemId, ACPI_OEM_ID_SIZE); + ACPI_STRNCPY (Header.OemTableId, OemTableId, ACPI_OEM_TABLE_ID_SIZE); + + /* Search for the table */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + if (ACPI_MEMCMP (&(AcpiGbl_RootTableList.Tables[i].Signature), + Header.Signature, ACPI_NAME_SIZE)) + { + /* Not the requested table */ + + continue; + } + + /* Table with matching signature has been found */ + + if (!AcpiGbl_RootTableList.Tables[i].Pointer) + { + /* Table is not currently mapped, map it */ + + Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (!AcpiGbl_RootTableList.Tables[i].Pointer) + { + continue; + } + } + + /* Check for table match on all IDs */ + + if (!ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->Signature, + Header.Signature, ACPI_NAME_SIZE) && + (!OemId[0] || + !ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->OemId, + Header.OemId, ACPI_OEM_ID_SIZE)) && + (!OemTableId[0] || + !ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->OemTableId, + Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE))) + { + *TableIndex = i; + + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n", + Header.Signature)); + return_ACPI_STATUS (AE_OK); + } + } + + return_ACPI_STATUS (AE_NOT_FOUND); +} diff --git a/source/components/tables/tbinstal.c b/source/components/tables/tbinstal.c new file mode 100644 index 000000000000..5c6bd876f819 --- /dev/null +++ b/source/components/tables/tbinstal.c @@ -0,0 +1,806 @@ +/****************************************************************************** + * + * Module Name: tbinstal - ACPI table installation and removal + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __TBINSTAL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbinstal") + + +/****************************************************************************** + * + * FUNCTION: AcpiTbVerifyTable + * + * PARAMETERS: TableDesc - table + * + * RETURN: Status + * + * DESCRIPTION: this function is called to verify and map table + * + *****************************************************************************/ + +ACPI_STATUS +AcpiTbVerifyTable ( + ACPI_TABLE_DESC *TableDesc) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (TbVerifyTable); + + + /* Map the table if necessary */ + + if (!TableDesc->Pointer) + { + if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_MAPPED) + { + TableDesc->Pointer = AcpiOsMapMemory ( + TableDesc->Address, TableDesc->Length); + } + + if (!TableDesc->Pointer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + /* FACS is the odd table, has no standard ACPI header and no checksum */ + + if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS)) + { + /* Always calculate checksum, ignore bad checksum if requested */ + + Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbAddTable + * + * PARAMETERS: TableDesc - Table descriptor + * TableIndex - Where the table index is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to add an ACPI table. It is used to + * dynamically load tables via the Load and LoadTable AML + * operators. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbAddTable ( + ACPI_TABLE_DESC *TableDesc, + UINT32 *TableIndex) +{ + UINT32 i; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (TbAddTable); + + + if (!TableDesc->Pointer) + { + Status = AcpiTbVerifyTable (TableDesc); + if (ACPI_FAILURE (Status) || !TableDesc->Pointer) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Validate the incoming table signature. + * + * 1) Originally, we checked the table signature for "SSDT" or "PSDT". + * 2) We added support for OEMx tables, signature "OEM". + * 3) Valid tables were encountered with a null signature, so we just + * gave up on validating the signature, (05/2008). + * 4) We encountered non-AML tables such as the MADT, which caused + * interpreter errors and kernel faults. So now, we once again allow + * only "SSDT", "OEMx", and now, also a null signature. (05/2011). + */ + if ((TableDesc->Pointer->Signature[0] != 0x00) && + (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) && + (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3))) + { + ACPI_ERROR ((AE_INFO, + "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx", + AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ? + TableDesc->Pointer->Signature : "????", + *(UINT32 *) TableDesc->Pointer->Signature)); + + return_ACPI_STATUS (AE_BAD_SIGNATURE); + } + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Check if table is already registered */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + if (!AcpiGbl_RootTableList.Tables[i].Pointer) + { + Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); + if (ACPI_FAILURE (Status) || + !AcpiGbl_RootTableList.Tables[i].Pointer) + { + continue; + } + } + + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length) + { + continue; + } + + if (ACPI_MEMCMP (TableDesc->Pointer, + AcpiGbl_RootTableList.Tables[i].Pointer, + AcpiGbl_RootTableList.Tables[i].Length)) + { + continue; + } + + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + + /* + * Table is already registered. + * We can delete the table that was passed as a parameter. + */ + AcpiTbDeleteTable (TableDesc); + *TableIndex = i; + + if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) + { + /* Table is still loaded, this is an error */ + + Status = AE_ALREADY_EXISTS; + goto Release; + } + else + { + /* Table was unloaded, allow it to be reloaded */ + + TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer; + TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address; + Status = AE_OK; + goto PrintHeader; + } + } + + /* + * ACPI Table Override: + * Allow the host to override dynamically loaded tables. + * NOTE: the table is fully mapped at this point, and the mapping will + * be deleted by TbTableOverride if the table is actually overridden. + */ + (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc); + + /* Add the table to the global root table list */ + + Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer, + TableDesc->Length, TableDesc->Flags, TableIndex); + if (ACPI_FAILURE (Status)) + { + goto Release; + } + +PrintHeader: + AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); + +Release: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbTableOverride + * + * PARAMETERS: TableHeader - Header for the original table + * TableDesc - Table descriptor initialized for the + * original table. May or may not be mapped. + * + * RETURN: Pointer to the entire new table. NULL if table not overridden. + * If overridden, installs the new table within the input table + * descriptor. + * + * DESCRIPTION: Attempt table override by calling the OSL override functions. + * Note: If the table is overridden, then the entire new table + * is mapped and returned by this function. + * + ******************************************************************************/ + +ACPI_TABLE_HEADER * +AcpiTbTableOverride ( + ACPI_TABLE_HEADER *TableHeader, + ACPI_TABLE_DESC *TableDesc) +{ + ACPI_STATUS Status; + ACPI_TABLE_HEADER *NewTable = NULL; + ACPI_PHYSICAL_ADDRESS NewAddress = 0; + UINT32 NewTableLength = 0; + UINT8 NewFlags; + char *OverrideType; + + + /* (1) Attempt logical override (returns a logical address) */ + + Status = AcpiOsTableOverride (TableHeader, &NewTable); + if (ACPI_SUCCESS (Status) && NewTable) + { + NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable); + NewTableLength = NewTable->Length; + NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE; + OverrideType = "Logical"; + goto FinishOverride; + } + + /* (2) Attempt physical override (returns a physical address) */ + + Status = AcpiOsPhysicalTableOverride (TableHeader, + &NewAddress, &NewTableLength); + if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength) + { + /* Map the entire new table */ + + NewTable = AcpiOsMapMemory (NewAddress, NewTableLength); + if (!NewTable) + { + ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, + "%4.4s %p Attempted physical table override failed", + TableHeader->Signature, + ACPI_CAST_PTR (void, TableDesc->Address))); + return (NULL); + } + + OverrideType = "Physical"; + NewFlags = ACPI_TABLE_ORIGIN_MAPPED; + goto FinishOverride; + } + + return (NULL); /* There was no override */ + + +FinishOverride: + + ACPI_INFO ((AE_INFO, + "%4.4s %p %s table override, new table: %p", + TableHeader->Signature, + ACPI_CAST_PTR (void, TableDesc->Address), + OverrideType, NewTable)); + + /* We can now unmap/delete the original table (if fully mapped) */ + + AcpiTbDeleteTable (TableDesc); + + /* Setup descriptor for the new table */ + + TableDesc->Address = NewAddress; + TableDesc->Pointer = NewTable; + TableDesc->Length = NewTableLength; + TableDesc->Flags = NewFlags; + + return (NewTable); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbResizeRootTableList + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Expand the size of global table array + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbResizeRootTableList ( + void) +{ + ACPI_TABLE_DESC *Tables; + + + ACPI_FUNCTION_TRACE (TbResizeRootTableList); + + + /* AllowResize flag is a parameter to AcpiInitializeTables */ + + if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE)) + { + ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed")); + return_ACPI_STATUS (AE_SUPPORT); + } + + /* Increase the Table Array size */ + + Tables = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof (ACPI_TABLE_DESC)); + if (!Tables) + { + ACPI_ERROR ((AE_INFO, "Could not allocate new root table array")); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy and free the previous table array */ + + if (AcpiGbl_RootTableList.Tables) + { + ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, + (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC)); + + if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) + { + ACPI_FREE (AcpiGbl_RootTableList.Tables); + } + } + + AcpiGbl_RootTableList.Tables = Tables; + AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT; + AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED; + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbStoreTable + * + * PARAMETERS: Address - Table address + * Table - Table header + * Length - Table length + * Flags - flags + * + * RETURN: Status and table index. + * + * DESCRIPTION: Add an ACPI table to the global table list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbStoreTable ( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Table, + UINT32 Length, + UINT8 Flags, + UINT32 *TableIndex) +{ + ACPI_STATUS Status; + ACPI_TABLE_DESC *NewTable; + + + /* Ensure that there is room for the table in the Root Table List */ + + if (AcpiGbl_RootTableList.CurrentTableCount >= + AcpiGbl_RootTableList.MaxTableCount) + { + Status = AcpiTbResizeRootTableList(); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount]; + + /* Initialize added table */ + + NewTable->Address = Address; + NewTable->Pointer = Table; + NewTable->Length = Length; + NewTable->OwnerId = 0; + NewTable->Flags = Flags; + + ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature); + + *TableIndex = AcpiGbl_RootTableList.CurrentTableCount; + AcpiGbl_RootTableList.CurrentTableCount++; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbDeleteTable + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: None + * + * DESCRIPTION: Delete one internal ACPI table + * + ******************************************************************************/ + +void +AcpiTbDeleteTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + /* Table must be mapped or allocated */ + + if (!TableDesc->Pointer) + { + return; + } + + switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_MAPPED: + AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length); + break; + + case ACPI_TABLE_ORIGIN_ALLOCATED: + ACPI_FREE (TableDesc->Pointer); + break; + + default: + break; + } + + TableDesc->Pointer = NULL; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbTerminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void +AcpiTbTerminate ( + void) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE (TbTerminate); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Delete the individual tables */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]); + } + + /* + * Delete the root table array if allocated locally. Array cannot be + * mapped, so we don't need to check for that flag. + */ + if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) + { + ACPI_FREE (AcpiGbl_RootTableList.Tables); + } + + AcpiGbl_RootTableList.Tables = NULL; + AcpiGbl_RootTableList.Flags = 0; + AcpiGbl_RootTableList.CurrentTableCount = 0; + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbDeleteNamespaceByOwner + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: Status + * + * DESCRIPTION: Delete all namespace objects created when this table was loaded. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbDeleteNamespaceByOwner ( + UINT32 TableIndex) +{ + ACPI_OWNER_ID OwnerId; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) + { + /* The table index does not exist */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Get the owner ID for this table, used to delete namespace nodes */ + + OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + + /* + * Need to acquire the namespace writer lock to prevent interference + * with any concurrent namespace walks. The interpreter must be + * released during the deletion since the acquisition of the deletion + * lock may block, and also since the execution of a namespace walk + * must be allowed to use the interpreter. + */ + (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); + Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock); + + AcpiNsDeleteNamespaceByOwner (OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock); + + Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbAllocateOwnerId + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: Status + * + * DESCRIPTION: Allocates OwnerId in TableDesc + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbAllocateOwnerId ( + UINT32 TableIndex) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + + + ACPI_FUNCTION_TRACE (TbAllocateOwnerId); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) + { + Status = AcpiUtAllocateOwnerId + (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbReleaseOwnerId + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: Status + * + * DESCRIPTION: Releases OwnerId in TableDesc + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbReleaseOwnerId ( + UINT32 TableIndex) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + + + ACPI_FUNCTION_TRACE (TbReleaseOwnerId); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) + { + AcpiUtReleaseOwnerId ( + &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); + Status = AE_OK; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbGetOwnerId + * + * PARAMETERS: TableIndex - Table index + * OwnerId - Where the table OwnerId is returned + * + * RETURN: Status + * + * DESCRIPTION: returns OwnerId for the ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbGetOwnerId ( + UINT32 TableIndex, + ACPI_OWNER_ID *OwnerId) +{ + ACPI_STATUS Status = AE_BAD_PARAMETER; + + + ACPI_FUNCTION_TRACE (TbGetOwnerId); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) + { + *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; + Status = AE_OK; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbIsTableLoaded + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: Table Loaded Flag + * + ******************************************************************************/ + +BOOLEAN +AcpiTbIsTableLoaded ( + UINT32 TableIndex) +{ + BOOLEAN IsLoaded = FALSE; + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) + { + IsLoaded = (BOOLEAN) + (AcpiGbl_RootTableList.Tables[TableIndex].Flags & + ACPI_TABLE_IS_LOADED); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return (IsLoaded); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbSetTableLoadedFlag + * + * PARAMETERS: TableIndex - Table index + * IsLoaded - TRUE if table is loaded, FALSE otherwise + * + * RETURN: None + * + * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * + ******************************************************************************/ + +void +AcpiTbSetTableLoadedFlag ( + UINT32 TableIndex, + BOOLEAN IsLoaded) +{ + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) + { + if (IsLoaded) + { + AcpiGbl_RootTableList.Tables[TableIndex].Flags |= + ACPI_TABLE_IS_LOADED; + } + else + { + AcpiGbl_RootTableList.Tables[TableIndex].Flags &= + ~ACPI_TABLE_IS_LOADED; + } + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +} + diff --git a/source/components/tables/tbutils.c b/source/components/tables/tbutils.c new file mode 100644 index 000000000000..bfdcf0c29832 --- /dev/null +++ b/source/components/tables/tbutils.c @@ -0,0 +1,760 @@ +/****************************************************************************** + * + * Module Name: tbutils - table utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __TBUTILS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbutils") + + +/* Local prototypes */ + +static void +AcpiTbFixString ( + char *String, + ACPI_SIZE Length); + +static void +AcpiTbCleanupTableHeader ( + ACPI_TABLE_HEADER *OutHeader, + ACPI_TABLE_HEADER *Header); + +static ACPI_PHYSICAL_ADDRESS +AcpiTbGetRootTableEntry ( + UINT8 *TableEntry, + UINT32 TableEntrySize); + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiTbInitializeFacs + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global + * for accessing the Global Lock and Firmware Waking Vector + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbInitializeFacs ( + void) +{ + ACPI_STATUS Status; + + + /* If Hardware Reduced flag is set, there is no FACS */ + + if (AcpiGbl_ReducedHardware) + { + AcpiGbl_FACS = NULL; + return (AE_OK); + } + + Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); + return (Status); +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiTbTablesLoaded + * + * PARAMETERS: None + * + * RETURN: TRUE if required ACPI tables are loaded + * + * DESCRIPTION: Determine if the minimum required ACPI tables are present + * (FADT, FACS, DSDT) + * + ******************************************************************************/ + +BOOLEAN +AcpiTbTablesLoaded ( + void) +{ + + if (AcpiGbl_RootTableList.CurrentTableCount >= 3) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbFixString + * + * PARAMETERS: String - String to be repaired + * Length - Maximum length + * + * RETURN: None + * + * DESCRIPTION: Replace every non-printable or non-ascii byte in the string + * with a question mark '?'. + * + ******************************************************************************/ + +static void +AcpiTbFixString ( + char *String, + ACPI_SIZE Length) +{ + + while (Length && *String) + { + if (!ACPI_IS_PRINT (*String)) + { + *String = '?'; + } + String++; + Length--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCleanupTableHeader + * + * PARAMETERS: OutHeader - Where the cleaned header is returned + * Header - Input ACPI table header + * + * RETURN: Returns the cleaned header in OutHeader + * + * DESCRIPTION: Copy the table header and ensure that all "string" fields in + * the header consist of printable characters. + * + ******************************************************************************/ + +static void +AcpiTbCleanupTableHeader ( + ACPI_TABLE_HEADER *OutHeader, + ACPI_TABLE_HEADER *Header) +{ + + ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); + + AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE); + AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); + AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE); + AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbPrintTableHeader + * + * PARAMETERS: Address - Table physical address + * Header - Table header + * + * RETURN: None + * + * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. + * + ******************************************************************************/ + +void +AcpiTbPrintTableHeader ( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Header) +{ + ACPI_TABLE_HEADER LocalHeader; + + + /* + * The reason that the Address is cast to a void pointer is so that we + * can use %p which will work properly on both 32-bit and 64-bit hosts. + */ + if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) + { + /* FACS only has signature and length fields */ + + ACPI_INFO ((AE_INFO, "%4.4s %p %05X", + Header->Signature, ACPI_CAST_PTR (void, Address), + Header->Length)); + } + else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) + { + /* RSDP has no common fields */ + + ACPI_MEMCPY (LocalHeader.OemId, + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE); + AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); + + ACPI_INFO ((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_CAST_PTR (void, Address), + (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, + ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, + LocalHeader.OemId)); + } + else + { + /* Standard ACPI table with full common header */ + + AcpiTbCleanupTableHeader (&LocalHeader, Header); + + ACPI_INFO ((AE_INFO, + "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + LocalHeader.Signature, ACPI_CAST_PTR (void, Address), + LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId, + LocalHeader.OemTableId, LocalHeader.OemRevision, + LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbValidateChecksum + * + * PARAMETERS: Table - ACPI table to verify + * Length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbVerifyChecksum ( + ACPI_TABLE_HEADER *Table, + UINT32 Length) +{ + UINT8 Checksum; + + + /* Compute the checksum on the table */ + + Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); + + /* Checksum ok? (should be zero) */ + + if (Checksum) + { + ACPI_WARNING ((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", + Table->Signature, Table->Checksum, + (UINT8) (Table->Checksum - Checksum))); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbChecksum + * + * PARAMETERS: Buffer - Pointer to memory region to be checked + * Length - Length of this memory region + * + * RETURN: Checksum (UINT8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ + +UINT8 +AcpiTbChecksum ( + UINT8 *Buffer, + UINT32 Length) +{ + UINT8 Sum = 0; + UINT8 *End = Buffer + Length; + + + while (Buffer < End) + { + Sum = (UINT8) (Sum + *(Buffer++)); + } + + return Sum; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCheckDsdtHeader + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect + * if the DSDT has been replaced from outside the OS and/or if + * the DSDT header has been corrupted. + * + ******************************************************************************/ + +void +AcpiTbCheckDsdtHeader ( + void) +{ + + /* Compare original length and checksum to current values */ + + if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || + AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) + { + ACPI_ERROR ((AE_INFO, + "The DSDT has been corrupted or replaced - old, new headers below")); + AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); + AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); + + /* Disable further error messages */ + + AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; + AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCopyDsdt + * + * PARAMETERS: TableDesc - Installed table to copy + * + * RETURN: None + * + * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. + * Some very bad BIOSs are known to either corrupt the DSDT or + * install a new, bad DSDT. This copy works around the problem. + * + ******************************************************************************/ + +ACPI_TABLE_HEADER * +AcpiTbCopyDsdt ( + UINT32 TableIndex) +{ + ACPI_TABLE_HEADER *NewTable; + ACPI_TABLE_DESC *TableDesc; + + + TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; + + NewTable = ACPI_ALLOCATE (TableDesc->Length); + if (!NewTable) + { + ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", + TableDesc->Length)); + return (NULL); + } + + ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); + AcpiTbDeleteTable (TableDesc); + TableDesc->Pointer = NewTable; + TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + ACPI_INFO ((AE_INFO, + "Forced DSDT copy: length 0x%05X copied locally, original unmapped", + NewTable->Length)); + + return (NewTable); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInstallTable + * + * PARAMETERS: Address - Physical address of DSDT or FACS + * Signature - Table signature, NULL if no need to + * match + * TableIndex - Index into root table array + * + * RETURN: None + * + * DESCRIPTION: Install an ACPI table into the global data structure. The + * table override mechanism is called to allow the host + * OS to replace any table before it is installed in the root + * table array. + * + ******************************************************************************/ + +void +AcpiTbInstallTable ( + ACPI_PHYSICAL_ADDRESS Address, + char *Signature, + UINT32 TableIndex) +{ + ACPI_TABLE_HEADER *Table; + ACPI_TABLE_HEADER *FinalTable; + ACPI_TABLE_DESC *TableDesc; + + + if (!Address) + { + ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", + Signature)); + return; + } + + /* Map just the table header */ + + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) + { + ACPI_ERROR ((AE_INFO, "Could not map memory for table [%s] at %p", + Signature, ACPI_CAST_PTR (void, Address))); + return; + } + + /* If a particular signature is expected (DSDT/FACS), it must match */ + + if (Signature && + !ACPI_COMPARE_NAME (Table->Signature, Signature)) + { + ACPI_ERROR ((AE_INFO, + "Invalid signature 0x%X for ACPI table, expected [%s]", + *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); + goto UnmapAndExit; + } + + /* + * Initialize the table entry. Set the pointer to NULL, since the + * table is not fully mapped at this time. + */ + TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; + + TableDesc->Address = Address; + TableDesc->Pointer = NULL; + TableDesc->Length = Table->Length; + TableDesc->Flags = ACPI_TABLE_ORIGIN_MAPPED; + ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); + + /* + * ACPI Table Override: + * + * Before we install the table, let the host OS override it with a new + * one if desired. Any table within the RSDT/XSDT can be replaced, + * including the DSDT which is pointed to by the FADT. + * + * NOTE: If the table is overridden, then FinalTable will contain a + * mapped pointer to the full new table. If the table is not overridden, + * then the table will be fully mapped elsewhere (in verify table). + * In any case, we must unmap the header that was mapped above. + */ + FinalTable = AcpiTbTableOverride (Table, TableDesc); + if (!FinalTable) + { + FinalTable = Table; /* There was no override */ + } + + AcpiTbPrintTableHeader (TableDesc->Address, FinalTable); + + /* Set the global integer width (based upon revision of the DSDT) */ + + if (TableIndex == ACPI_TABLE_INDEX_DSDT) + { + AcpiUtSetIntegerWidth (FinalTable->Revision); + } + +UnmapAndExit: + + /* Always unmap the table header that we mapped above */ + + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbGetRootTableEntry + * + * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry + * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) + * + * RETURN: Physical address extracted from the root table + * + * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on + * both 32-bit and 64-bit platforms + * + * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on + * 64-bit platforms. + * + ******************************************************************************/ + +static ACPI_PHYSICAL_ADDRESS +AcpiTbGetRootTableEntry ( + UINT8 *TableEntry, + UINT32 TableEntrySize) +{ + UINT64 Address64; + + + /* + * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): + * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT + */ + if (TableEntrySize == sizeof (UINT32)) + { + /* + * 32-bit platform, RSDT: Return 32-bit table entry + * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return + */ + return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); + } + else + { + /* + * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return + * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, + * return 64-bit + */ + ACPI_MOVE_64_TO_64 (&Address64, TableEntry); + +#if ACPI_MACHINE_WIDTH == 32 + if (Address64 > ACPI_UINT32_MAX) + { + /* Will truncate 64-bit address to 32 bits, issue warning */ + + ACPI_WARNING ((AE_INFO, + "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," + " truncating", + ACPI_FORMAT_UINT64 (Address64))); + } +#endif + return ((ACPI_PHYSICAL_ADDRESS) (Address64)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbParseRootTable + * + * PARAMETERS: Rsdp - Pointer to the RSDP + * + * RETURN: Status + * + * DESCRIPTION: This function is called to parse the Root System Description + * Table (RSDT or XSDT) + * + * NOTE: Tables are mapped (not copied) for efficiency. The FACS must + * be mapped and cannot be copied because it contains the actual + * memory location of the ACPI Global Lock. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbParseRootTable ( + ACPI_PHYSICAL_ADDRESS RsdpAddress) +{ + ACPI_TABLE_RSDP *Rsdp; + UINT32 TableEntrySize; + UINT32 i; + UINT32 TableCount; + ACPI_TABLE_HEADER *Table; + ACPI_PHYSICAL_ADDRESS Address; + UINT32 Length; + UINT8 *TableEntry; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (TbParseRootTable); + + + /* + * Map the entire RSDP and extract the address of the RSDT or XSDT + */ + Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); + if (!Rsdp) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + AcpiTbPrintTableHeader (RsdpAddress, + ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); + + /* Differentiate between RSDT and XSDT root tables */ + + if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) + { + /* + * Root table is an XSDT (64-bit physical addresses). We must use the + * XSDT if the revision is > 1 and the XSDT pointer is present, as per + * the ACPI specification. + */ + Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; + TableEntrySize = sizeof (UINT64); + } + else + { + /* Root table is an RSDT (32-bit physical addresses) */ + + Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; + TableEntrySize = sizeof (UINT32); + } + + /* + * It is not possible to map more than one entry in some environments, + * so unmap the RSDP here before mapping other tables + */ + AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); + + + /* Map the RSDT/XSDT table header to get the full table length */ + + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + AcpiTbPrintTableHeader (Address, Table); + + /* Get the length of the full table, verify length and map entire table */ + + Length = Table->Length; + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); + + if (Length < sizeof (ACPI_TABLE_HEADER)) + { + ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + + Table = AcpiOsMapMemory (Address, Length); + if (!Table) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Validate the root table checksum */ + + Status = AcpiTbVerifyChecksum (Table, Length); + if (ACPI_FAILURE (Status)) + { + AcpiOsUnmapMemory (Table, Length); + return_ACPI_STATUS (Status); + } + + /* Calculate the number of tables described in the root table */ + + TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / + TableEntrySize); + + /* + * First two entries in the table array are reserved for the DSDT + * and FACS, which are not actually present in the RSDT/XSDT - they + * come from the FADT + */ + TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); + AcpiGbl_RootTableList.CurrentTableCount = 2; + + /* + * Initialize the root table array from the RSDT/XSDT + */ + for (i = 0; i < TableCount; i++) + { + if (AcpiGbl_RootTableList.CurrentTableCount >= + AcpiGbl_RootTableList.MaxTableCount) + { + /* There is no more room in the root table array, attempt resize */ + + Status = AcpiTbResizeRootTableList (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", + (unsigned) (TableCount - + (AcpiGbl_RootTableList.CurrentTableCount - 2)))); + break; + } + } + + /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ + + AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address = + AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); + + TableEntry += TableEntrySize; + AcpiGbl_RootTableList.CurrentTableCount++; + } + + /* + * It is not possible to map more than one entry in some environments, + * so unmap the root table here before mapping other tables + */ + AcpiOsUnmapMemory (Table, Length); + + /* + * Complete the initialization of the root table array by examining + * the header of each table + */ + for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, + NULL, i); + + /* Special case for FADT - get the DSDT and FACS */ + + if (ACPI_COMPARE_NAME ( + &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) + { + AcpiTbParseFadt (i); + } + } + + return_ACPI_STATUS (AE_OK); +} diff --git a/source/components/tables/tbxface.c b/source/components/tables/tbxface.c new file mode 100644 index 000000000000..58dae6935d62 --- /dev/null +++ b/source/components/tables/tbxface.c @@ -0,0 +1,712 @@ +/****************************************************************************** + * + * Module Name: tbxface - Public interfaces to the ACPI subsystem + * ACPI table oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __TBXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxface") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiTbLoadNamespace ( + void); + + +/******************************************************************************* + * + * FUNCTION: AcpiAllocateRootTable + * + * PARAMETERS: InitialTableCount - Size of InitialTableArray, in number of + * ACPI_TABLE_DESC structures + * + * RETURN: Status + * + * DESCRIPTION: Allocate a root table array. Used by iASL compiler and + * AcpiInitializeTables. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiAllocateRootTable ( + UINT32 InitialTableCount) +{ + + AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; + AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE; + + return (AcpiTbResizeRootTableList ()); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiInitializeTables + * + * PARAMETERS: InitialTableArray - Pointer to an array of pre-allocated + * ACPI_TABLE_DESC structures. If NULL, the + * array is dynamically allocated. + * InitialTableCount - Size of InitialTableArray, in number of + * ACPI_TABLE_DESC structures + * AllowRealloc - Flag to tell Table Manager if resize of + * pre-allocated array is allowed. Ignored + * if InitialTableArray is NULL. + * + * RETURN: Status + * + * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. + * + * NOTE: Allows static allocation of the initial table array in order + * to avoid the use of dynamic memory in confined environments + * such as the kernel boot sequence where it may not be available. + * + * If the host OS memory managers are initialized, use NULL for + * InitialTableArray, and the table will be dynamically allocated. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInitializeTables ( + ACPI_TABLE_DESC *InitialTableArray, + UINT32 InitialTableCount, + BOOLEAN AllowResize) +{ + ACPI_PHYSICAL_ADDRESS RsdpAddress; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInitializeTables); + + + /* + * Set up the Root Table Array + * Allocate the table array if requested + */ + if (!InitialTableArray) + { + Status = AcpiAllocateRootTable (InitialTableCount); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + else + { + /* Root Table Array has been statically allocated by the host */ + + ACPI_MEMSET (InitialTableArray, 0, + (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC)); + + AcpiGbl_RootTableList.Tables = InitialTableArray; + AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; + AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN; + if (AllowResize) + { + AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE; + } + } + + /* Get the address of the RSDP */ + + RsdpAddress = AcpiOsGetRootPointer (); + if (!RsdpAddress) + { + return_ACPI_STATUS (AE_NOT_FOUND); + } + + /* + * Get the root table (RSDT or XSDT) and extract all entries to the local + * Root Table Array. This array contains the information of the RSDT/XSDT + * in a common, more useable format. + */ + Status = AcpiTbParseRootTable (RsdpAddress); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInitializeTables) + + +/******************************************************************************* + * + * FUNCTION: AcpiReallocateRootTable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the + * root list from the previously provided scratch area. Should + * be called once dynamic memory allocation is available in the + * kernel + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReallocateRootTable ( + void) +{ + ACPI_TABLE_DESC *Tables; + ACPI_SIZE NewSize; + ACPI_SIZE CurrentSize; + + + ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); + + + /* + * Only reallocate the root table if the host provided a static buffer + * for the table array in the call to AcpiInitializeTables. + */ + if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) + { + return_ACPI_STATUS (AE_SUPPORT); + } + + /* + * Get the current size of the root table and add the default + * increment to create the new table size. + */ + CurrentSize = (ACPI_SIZE) + AcpiGbl_RootTableList.CurrentTableCount * sizeof (ACPI_TABLE_DESC); + + NewSize = CurrentSize + + (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof (ACPI_TABLE_DESC)); + + /* Create new array and copy the old array */ + + Tables = ACPI_ALLOCATE_ZEROED (NewSize); + if (!Tables) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, CurrentSize); + + /* + * Update the root table descriptor. The new size will be the current + * number of tables plus the increment, independent of the reserved + * size of the original table list. + */ + AcpiGbl_RootTableList.Tables = Tables; + AcpiGbl_RootTableList.MaxTableCount = + AcpiGbl_RootTableList.CurrentTableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT; + AcpiGbl_RootTableList.Flags = + ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiReallocateRootTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTableHeader + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * OutTableHeader - The pointer to the table header to fill + * + * RETURN: Status and pointer to mapped table header + * + * DESCRIPTION: Finds an ACPI table header. + * + * NOTE: Caller is responsible in unmapping the header with + * AcpiOsUnmapMemory + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTableHeader ( + char *Signature, + UINT32 Instance, + ACPI_TABLE_HEADER *OutTableHeader) +{ + UINT32 i; + UINT32 j; + ACPI_TABLE_HEADER *Header; + + + /* Parameter validation */ + + if (!Signature || !OutTableHeader) + { + return (AE_BAD_PARAMETER); + } + + /* Walk the root table list */ + + for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + Signature)) + { + continue; + } + + if (++j < Instance) + { + continue; + } + + if (!AcpiGbl_RootTableList.Tables[i].Pointer) + { + if ((AcpiGbl_RootTableList.Tables[i].Flags & + ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_MAPPED) + { + Header = AcpiOsMapMemory ( + AcpiGbl_RootTableList.Tables[i].Address, + sizeof (ACPI_TABLE_HEADER)); + if (!Header) + { + return AE_NO_MEMORY; + } + + ACPI_MEMCPY (OutTableHeader, Header, sizeof(ACPI_TABLE_HEADER)); + AcpiOsUnmapMemory (Header, sizeof(ACPI_TABLE_HEADER)); + } + else + { + return AE_NOT_FOUND; + } + } + else + { + ACPI_MEMCPY (OutTableHeader, + AcpiGbl_RootTableList.Tables[i].Pointer, + sizeof(ACPI_TABLE_HEADER)); + } + + return (AE_OK); + } + + return (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTableHeader) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTable + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * OutTable - Where the pointer to the table is returned + * + * RETURN: Status and pointer to table + * + * DESCRIPTION: Finds and verifies an ACPI table. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTable ( + char *Signature, + UINT32 Instance, + ACPI_TABLE_HEADER **OutTable) +{ + UINT32 i; + UINT32 j; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!Signature || !OutTable) + { + return (AE_BAD_PARAMETER); + } + + /* Walk the root table list */ + + for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + Signature)) + { + continue; + } + + if (++j < Instance) + { + continue; + } + + Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); + if (ACPI_SUCCESS (Status)) + { + *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer; + } + + return (Status); + } + + return (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTableByIndex + * + * PARAMETERS: TableIndex - Table index + * Table - Where the pointer to the table is returned + * + * RETURN: Status and pointer to the table + * + * DESCRIPTION: Obtain a table by an index into the global table list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTableByIndex ( + UINT32 TableIndex, + ACPI_TABLE_HEADER **Table) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetTableByIndex); + + + /* Parameter validation */ + + if (!Table) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Validate index */ + + if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) + { + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer) + { + /* Table is not mapped, map it */ + + Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[TableIndex]); + if (ACPI_FAILURE (Status)) + { + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); + } + } + + *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer; + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) + + +/******************************************************************************* + * + * FUNCTION: AcpiTbLoadNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiTbLoadNamespace ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + ACPI_TABLE_HEADER *NewDsdt; + + + ACPI_FUNCTION_TRACE (TbLoadNamespace); + + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* + * Load the namespace. The DSDT is required, but any SSDT and + * PSDT tables are optional. Verify the DSDT. + */ + if (!AcpiGbl_RootTableList.CurrentTableCount || + !ACPI_COMPARE_NAME ( + &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), + ACPI_SIG_DSDT) || + ACPI_FAILURE (AcpiTbVerifyTable ( + &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) + { + Status = AE_NO_ACPI_TABLES; + goto UnlockAndExit; + } + + /* + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time. Note: + * .Pointer field is not validated until after call to AcpiTbVerifyTable. + */ + AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; + + /* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ + if (AcpiGbl_CopyDsdtLocally) + { + NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); + if (NewDsdt) + { + AcpiGbl_DSDT = NewDsdt; + } + } + + /* + * Save the original DSDT header for detection of table corruption + * and/or replacement of the DSDT from outside the OS. + */ + ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, + sizeof (ACPI_TABLE_HEADER)); + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + + /* Load and parse tables */ + + Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_SSDT) && + !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_PSDT)) || + ACPI_FAILURE (AcpiTbVerifyTable ( + &AcpiGbl_RootTableList.Tables[i]))) + { + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiLoadTables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLoadTables ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLoadTables); + + + /* Load the namespace from the tables */ + + Status = AcpiTbLoadNamespace (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While loading namespace from ACPI tables")); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLoadTables) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallTableHandler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install table event handler + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallTableHandler ( + ACPI_TABLE_HANDLER Handler, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallTableHandler); + + + if (!Handler) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow more than one handler */ + + if (AcpiGbl_TableHandler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + /* Install the handler */ + + AcpiGbl_TableHandler = Handler; + AcpiGbl_TableHandlerContext = Context; + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveTableHandler + * + * PARAMETERS: Handler - Table event handler that was installed + * previously. + * + * RETURN: Status + * + * DESCRIPTION: Remove table event handler + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveTableHandler ( + ACPI_TABLE_HANDLER Handler) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Make sure that the installed handler is the same */ + + if (!Handler || + Handler != AcpiGbl_TableHandler) + { + Status = AE_BAD_PARAMETER; + goto Cleanup; + } + + /* Remove the handler */ + + AcpiGbl_TableHandler = NULL; + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler) + diff --git a/source/components/tables/tbxfroot.c b/source/components/tables/tbxfroot.c new file mode 100644 index 000000000000..17e52ef7f4ec --- /dev/null +++ b/source/components/tables/tbxfroot.c @@ -0,0 +1,299 @@ +/****************************************************************************** + * + * Module Name: tbxfroot - Find the root ACPI table (RSDT) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __TBXFROOT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxfroot") + +/* Local prototypes */ + +static UINT8 * +AcpiTbScanMemoryForRsdp ( + UINT8 *StartAddress, + UINT32 Length); + +static ACPI_STATUS +AcpiTbValidateRsdp ( + ACPI_TABLE_RSDP *Rsdp); + + +/******************************************************************************* + * + * FUNCTION: AcpiTbValidateRsdp + * + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * + * RETURN: Status + * + * DESCRIPTION: Validate the RSDP (ptr) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiTbValidateRsdp ( + ACPI_TABLE_RSDP *Rsdp) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * The signature and checksum must both be correct + * + * Note: Sometimes there exists more than one RSDP in memory; the valid + * RSDP has a valid checksum, all others have an invalid checksum. + */ + if (ACPI_STRNCMP ((char *) Rsdp, ACPI_SIG_RSDP, + sizeof (ACPI_SIG_RSDP)-1) != 0) + { + /* Nope, BAD Signature */ + + return (AE_BAD_SIGNATURE); + } + + /* Check the standard checksum */ + + if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) + { + return (AE_BAD_CHECKSUM); + } + + /* Check extended checksum if table version >= 2 */ + + if ((Rsdp->Revision >= 2) && + (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) + { + return (AE_BAD_CHECKSUM); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiFindRootPointer + * + * PARAMETERS: TableAddress - Where the table pointer is returned + * + * RETURN: Status, RSDP physical address + * + * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE1: The RSDP must be either in the first 1K of the Extended + * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) + * Only a 32-bit physical address is necessary. + * + * NOTE2: This function is always available, regardless of the + * initialization state of the rest of ACPI. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiFindRootPointer ( + ACPI_SIZE *TableAddress) +{ + UINT8 *TablePtr; + UINT8 *MemRover; + UINT32 PhysicalAddress; + + + ACPI_FUNCTION_TRACE (AcpiFindRootPointer); + + + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ + + TablePtr = AcpiOsMapMemory ( + (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH); + if (!TablePtr) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X for length %u", + ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); + + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); + + /* Convert segment part to physical address */ + + PhysicalAddress <<= 4; + AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); + + /* EBDA present? */ + + if (PhysicalAddress > 0x400) + { + /* + * 1b) Search EBDA paragraphs (EBDA is required to be a + * minimum of 1K length) + */ + TablePtr = AcpiOsMapMemory ( + (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, + ACPI_EBDA_WINDOW_SIZE); + if (!TablePtr) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X for length %u", + PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); + + return_ACPI_STATUS (AE_NO_MEMORY); + } + + MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); + AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); + + if (MemRover) + { + /* Return the physical address */ + + PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); + + *TableAddress = PhysicalAddress; + return_ACPI_STATUS (AE_OK); + } + } + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh + */ + TablePtr = AcpiOsMapMemory ( + (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE); + + if (!TablePtr) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X for length %u", + ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); + + return_ACPI_STATUS (AE_NO_MEMORY); + } + + MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); + AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); + + if (MemRover) + { + /* Return the physical address */ + + PhysicalAddress = (UINT32) + (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); + + *TableAddress = PhysicalAddress; + return_ACPI_STATUS (AE_OK); + } + + /* A valid RSDP was not found */ + + ACPI_ERROR ((AE_INFO, "A valid RSDP was not found")); + return_ACPI_STATUS (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL (AcpiFindRootPointer) + + +/******************************************************************************* + * + * FUNCTION: AcpiTbScanMemoryForRsdp + * + * PARAMETERS: StartAddress - Starting pointer for search + * Length - Maximum length to search + * + * RETURN: Pointer to the RSDP if found, otherwise NULL. + * + * DESCRIPTION: Search a block of memory for the RSDP signature + * + ******************************************************************************/ + +static UINT8 * +AcpiTbScanMemoryForRsdp ( + UINT8 *StartAddress, + UINT32 Length) +{ + ACPI_STATUS Status; + UINT8 *MemRover; + UINT8 *EndAddress; + + + ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); + + + EndAddress = StartAddress + Length; + + /* Search from given start address for the requested length */ + + for (MemRover = StartAddress; MemRover < EndAddress; + MemRover += ACPI_RSDP_SCAN_STEP) + { + /* The RSDP signature and checksum must both be correct */ + + Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); + if (ACPI_SUCCESS (Status)) + { + /* Sig and checksum valid, we have found a real RSDP */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "RSDP located at physical address %p\n", MemRover)); + return_PTR (MemRover); + } + + /* No sig match or bad checksum, keep searching */ + } + + /* Searched entire block, no RSDP was found */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Searched entire block from %p, valid RSDP was not found\n", + StartAddress)); + return_PTR (NULL); +} + diff --git a/source/components/utilities/utaddress.c b/source/components/utilities/utaddress.c new file mode 100644 index 000000000000..0b357b681b51 --- /dev/null +++ b/source/components/utilities/utaddress.c @@ -0,0 +1,322 @@ +/****************************************************************************** + * + * Module Name: utaddress - OpRegion address range check + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTADDRESS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utaddress") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAddAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - OpRegion start address + * Length - OpRegion length + * RegionNode - OpRegion namespace node + * + * RETURN: Status + * + * DESCRIPTION: Add the Operation Region address range to the global list. + * The only supported Space IDs are Memory and I/O. Called when + * the OpRegion address/length operands are fully evaluated. + * + * MUTEX: Locks the namespace + * + * NOTE: Because this interface is only called when an OpRegion argument + * list is evaluated, there cannot be any duplicate RegionNodes. + * Duplicate Address/Length values are allowed, however, so that multiple + * address conflicts can be detected. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAddAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + ACPI_NAMESPACE_NODE *RegionNode) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtAddAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_ACPI_STATUS (AE_OK); + } + + /* Allocate/init a new info block, add it to the appropriate list */ + + RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE)); + if (!RangeInfo) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + RangeInfo->StartAddress = Address; + RangeInfo->EndAddress = (Address + Length - 1); + RangeInfo->RegionNode = RegionNode; + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (RangeInfo); + return_ACPI_STATUS (Status); + } + + RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId]; + AcpiGbl_AddressRangeList[SpaceId] = RangeInfo; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "\nAdded [%4.4s] address range: 0x%p-0x%p\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_CAST_PTR (void, Address), + ACPI_CAST_PTR (void, RangeInfo->EndAddress))); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * RegionNode - OpRegion namespace node + * + * RETURN: None + * + * DESCRIPTION: Remove the Operation Region from the global list. The only + * supported Space IDs are Memory and I/O. Called when an + * OpRegion is deleted. + * + * MUTEX: Assumes the namespace is locked + * + ******************************************************************************/ + +void +AcpiUtRemoveAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_NAMESPACE_NODE *RegionNode) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_ADDRESS_RANGE *Prev; + + + ACPI_FUNCTION_TRACE (UtRemoveAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_VOID; + } + + /* Get the appropriate list head and check the list */ + + RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId]; + while (RangeInfo) + { + if (RangeInfo->RegionNode == RegionNode) + { + if (RangeInfo == Prev) /* Found at list head */ + { + AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next; + } + else + { + Prev->Next = RangeInfo->Next; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_CAST_PTR (void, RangeInfo->StartAddress), + ACPI_CAST_PTR (void, RangeInfo->EndAddress))); + + ACPI_FREE (RangeInfo); + return_VOID; + } + + Prev = RangeInfo; + RangeInfo = RangeInfo->Next; + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCheckAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - Start address + * Length - Length of address range + * Warn - TRUE if warning on overlap desired + * + * RETURN: Count of the number of conflicts detected. Zero is always + * returned for Space IDs other than Memory or I/O. + * + * DESCRIPTION: Check if the input address range overlaps any of the + * ASL operation region address ranges. The only supported + * Space IDs are Memory and I/O. + * + * MUTEX: Assumes the namespace is locked. + * + ******************************************************************************/ + +UINT32 +AcpiUtCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + BOOLEAN Warn) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_PHYSICAL_ADDRESS EndAddress; + char *Pathname; + UINT32 OverlapCount = 0; + + + ACPI_FUNCTION_TRACE (UtCheckAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_UINT32 (0); + } + + RangeInfo = AcpiGbl_AddressRangeList[SpaceId]; + EndAddress = Address + Length - 1; + + /* Check entire list for all possible conflicts */ + + while (RangeInfo) + { + /* + * Check if the requested Address/Length overlaps this AddressRange. + * Four cases to consider: + * + * 1) Input address/length is contained completely in the address range + * 2) Input address/length overlaps range at the range start + * 3) Input address/length overlaps range at the range end + * 4) Input address/length completely encompasses the range + */ + if ((Address <= RangeInfo->EndAddress) && + (EndAddress >= RangeInfo->StartAddress)) + { + /* Found an address range overlap */ + + OverlapCount++; + if (Warn) /* Optional warning message */ + { + Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode); + + ACPI_WARNING ((AE_INFO, + "0x%p-0x%p %s conflicts with Region %s %d", + ACPI_CAST_PTR (void, Address), + ACPI_CAST_PTR (void, EndAddress), + AcpiUtGetRegionName (SpaceId), Pathname, OverlapCount)); + ACPI_FREE (Pathname); + } + } + + RangeInfo = RangeInfo->Next; + } + + return_UINT32 (OverlapCount); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteAddressLists + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all global address range lists (called during + * subsystem shutdown). + * + ******************************************************************************/ + +void +AcpiUtDeleteAddressLists ( + void) +{ + ACPI_ADDRESS_RANGE *Next; + ACPI_ADDRESS_RANGE *RangeInfo; + int i; + + + /* Delete all elements in all address range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) + { + Next = AcpiGbl_AddressRangeList[i]; + + while (Next) + { + RangeInfo = Next; + Next = RangeInfo->Next; + ACPI_FREE (RangeInfo); + } + + AcpiGbl_AddressRangeList[i] = NULL; + } +} diff --git a/source/components/utilities/utalloc.c b/source/components/utilities/utalloc.c new file mode 100644 index 000000000000..d2eb11edcb6f --- /dev/null +++ b/source/components/utilities/utalloc.c @@ -0,0 +1,416 @@ +/****************************************************************************** + * + * Module Name: utalloc - local memory allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTALLOC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utalloc") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateCaches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create all local caches + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateCaches ( + void) +{ + ACPI_STATUS Status; + + + /* Object Caches, for frequently used objects */ + + Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE), + ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE), + ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON), + ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED), + ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT), + ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Memory allocation lists */ + + Status = AcpiUtCreateList ("Acpi-Global", 0, + &AcpiGbl_GlobalList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE), + &AcpiGbl_NsNodeList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } +#endif + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteCaches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge and delete all local caches + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtDeleteCaches ( + void) +{ +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + char Buffer[7]; + + if (AcpiGbl_DisplayFinalMemStats) + { + ACPI_STRCPY (Buffer, "MEMORY"); + (void) AcpiDbDisplayStatistics (Buffer); + } +#endif + + (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache); + AcpiGbl_NamespaceCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_StateCache); + AcpiGbl_StateCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_OperandCache); + AcpiGbl_OperandCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache); + AcpiGbl_PsNodeCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache); + AcpiGbl_PsNodeExtCache = NULL; + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Debug only - display leftover memory allocation, if any */ + + AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL); + + /* Free memory lists */ + + AcpiOsFree (AcpiGbl_GlobalList); + AcpiGbl_GlobalList = NULL; + + AcpiOsFree (AcpiGbl_NsNodeList); + AcpiGbl_NsNodeList = NULL; +#endif + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateBuffer + * + * PARAMETERS: Buffer - Buffer descriptor to be validated + * + * RETURN: Status + * + * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtValidateBuffer ( + ACPI_BUFFER *Buffer) +{ + + /* Obviously, the structure pointer must be valid */ + + if (!Buffer) + { + return (AE_BAD_PARAMETER); + } + + /* Special semantics for the length */ + + if ((Buffer->Length == ACPI_NO_BUFFER) || + (Buffer->Length == ACPI_ALLOCATE_BUFFER) || + (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER)) + { + return (AE_OK); + } + + /* Length is valid, the buffer pointer must be also */ + + if (!Buffer->Pointer) + { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitializeBuffer + * + * PARAMETERS: Buffer - Buffer to be validated + * RequiredLength - Length needed + * + * RETURN: Status + * + * DESCRIPTION: Validate that the buffer is of the required length or + * allocate a new buffer. Returned buffer is always zeroed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitializeBuffer ( + ACPI_BUFFER *Buffer, + ACPI_SIZE RequiredLength) +{ + ACPI_SIZE InputBufferLength; + + + /* Parameter validation */ + + if (!Buffer || !RequiredLength) + { + return (AE_BAD_PARAMETER); + } + + /* + * Buffer->Length is used as both an input and output parameter. Get the + * input actual length and set the output required buffer length. + */ + InputBufferLength = Buffer->Length; + Buffer->Length = RequiredLength; + + /* + * The input buffer length contains the actual buffer length, or the type + * of buffer to be allocated by this routine. + */ + switch (InputBufferLength) + { + case ACPI_NO_BUFFER: + + /* Return the exception (and the required buffer length) */ + + return (AE_BUFFER_OVERFLOW); + + case ACPI_ALLOCATE_BUFFER: + + /* Allocate a new buffer */ + + Buffer->Pointer = AcpiOsAllocate (RequiredLength); + break; + + case ACPI_ALLOCATE_LOCAL_BUFFER: + + /* Allocate a new buffer with local interface to allow tracking */ + + Buffer->Pointer = ACPI_ALLOCATE (RequiredLength); + break; + + default: + + /* Existing buffer: Validate the size of the buffer */ + + if (InputBufferLength < RequiredLength) + { + return (AE_BUFFER_OVERFLOW); + } + break; + } + + /* Validate allocation from above or input buffer pointer */ + + if (!Buffer->Pointer) + { + return (AE_NO_MEMORY); + } + + /* Have a valid buffer, clear it */ + + ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of malloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocate ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + void *Allocation; + + + ACPI_FUNCTION_TRACE_U32 (UtAllocate, Size); + + + /* Check for an inadvertent size of zero bytes */ + + if (!Size) + { + ACPI_WARNING ((Module, Line, + "Attempt to allocate zero bytes, allocating 1 byte")); + Size = 1; + } + + Allocation = AcpiOsAllocate (Size); + if (!Allocation) + { + /* Report allocation error */ + + ACPI_WARNING ((Module, Line, + "Could not allocate size %u", (UINT32) Size)); + + return_PTR (NULL); + } + + return_PTR (Allocation); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateZeroed + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * + ******************************************************************************/ + +void * +AcpiUtAllocateZeroed ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + void *Allocation; + + + ACPI_FUNCTION_ENTRY (); + + + Allocation = AcpiUtAllocate (Size, Component, Module, Line); + if (Allocation) + { + /* Clear the memory block */ + + ACPI_MEMSET (Allocation, 0, Size); + } + + return (Allocation); +} + diff --git a/source/components/utilities/utcache.c b/source/components/utilities/utcache.c new file mode 100644 index 000000000000..7b3abe2894ca --- /dev/null +++ b/source/components/utilities/utcache.c @@ -0,0 +1,361 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTCACHE_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utcache") + + +#ifdef ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: AcpiOsCreateCache + * + * PARAMETERS: CacheName - Ascii name for the cache + * ObjectSize - Size of each cached object + * MaxDepth - Maximum depth of the cache (in objects) + * ReturnCache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsCreateCache ( + char *CacheName, + UINT16 ObjectSize, + UINT16 MaxDepth, + ACPI_MEMORY_LIST **ReturnCache) +{ + ACPI_MEMORY_LIST *Cache; + + + ACPI_FUNCTION_ENTRY (); + + + if (!CacheName || !ReturnCache || (ObjectSize < 16)) + { + return (AE_BAD_PARAMETER); + } + + /* Create the cache object */ + + Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); + if (!Cache) + { + return (AE_NO_MEMORY); + } + + /* Populate the cache object and return it */ + + ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + Cache->LinkOffset = 8; + Cache->ListName = CacheName; + Cache->ObjectSize = ObjectSize; + Cache->MaxDepth = MaxDepth; + + *ReturnCache = Cache; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsPurgeCache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsPurgeCache ( + ACPI_MEMORY_LIST *Cache) +{ + char *Next; + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Cache) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Walk the list of objects in this cache */ + + while (Cache->ListHead) + { + /* Delete and unlink one cached state object */ + + Next = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Cache->ListHead)[Cache->LinkOffset]))); + ACPI_FREE (Cache->ListHead); + + Cache->ListHead = Next; + Cache->CurrentDepth--; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsDeleteCache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsDeleteCache ( + ACPI_MEMORY_LIST *Cache) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + /* Purge all objects in the cache */ + + Status = AcpiOsPurgeCache (Cache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Now we can delete the cache object */ + + AcpiOsFree (Cache); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsReleaseObject + * + * PARAMETERS: Cache - Handle to cache object + * Object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsReleaseObject ( + ACPI_MEMORY_LIST *Cache, + void *Object) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Cache || !Object) + { + return (AE_BAD_PARAMETER); + } + + /* If cache is full, just free this object */ + + if (Cache->CurrentDepth >= Cache->MaxDepth) + { + ACPI_FREE (Object); + ACPI_MEM_TRACKING (Cache->TotalFreed++); + } + + /* Otherwise put this object back into the cache */ + + else + { + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Mark the object as cached */ + + ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize); + ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); + + /* Put the object at the head of the cache list */ + + * (ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Object)[Cache->LinkOffset]))) = Cache->ListHead; + Cache->ListHead = Object; + Cache->CurrentDepth++; + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsAcquireObject + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: the acquired object. NULL on error + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void * +AcpiOsAcquireObject ( + ACPI_MEMORY_LIST *Cache) +{ + ACPI_STATUS Status; + void *Object; + + + ACPI_FUNCTION_NAME (OsAcquireObject); + + + if (!Cache) + { + return (NULL); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + ACPI_MEM_TRACKING (Cache->Requests++); + + /* Check the cache first */ + + if (Cache->ListHead) + { + /* There is an object available, use it */ + + Object = Cache->ListHead; + Cache->ListHead = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Object)[Cache->LinkOffset]))); + + Cache->CurrentDepth--; + + ACPI_MEM_TRACKING (Cache->Hits++); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Object %p from %s cache\n", Object, Cache->ListName)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + /* Clear (zero) the previously used Object */ + + ACPI_MEMSET (Object, 0, Cache->ObjectSize); + } + else + { + /* The cache is empty, create a new object */ + + ACPI_MEM_TRACKING (Cache->TotalAllocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) + { + Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; + } +#endif + + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ + + Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); + if (!Object) + { + return (NULL); + } + } + + return (Object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ + + diff --git a/source/components/utilities/utclib.c b/source/components/utilities/utclib.c new file mode 100644 index 000000000000..d0153ec5d295 --- /dev/null +++ b/source/components/utilities/utclib.c @@ -0,0 +1,889 @@ +/****************************************************************************** + * + * Module Name: cmclib - Local implementation of C library functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __CMCLIB_C__ + +#include "acpi.h" +#include "accommon.h" + +/* + * These implementations of standard C Library routines can optionally be + * used if a C library is not available. In general, they are less efficient + * than an inline or assembly implementation + */ + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("cmclib") + + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +#define NEGATIVE 1 +#define POSITIVE 0 + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemcmp (memcmp) + * + * PARAMETERS: Buffer1 - First Buffer + * Buffer2 - Second Buffer + * Count - Maximum # of bytes to compare + * + * RETURN: Index where Buffers mismatched, or 0 if Buffers matched + * + * DESCRIPTION: Compare two Buffers, with a maximum length + * + ******************************************************************************/ + +int +AcpiUtMemcmp ( + const char *Buffer1, + const char *Buffer2, + ACPI_SIZE Count) +{ + + for ( ; Count-- && (*Buffer1 == *Buffer2); Buffer1++, Buffer2++) + { + } + + return ((Count == ACPI_SIZE_MAX) ? 0 : ((unsigned char) *Buffer1 - + (unsigned char) *Buffer2)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemcpy (memcpy) + * + * PARAMETERS: Dest - Target of the copy + * Src - Source buffer to copy + * Count - Number of bytes to copy + * + * RETURN: Dest + * + * DESCRIPTION: Copy arbitrary bytes of memory + * + ******************************************************************************/ + +void * +AcpiUtMemcpy ( + void *Dest, + const void *Src, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + char *Old = (char *) Src; + + + while (Count) + { + *New = *Old; + New++; + Old++; + Count--; + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemset (memset) + * + * PARAMETERS: Dest - Buffer to set + * Value - Value to set each byte of memory + * Count - Number of bytes to set + * + * RETURN: Dest + * + * DESCRIPTION: Initialize a buffer to a known value. + * + ******************************************************************************/ + +void * +AcpiUtMemset ( + void *Dest, + UINT8 Value, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + + + while (Count) + { + *New = (char) Value; + New++; + Count--; + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlen (strlen) + * + * PARAMETERS: String - Null terminated string + * + * RETURN: Length + * + * DESCRIPTION: Returns the length of the input string + * + ******************************************************************************/ + + +ACPI_SIZE +AcpiUtStrlen ( + const char *String) +{ + UINT32 Length = 0; + + + /* Count the string until a null is encountered */ + + while (*String) + { + Length++; + String++; + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcpy (strcpy) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * + * RETURN: DstString + * + * DESCRIPTION: Copy a null terminated string + * + ******************************************************************************/ + +char * +AcpiUtStrcpy ( + char *DstString, + const char *SrcString) +{ + char *String = DstString; + + + /* Move bytes brute force */ + + while (*SrcString) + { + *String = *SrcString; + + String++; + SrcString++; + } + + /* Null terminate */ + + *String = 0; + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncpy (strncpy) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: DstString + * + * DESCRIPTION: Copy a null terminated string, with a maximum length + * + ******************************************************************************/ + +char * +AcpiUtStrncpy ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count) +{ + char *String = DstString; + + + /* Copy the string */ + + for (String = DstString; + Count && (Count--, (*String++ = *SrcString++)); ) + {;} + + /* Pad with nulls if necessary */ + + while (Count--) + { + *String = 0; + String++; + } + + /* Return original pointer */ + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcmp (strcmp) + * + * PARAMETERS: String1 - First string + * String2 - Second string + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings + * + ******************************************************************************/ + +int +AcpiUtStrcmp ( + const char *String1, + const char *String2) +{ + + + for ( ; (*String1 == *String2); String2++) + { + if (!*String1++) + { + return (0); + } + } + + return ((unsigned char) *String1 - (unsigned char) *String2); +} + + +#ifdef ACPI_FUTURE_IMPLEMENTATION +/* Not used at this time */ +/******************************************************************************* + * + * FUNCTION: AcpiUtStrchr (strchr) + * + * PARAMETERS: String - Search string + * ch - character to search for + * + * RETURN: Ptr to char or NULL if not found + * + * DESCRIPTION: Search a string for a character + * + ******************************************************************************/ + +char * +AcpiUtStrchr ( + const char *String, + int ch) +{ + + + for ( ; (*String); String++) + { + if ((*String) == (char) ch) + { + return ((char *) String); + } + } + + return (NULL); +} +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncmp (strncmp) + * + * PARAMETERS: String1 - First string + * String2 - Second string + * Count - Maximum # of bytes to compare + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings, with a maximum length + * + ******************************************************************************/ + +int +AcpiUtStrncmp ( + const char *String1, + const char *String2, + ACPI_SIZE Count) +{ + + + for ( ; Count-- && (*String1 == *String2); String2++) + { + if (!*String1++) + { + return (0); + } + } + + return ((Count == ACPI_SIZE_MAX) ? 0 : ((unsigned char) *String1 - + (unsigned char) *String2)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcat (Strcat) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * + * RETURN: DstString + * + * DESCRIPTION: Append a null terminated string to a null terminated string + * + ******************************************************************************/ + +char * +AcpiUtStrcat ( + char *DstString, + const char *SrcString) +{ + char *String; + + + /* Find end of the destination string */ + + for (String = DstString; *String++; ) + { ; } + + /* Concatenate the string */ + + for (--String; (*String++ = *SrcString++); ) + { ; } + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncat (strncat) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: DstString + * + * DESCRIPTION: Append a null terminated string to a null terminated string, + * with a maximum count. + * + ******************************************************************************/ + +char * +AcpiUtStrncat ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count) +{ + char *String; + + + if (Count) + { + /* Find end of the destination string */ + + for (String = DstString; *String++; ) + { ; } + + /* Concatenate the string */ + + for (--String; (*String++ = *SrcString++) && --Count; ) + { ; } + + /* Null terminate if necessary */ + + if (!Count) + { + *String = 0; + } + } + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrstr (strstr) + * + * PARAMETERS: String1 - Target string + * String2 - Substring to search for + * + * RETURN: Where substring match starts, Null if no match found + * + * DESCRIPTION: Checks if String2 occurs in String1. This is not really a + * full implementation of strstr, only sufficient for command + * matching + * + ******************************************************************************/ + +char * +AcpiUtStrstr ( + char *String1, + char *String2) +{ + char *String; + + + if (AcpiUtStrlen (String2) > AcpiUtStrlen (String1)) + { + return (NULL); + } + + /* Walk entire string, comparing the letters */ + + for (String = String1; *String2; ) + { + if (*String2 != *String) + { + return (NULL); + } + + String2++; + String++; + } + + return (String1); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul (strtoul) + * + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte is + * returned + * Base - Radix of the string + * + * RETURN: Converted value + * + * DESCRIPTION: Convert a string into a 32-bit unsigned value. + * Note: use AcpiUtStrtoul64 for 64-bit integers. + * + ******************************************************************************/ + +UINT32 +AcpiUtStrtoul ( + const char *String, + char **Terminator, + UINT32 Base) +{ + UINT32 converted = 0; + UINT32 index; + UINT32 sign; + const char *StringStart; + UINT32 ReturnValue = 0; + ACPI_STATUS Status = AE_OK; + + + /* + * Save the value of the pointer to the buffer's first + * character, save the current errno value, and then + * skip over any white space in the buffer: + */ + StringStart = String; + while (ACPI_IS_SPACE (*String) || *String == '\t') + { + ++String; + } + + /* + * The buffer may contain an optional plus or minus sign. + * If it does, then skip over it but remember what is was: + */ + if (*String == '-') + { + sign = NEGATIVE; + ++String; + } + else if (*String == '+') + { + ++String; + sign = POSITIVE; + } + else + { + sign = POSITIVE; + } + + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (Base == 0) + { + if (*String == '0') + { + if (AcpiUtToLower (*(++String)) == 'x') + { + Base = 16; + ++String; + } + else + { + Base = 8; + } + } + else + { + Base = 10; + } + } + else if (Base < 2 || Base > 36) + { + /* + * The specified Base parameter is not in the domain of + * this function: + */ + goto done; + } + + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (Base == 8 && *String == '0') + { + String++; + } + + if (Base == 16 && + *String == '0' && + AcpiUtToLower (*(++String)) == 'x') + { + String++; + } + + /* + * Main loop: convert the string to an unsigned long: + */ + while (*String) + { + if (ACPI_IS_DIGIT (*String)) + { + index = (UINT32) ((UINT8) *String - '0'); + } + else + { + index = (UINT32) AcpiUtToUpper (*String); + if (ACPI_IS_UPPER (index)) + { + index = index - 'A' + 10; + } + else + { + goto done; + } + } + + if (index >= Base) + { + goto done; + } + + /* + * Check to see if value is out of range: + */ + + if (ReturnValue > ((ACPI_UINT32_MAX - (UINT32) index) / + (UINT32) Base)) + { + Status = AE_ERROR; + ReturnValue = 0; /* reset */ + } + else + { + ReturnValue *= Base; + ReturnValue += index; + converted = 1; + } + + ++String; + } + +done: + /* + * If appropriate, update the caller's pointer to the next + * unconverted character in the buffer. + */ + if (Terminator) + { + if (converted == 0 && ReturnValue == 0 && String != NULL) + { + *Terminator = (char *) StringStart; + } + else + { + *Terminator = (char *) String; + } + } + + if (Status == AE_ERROR) + { + ReturnValue = ACPI_UINT32_MAX; + } + + /* + * If a minus sign was present, then "the conversion is negated": + */ + if (sign == NEGATIVE) + { + ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; + } + + return (ReturnValue); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtToUpper (TOUPPER) + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to uppercase + * + ******************************************************************************/ + +int +AcpiUtToUpper ( + int c) +{ + + return (ACPI_IS_LOWER(c) ? ((c)-0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtToLower (TOLOWER) + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to lowercase + * + ******************************************************************************/ + +int +AcpiUtToLower ( + int c) +{ + + return (ACPI_IS_UPPER(c) ? ((c)+0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: is* functions + * + * DESCRIPTION: is* functions use the ctype table below + * + ******************************************************************************/ + +const UINT8 _acpi_ctype[257] = { + _ACPI_CN, /* 0x0 0. */ + _ACPI_CN, /* 0x1 1. */ + _ACPI_CN, /* 0x2 2. */ + _ACPI_CN, /* 0x3 3. */ + _ACPI_CN, /* 0x4 4. */ + _ACPI_CN, /* 0x5 5. */ + _ACPI_CN, /* 0x6 6. */ + _ACPI_CN, /* 0x7 7. */ + _ACPI_CN, /* 0x8 8. */ + _ACPI_CN|_ACPI_SP, /* 0x9 9. */ + _ACPI_CN|_ACPI_SP, /* 0xA 10. */ + _ACPI_CN|_ACPI_SP, /* 0xB 11. */ + _ACPI_CN|_ACPI_SP, /* 0xC 12. */ + _ACPI_CN|_ACPI_SP, /* 0xD 13. */ + _ACPI_CN, /* 0xE 14. */ + _ACPI_CN, /* 0xF 15. */ + _ACPI_CN, /* 0x10 16. */ + _ACPI_CN, /* 0x11 17. */ + _ACPI_CN, /* 0x12 18. */ + _ACPI_CN, /* 0x13 19. */ + _ACPI_CN, /* 0x14 20. */ + _ACPI_CN, /* 0x15 21. */ + _ACPI_CN, /* 0x16 22. */ + _ACPI_CN, /* 0x17 23. */ + _ACPI_CN, /* 0x18 24. */ + _ACPI_CN, /* 0x19 25. */ + _ACPI_CN, /* 0x1A 26. */ + _ACPI_CN, /* 0x1B 27. */ + _ACPI_CN, /* 0x1C 28. */ + _ACPI_CN, /* 0x1D 29. */ + _ACPI_CN, /* 0x1E 30. */ + _ACPI_CN, /* 0x1F 31. */ + _ACPI_XS|_ACPI_SP, /* 0x20 32. ' ' */ + _ACPI_PU, /* 0x21 33. '!' */ + _ACPI_PU, /* 0x22 34. '"' */ + _ACPI_PU, /* 0x23 35. '#' */ + _ACPI_PU, /* 0x24 36. '$' */ + _ACPI_PU, /* 0x25 37. '%' */ + _ACPI_PU, /* 0x26 38. '&' */ + _ACPI_PU, /* 0x27 39. ''' */ + _ACPI_PU, /* 0x28 40. '(' */ + _ACPI_PU, /* 0x29 41. ')' */ + _ACPI_PU, /* 0x2A 42. '*' */ + _ACPI_PU, /* 0x2B 43. '+' */ + _ACPI_PU, /* 0x2C 44. ',' */ + _ACPI_PU, /* 0x2D 45. '-' */ + _ACPI_PU, /* 0x2E 46. '.' */ + _ACPI_PU, /* 0x2F 47. '/' */ + _ACPI_XD|_ACPI_DI, /* 0x30 48. '0' */ + _ACPI_XD|_ACPI_DI, /* 0x31 49. '1' */ + _ACPI_XD|_ACPI_DI, /* 0x32 50. '2' */ + _ACPI_XD|_ACPI_DI, /* 0x33 51. '3' */ + _ACPI_XD|_ACPI_DI, /* 0x34 52. '4' */ + _ACPI_XD|_ACPI_DI, /* 0x35 53. '5' */ + _ACPI_XD|_ACPI_DI, /* 0x36 54. '6' */ + _ACPI_XD|_ACPI_DI, /* 0x37 55. '7' */ + _ACPI_XD|_ACPI_DI, /* 0x38 56. '8' */ + _ACPI_XD|_ACPI_DI, /* 0x39 57. '9' */ + _ACPI_PU, /* 0x3A 58. ':' */ + _ACPI_PU, /* 0x3B 59. ';' */ + _ACPI_PU, /* 0x3C 60. '<' */ + _ACPI_PU, /* 0x3D 61. '=' */ + _ACPI_PU, /* 0x3E 62. '>' */ + _ACPI_PU, /* 0x3F 63. '?' */ + _ACPI_PU, /* 0x40 64. '@' */ + _ACPI_XD|_ACPI_UP, /* 0x41 65. 'A' */ + _ACPI_XD|_ACPI_UP, /* 0x42 66. 'B' */ + _ACPI_XD|_ACPI_UP, /* 0x43 67. 'C' */ + _ACPI_XD|_ACPI_UP, /* 0x44 68. 'D' */ + _ACPI_XD|_ACPI_UP, /* 0x45 69. 'E' */ + _ACPI_XD|_ACPI_UP, /* 0x46 70. 'F' */ + _ACPI_UP, /* 0x47 71. 'G' */ + _ACPI_UP, /* 0x48 72. 'H' */ + _ACPI_UP, /* 0x49 73. 'I' */ + _ACPI_UP, /* 0x4A 74. 'J' */ + _ACPI_UP, /* 0x4B 75. 'K' */ + _ACPI_UP, /* 0x4C 76. 'L' */ + _ACPI_UP, /* 0x4D 77. 'M' */ + _ACPI_UP, /* 0x4E 78. 'N' */ + _ACPI_UP, /* 0x4F 79. 'O' */ + _ACPI_UP, /* 0x50 80. 'P' */ + _ACPI_UP, /* 0x51 81. 'Q' */ + _ACPI_UP, /* 0x52 82. 'R' */ + _ACPI_UP, /* 0x53 83. 'S' */ + _ACPI_UP, /* 0x54 84. 'T' */ + _ACPI_UP, /* 0x55 85. 'U' */ + _ACPI_UP, /* 0x56 86. 'V' */ + _ACPI_UP, /* 0x57 87. 'W' */ + _ACPI_UP, /* 0x58 88. 'X' */ + _ACPI_UP, /* 0x59 89. 'Y' */ + _ACPI_UP, /* 0x5A 90. 'Z' */ + _ACPI_PU, /* 0x5B 91. '[' */ + _ACPI_PU, /* 0x5C 92. '\' */ + _ACPI_PU, /* 0x5D 93. ']' */ + _ACPI_PU, /* 0x5E 94. '^' */ + _ACPI_PU, /* 0x5F 95. '_' */ + _ACPI_PU, /* 0x60 96. '`' */ + _ACPI_XD|_ACPI_LO, /* 0x61 97. 'a' */ + _ACPI_XD|_ACPI_LO, /* 0x62 98. 'b' */ + _ACPI_XD|_ACPI_LO, /* 0x63 99. 'c' */ + _ACPI_XD|_ACPI_LO, /* 0x64 100. 'd' */ + _ACPI_XD|_ACPI_LO, /* 0x65 101. 'e' */ + _ACPI_XD|_ACPI_LO, /* 0x66 102. 'f' */ + _ACPI_LO, /* 0x67 103. 'g' */ + _ACPI_LO, /* 0x68 104. 'h' */ + _ACPI_LO, /* 0x69 105. 'i' */ + _ACPI_LO, /* 0x6A 106. 'j' */ + _ACPI_LO, /* 0x6B 107. 'k' */ + _ACPI_LO, /* 0x6C 108. 'l' */ + _ACPI_LO, /* 0x6D 109. 'm' */ + _ACPI_LO, /* 0x6E 110. 'n' */ + _ACPI_LO, /* 0x6F 111. 'o' */ + _ACPI_LO, /* 0x70 112. 'p' */ + _ACPI_LO, /* 0x71 113. 'q' */ + _ACPI_LO, /* 0x72 114. 'r' */ + _ACPI_LO, /* 0x73 115. 's' */ + _ACPI_LO, /* 0x74 116. 't' */ + _ACPI_LO, /* 0x75 117. 'u' */ + _ACPI_LO, /* 0x76 118. 'v' */ + _ACPI_LO, /* 0x77 119. 'w' */ + _ACPI_LO, /* 0x78 120. 'x' */ + _ACPI_LO, /* 0x79 121. 'y' */ + _ACPI_LO, /* 0x7A 122. 'z' */ + _ACPI_PU, /* 0x7B 123. '{' */ + _ACPI_PU, /* 0x7C 124. '|' */ + _ACPI_PU, /* 0x7D 125. '}' */ + _ACPI_PU, /* 0x7E 126. '~' */ + _ACPI_CN, /* 0x7F 127. */ + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */ +}; + + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + diff --git a/source/components/utilities/utcopy.c b/source/components/utilities/utcopy.c new file mode 100644 index 000000000000..ab04a7a7aac8 --- /dev/null +++ b/source/components/utilities/utcopy.c @@ -0,0 +1,1078 @@ +/****************************************************************************** + * + * Module Name: utcopy - Internal to external object translation utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTCOPY_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utcopy") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtCopyIsimpleToEsimple ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_OBJECT *ExternalObject, + UINT8 *DataSpace, + ACPI_SIZE *BufferSpaceUsed); + +static ACPI_STATUS +AcpiUtCopyIelementToIelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + +static ACPI_STATUS +AcpiUtCopyIpackageToEpackage ( + ACPI_OPERAND_OBJECT *InternalObject, + UINT8 *Buffer, + ACPI_SIZE *SpaceUsed); + +static ACPI_STATUS +AcpiUtCopyEsimpleToIsimple( + ACPI_OBJECT *UserObj, + ACPI_OPERAND_OBJECT **ReturnObj); + +static ACPI_STATUS +AcpiUtCopyEpackageToIpackage ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject); + +static ACPI_STATUS +AcpiUtCopySimpleObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc); + +static ACPI_STATUS +AcpiUtCopyIelementToEelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + +static ACPI_STATUS +AcpiUtCopyIpackageToIpackage ( + ACPI_OPERAND_OBJECT *SourceObj, + ACPI_OPERAND_OBJECT *DestObj, + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIsimpleToEsimple + * + * PARAMETERS: InternalObject - Source object to be copied + * ExternalObject - Where to return the copied object + * DataSpace - Where object data is returned (such as + * buffer and string data) + * BufferSpaceUsed - Length of DataSpace that was used + * + * RETURN: Status + * + * DESCRIPTION: This function is called to copy a simple internal object to + * an external object. + * + * The DataSpace buffer is assumed to have sufficient space for + * the object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIsimpleToEsimple ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_OBJECT *ExternalObject, + UINT8 *DataSpace, + ACPI_SIZE *BufferSpaceUsed) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple); + + + *BufferSpaceUsed = 0; + + /* + * Check for NULL object case (could be an uninitialized + * package element) + */ + if (!InternalObject) + { + return_ACPI_STATUS (AE_OK); + } + + /* Always clear the external object */ + + ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + ExternalObject->Type = InternalObject->Common.Type; + + /* However, only a limited number of external types are supported */ + + switch (InternalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + ExternalObject->String.Pointer = (char *) DataSpace; + ExternalObject->String.Length = InternalObject->String.Length; + *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( + (ACPI_SIZE) InternalObject->String.Length + 1); + + ACPI_MEMCPY ((void *) DataSpace, + (void *) InternalObject->String.Pointer, + (ACPI_SIZE) InternalObject->String.Length + 1); + break; + + + case ACPI_TYPE_BUFFER: + + ExternalObject->Buffer.Pointer = DataSpace; + ExternalObject->Buffer.Length = InternalObject->Buffer.Length; + *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( + InternalObject->String.Length); + + ACPI_MEMCPY ((void *) DataSpace, + (void *) InternalObject->Buffer.Pointer, + InternalObject->Buffer.Length); + break; + + + case ACPI_TYPE_INTEGER: + + ExternalObject->Integer.Value = InternalObject->Integer.Value; + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* This is an object reference. */ + + switch (InternalObject->Reference.Class) + { + case ACPI_REFCLASS_NAME: + + /* + * For namepath, return the object handle ("reference") + * We are referring to the namespace node + */ + ExternalObject->Reference.Handle = + InternalObject->Reference.Node; + ExternalObject->Reference.ActualType = + AcpiNsGetType (InternalObject->Reference.Node); + break; + + default: + + /* All other reference types are unsupported */ + + return_ACPI_STATUS (AE_TYPE); + } + break; + + + case ACPI_TYPE_PROCESSOR: + + ExternalObject->Processor.ProcId = + InternalObject->Processor.ProcId; + ExternalObject->Processor.PblkAddress = + InternalObject->Processor.Address; + ExternalObject->Processor.PblkLength = + InternalObject->Processor.Length; + break; + + + case ACPI_TYPE_POWER: + + ExternalObject->PowerResource.SystemLevel = + InternalObject->PowerResource.SystemLevel; + + ExternalObject->PowerResource.ResourceOrder = + InternalObject->PowerResource.ResourceOrder; + break; + + + default: + /* + * There is no corresponding external object type + */ + ACPI_ERROR ((AE_INFO, + "Unsupported object type, cannot convert to external object: %s", + AcpiUtGetTypeName (InternalObject->Common.Type))); + + return_ACPI_STATUS (AE_SUPPORT); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIelementToEelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIelementToEelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; + ACPI_SIZE ObjectSpace; + UINT32 ThisIndex; + ACPI_OBJECT *TargetObject; + + + ACPI_FUNCTION_ENTRY (); + + + ThisIndex = State->Pkg.Index; + TargetObject = (ACPI_OBJECT *) + &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex]; + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * This is a simple or null object + */ + Status = AcpiUtCopyIsimpleToEsimple (SourceObject, + TargetObject, Info->FreeSpace, &ObjectSpace); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * Build the package object + */ + TargetObject->Type = ACPI_TYPE_PACKAGE; + TargetObject->Package.Count = SourceObject->Package.Count; + TargetObject->Package.Elements = + ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace); + + /* + * Pass the new package object back to the package walk routine + */ + State->Pkg.ThisTargetObj = TargetObject; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD ( + (ACPI_SIZE) TargetObject->Package.Count * + sizeof (ACPI_OBJECT)); + break; + + + default: + return (AE_BAD_PARAMETER); + } + + Info->FreeSpace += ObjectSpace; + Info->Length += ObjectSpace; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIpackageToEpackage + * + * PARAMETERS: InternalObject - Pointer to the object we are returning + * Buffer - Where the object is returned + * SpaceUsed - Where the object length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using + * the AcpiUtGetObjectSize function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIpackageToEpackage ( + ACPI_OPERAND_OBJECT *InternalObject, + UINT8 *Buffer, + ACPI_SIZE *SpaceUsed) +{ + ACPI_OBJECT *ExternalObject; + ACPI_STATUS Status; + ACPI_PKG_INFO Info; + + + ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage); + + + /* + * First package at head of the buffer + */ + ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer); + + /* + * Free space begins right after the first package + */ + Info.Length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + Info.FreeSpace = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD ( + sizeof (ACPI_OBJECT)); + Info.ObjectSpace = 0; + Info.NumPackages = 1; + + ExternalObject->Type = InternalObject->Common.Type; + ExternalObject->Package.Count = InternalObject->Package.Count; + ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT, + Info.FreeSpace); + + /* + * Leave room for an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + Info.Length += (ACPI_SIZE) ExternalObject->Package.Count * + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + Info.FreeSpace += ExternalObject->Package.Count * + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject, + AcpiUtCopyIelementToEelement, &Info); + + *SpaceUsed = Info.Length; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIobjectToEobject + * + * PARAMETERS: InternalObject - The internal object to be converted + * RetBuffer - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to build an API object to be returned + * to the caller. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyIobjectToEobject ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject); + + + if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE) + { + /* + * Package object: Copy all subobjects (including + * nested packages) + */ + Status = AcpiUtCopyIpackageToEpackage (InternalObject, + RetBuffer->Pointer, &RetBuffer->Length); + } + else + { + /* + * Build a simple object (no nested objects) + */ + Status = AcpiUtCopyIsimpleToEsimple (InternalObject, + ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer), + ACPI_ADD_PTR (UINT8, RetBuffer->Pointer, + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))), + &RetBuffer->Length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + RetBuffer->Length += sizeof (ACPI_OBJECT); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEsimpleToIsimple + * + * PARAMETERS: ExternalObject - The external object to be converted + * RetInternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyEsimpleToIsimple ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **RetInternalObject) +{ + ACPI_OPERAND_OBJECT *InternalObject; + + + ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple); + + + /* + * Simple types supported are: String, Buffer, Integer + */ + switch (ExternalObject->Type) + { + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_LOCAL_REFERENCE: + + InternalObject = AcpiUtCreateInternalObject ( + (UINT8) ExternalObject->Type); + if (!InternalObject) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + break; + + case ACPI_TYPE_ANY: /* This is the case for a NULL object */ + + *RetInternalObject = NULL; + return_ACPI_STATUS (AE_OK); + + default: + /* All other types are not supported */ + + ACPI_ERROR ((AE_INFO, + "Unsupported object type, cannot convert to internal object: %s", + AcpiUtGetTypeName (ExternalObject->Type))); + + return_ACPI_STATUS (AE_SUPPORT); + } + + + /* Must COPY string and buffer contents */ + + switch (ExternalObject->Type) + { + case ACPI_TYPE_STRING: + + InternalObject->String.Pointer = + ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) + ExternalObject->String.Length + 1); + + if (!InternalObject->String.Pointer) + { + goto ErrorExit; + } + + ACPI_MEMCPY (InternalObject->String.Pointer, + ExternalObject->String.Pointer, + ExternalObject->String.Length); + + InternalObject->String.Length = ExternalObject->String.Length; + break; + + + case ACPI_TYPE_BUFFER: + + InternalObject->Buffer.Pointer = + ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length); + if (!InternalObject->Buffer.Pointer) + { + goto ErrorExit; + } + + ACPI_MEMCPY (InternalObject->Buffer.Pointer, + ExternalObject->Buffer.Pointer, + ExternalObject->Buffer.Length); + + InternalObject->Buffer.Length = ExternalObject->Buffer.Length; + + /* Mark buffer data valid */ + + InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID; + break; + + + case ACPI_TYPE_INTEGER: + + InternalObject->Integer.Value = ExternalObject->Integer.Value; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* TBD: should validate incoming handle */ + + InternalObject->Reference.Class = ACPI_REFCLASS_NAME; + InternalObject->Reference.Node = ExternalObject->Reference.Handle; + break; + + default: + /* Other types can't get here */ + break; + } + + *RetInternalObject = InternalObject; + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + AcpiUtRemoveReference (InternalObject); + return_ACPI_STATUS (AE_NO_MEMORY); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEpackageToIpackage + * + * PARAMETERS: ExternalObject - The external object to be converted + * InternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Copy an external package object to an internal package. + * Handles nested packages. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyEpackageToIpackage ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *PackageObject; + ACPI_OPERAND_OBJECT **PackageElements; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage); + + + /* Create the package object */ + + PackageObject = AcpiUtCreatePackageObject (ExternalObject->Package.Count); + if (!PackageObject) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + PackageElements = PackageObject->Package.Elements; + + /* + * Recursive implementation. Probably ok, since nested external packages + * as parameters should be very rare. + */ + for (i = 0; i < ExternalObject->Package.Count; i++) + { + Status = AcpiUtCopyEobjectToIobject ( + &ExternalObject->Package.Elements[i], + &PackageElements[i]); + if (ACPI_FAILURE (Status)) + { + /* Truncate package and delete it */ + + PackageObject->Package.Count = i; + PackageElements[i] = NULL; + AcpiUtRemoveReference (PackageObject); + return_ACPI_STATUS (Status); + } + } + + /* Mark package data valid */ + + PackageObject->Package.Flags |= AOPOBJ_DATA_VALID; + + *InternalObject = PackageObject; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEobjectToIobject + * + * PARAMETERS: ExternalObject - The external object to be converted + * InternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyEobjectToIobject ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject); + + + if (ExternalObject->Type == ACPI_TYPE_PACKAGE) + { + Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject); + } + else + { + /* + * Build a simple object (no nested objects) + */ + Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopySimpleObject + * + * PARAMETERS: SourceDesc - The internal object to be copied + * DestDesc - New target object + * + * RETURN: Status + * + * DESCRIPTION: Simple copy of one internal object to another. Reference count + * of the destination object is preserved. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopySimpleObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc) +{ + UINT16 ReferenceCount; + ACPI_OPERAND_OBJECT *NextObject; + ACPI_STATUS Status; + ACPI_SIZE CopySize; + + + /* Save fields from destination that we don't want to overwrite */ + + ReferenceCount = DestDesc->Common.ReferenceCount; + NextObject = DestDesc->Common.NextObject; + + /* + * Copy the entire source object over the destination object. + * Note: Source can be either an operand object or namespace node. + */ + CopySize = sizeof (ACPI_OPERAND_OBJECT); + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) + { + CopySize = sizeof (ACPI_NAMESPACE_NODE); + } + + ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc), + ACPI_CAST_PTR (char, SourceDesc), CopySize); + + /* Restore the saved fields */ + + DestDesc->Common.ReferenceCount = ReferenceCount; + DestDesc->Common.NextObject = NextObject; + + /* New object is not static, regardless of source */ + + DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; + + /* Handle the objects with extra data */ + + switch (DestDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + /* + * Allocate and copy the actual buffer if and only if: + * 1) There is a valid buffer pointer + * 2) The buffer has a length > 0 + */ + if ((SourceDesc->Buffer.Pointer) && + (SourceDesc->Buffer.Length)) + { + DestDesc->Buffer.Pointer = + ACPI_ALLOCATE (SourceDesc->Buffer.Length); + if (!DestDesc->Buffer.Pointer) + { + return (AE_NO_MEMORY); + } + + /* Copy the actual buffer data */ + + ACPI_MEMCPY (DestDesc->Buffer.Pointer, + SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); + } + break; + + case ACPI_TYPE_STRING: + /* + * Allocate and copy the actual string if and only if: + * 1) There is a valid string pointer + * (Pointer to a NULL string is allowed) + */ + if (SourceDesc->String.Pointer) + { + DestDesc->String.Pointer = + ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1); + if (!DestDesc->String.Pointer) + { + return (AE_NO_MEMORY); + } + + /* Copy the actual string data */ + + ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, + (ACPI_SIZE) SourceDesc->String.Length + 1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * We copied the reference object, so we now must add a reference + * to the object pointed to by the reference + * + * DDBHandle reference (from Load/LoadTable) is a special reference, + * it does not have a Reference.Object, so does not need to + * increase the reference count + */ + if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) + { + break; + } + + AcpiUtAddReference (SourceDesc->Reference.Object); + break; + + case ACPI_TYPE_REGION: + /* + * We copied the Region Handler, so we now must add a reference + */ + if (DestDesc->Region.Handler) + { + AcpiUtAddReference (DestDesc->Region.Handler); + } + break; + + /* + * For Mutex and Event objects, we cannot simply copy the underlying + * OS object. We must create a new one. + */ + case ACPI_TYPE_MUTEX: + + Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_EVENT: + + Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, + &DestDesc->Event.OsSemaphore); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + default: + /* Nothing to do for other simple objects */ + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIelementToIelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIelementToIelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + UINT32 ThisIndex; + ACPI_OPERAND_OBJECT **ThisTargetPtr; + ACPI_OPERAND_OBJECT *TargetObject; + + + ACPI_FUNCTION_ENTRY (); + + + ThisIndex = State->Pkg.Index; + ThisTargetPtr = (ACPI_OPERAND_OBJECT **) + &State->Pkg.DestObject->Package.Elements[ThisIndex]; + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* A null source object indicates a (legal) null package element */ + + if (SourceObject) + { + /* + * This is a simple object, just copy it + */ + TargetObject = AcpiUtCreateInternalObject ( + SourceObject->Common.Type); + if (!TargetObject) + { + return (AE_NO_MEMORY); + } + + Status = AcpiUtCopySimpleObject (SourceObject, TargetObject); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + *ThisTargetPtr = TargetObject; + } + else + { + /* Pass through a null element */ + + *ThisTargetPtr = NULL; + } + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * This object is a package - go down another nesting level + * Create and build the package object + */ + TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count); + if (!TargetObject) + { + return (AE_NO_MEMORY); + } + + TargetObject->Common.Flags = SourceObject->Common.Flags; + + /* Pass the new package object back to the package walk routine */ + + State->Pkg.ThisTargetObj = TargetObject; + + /* Store the object pointer in the parent package object */ + + *ThisTargetPtr = TargetObject; + break; + + + default: + return (AE_BAD_PARAMETER); + } + + return (Status); + +ErrorExit: + AcpiUtRemoveReference (TargetObject); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIpackageToIpackage + * + * PARAMETERS: SourceObj - Pointer to the source package object + * DestObj - Where the internal object is returned + * WalkState - Current Walk state descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIpackageToIpackage ( + ACPI_OPERAND_OBJECT *SourceObj, + ACPI_OPERAND_OBJECT *DestObj, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage); + + + DestObj->Common.Type = SourceObj->Common.Type; + DestObj->Common.Flags = SourceObj->Common.Flags; + DestObj->Package.Count = SourceObj->Package.Count; + + /* + * Create the object array and walk the source package tree + */ + DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) SourceObj->Package.Count + 1) * + sizeof (void *)); + if (!DestObj->Package.Elements) + { + ACPI_ERROR ((AE_INFO, "Package allocation failure")); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Copy the package element-by-element by walking the package "tree". + * This handles nested packages of arbitrary depth. + */ + Status = AcpiUtWalkPackageTree (SourceObj, DestObj, + AcpiUtCopyIelementToIelement, WalkState); + if (ACPI_FAILURE (Status)) + { + /* On failure, delete the destination package object */ + + AcpiUtRemoveReference (DestObj); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIobjectToIobject + * + * PARAMETERS: SourceDesc - The internal object to be copied + * DestDesc - Where the copied object is returned + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Copy an internal object to a new internal object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyIobjectToIobject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **DestDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject); + + + /* Create the top level object */ + + *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type); + if (!*DestDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the object and possible subobjects */ + + if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc, + WalkState); + } + else + { + Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc); + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/utilities/utdebug.c b/source/components/utilities/utdebug.c new file mode 100644 index 000000000000..051d47b4430a --- /dev/null +++ b/source/components/utilities/utdebug.c @@ -0,0 +1,741 @@ +/****************************************************************************** + * + * Module Name: utdebug - Debug print routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDEBUG_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdebug") + + +#ifdef ACPI_DEBUG_OUTPUT + +static ACPI_THREAD_ID AcpiGbl_PrevThreadId = (ACPI_THREAD_ID) 0xFFFFFFFF; +static char *AcpiGbl_FnEntryStr = "----Entry"; +static char *AcpiGbl_FnExitStr = "----Exit-"; + +/* Local prototypes */ + +static const char * +AcpiUtTrimFunctionName ( + const char *FunctionName); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitStackPtrTrace + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer at subsystem startup + * + ******************************************************************************/ + +void +AcpiUtInitStackPtrTrace ( + void) +{ + ACPI_SIZE CurrentSp; + + + AcpiGbl_EntryStackPointer = &CurrentSp; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrackStackPtr + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer + * + ******************************************************************************/ + +void +AcpiUtTrackStackPtr ( + void) +{ + ACPI_SIZE CurrentSp; + + + if (&CurrentSp < AcpiGbl_LowestStackPointer) + { + AcpiGbl_LowestStackPointer = &CurrentSp; + } + + if (AcpiGbl_NestingLevel > AcpiGbl_DeepestNesting) + { + AcpiGbl_DeepestNesting = AcpiGbl_NestingLevel; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrimFunctionName + * + * PARAMETERS: FunctionName - Ascii string containing a procedure name + * + * RETURN: Updated pointer to the function name + * + * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. + * This allows compiler macros such as __FUNCTION__ to be used + * with no change to the debug output. + * + ******************************************************************************/ + +static const char * +AcpiUtTrimFunctionName ( + const char *FunctionName) +{ + + /* All Function names are longer than 4 chars, check is safe */ + + if (*(ACPI_CAST_PTR (UINT32, FunctionName)) == ACPI_PREFIX_MIXED) + { + /* This is the case where the original source has not been modified */ + + return (FunctionName + 4); + } + + if (*(ACPI_CAST_PTR (UINT32, FunctionName)) == ACPI_PREFIX_LOWER) + { + /* This is the case where the source has been 'linuxized' */ + + return (FunctionName + 5); + } + + return (FunctionName); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDebugPrint + * + * PARAMETERS: RequestedDebugLevel - Requested debug print level + * LineNumber - Caller's line number (for error output) + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrint ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) +{ + ACPI_THREAD_ID ThreadId; + va_list args; + + + /* + * Stay silent if the debug level or component ID is disabled + */ + if (!(RequestedDebugLevel & AcpiDbgLevel) || + !(ComponentId & AcpiDbgLayer)) + { + return; + } + + /* + * Thread tracking and context switch notification + */ + ThreadId = AcpiOsGetThreadId (); + if (ThreadId != AcpiGbl_PrevThreadId) + { + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ( + "\n**** Context Switch from TID %u to TID %u ****\n\n", + (UINT32) AcpiGbl_PrevThreadId, (UINT32) ThreadId); + } + + AcpiGbl_PrevThreadId = ThreadId; + } + + /* + * Display the module name, current line number, thread ID (if requested), + * current procedure nesting level, and the current procedure name + */ + AcpiOsPrintf ("%8s-%04ld ", ModuleName, LineNumber); + + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ("[%u] ", (UINT32) ThreadId); + } + + AcpiOsPrintf ("[%02ld] %-22.22s: ", + AcpiGbl_NestingLevel, AcpiUtTrimFunctionName (FunctionName)); + + va_start (args, Format); + AcpiOsVprintf (Format, args); + va_end (args); +} + +ACPI_EXPORT_SYMBOL (AcpiDebugPrint) + + +/******************************************************************************* + * + * FUNCTION: AcpiDebugPrintRaw + * + * PARAMETERS: RequestedDebugLevel - Requested debug print level + * LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print message with no headers. Has same interface as + * DebugPrint so that the same macros can be used. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrintRaw ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) +{ + va_list args; + + + if (!(RequestedDebugLevel & AcpiDbgLevel) || + !(ComponentId & AcpiDbgLayer)) + { + return; + } + + va_start (args, Format); + AcpiOsVprintf (Format, args); + va_end (args); +} + +ACPI_EXPORT_SYMBOL (AcpiDebugPrintRaw) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrace + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTrace ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FnEntryStr); +} + +ACPI_EXPORT_SYMBOL (AcpiUtTrace) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTracePtr + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTracePtr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + void *Pointer) +{ + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FnEntryStr, Pointer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTraceStr + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTraceStr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + char *String) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FnEntryStr, String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTraceU32 + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTraceU32 ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT32 Integer) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %08X\n", AcpiGbl_FnEntryStr, Integer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FnExitStr); + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStatusExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit status also. + * + ******************************************************************************/ + +void +AcpiUtStatusExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + ACPI_STATUS Status) +{ + + if (ACPI_SUCCESS (Status)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FnExitStr, + AcpiFormatException (Status)); + } + else + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s ****Exception****: %s\n", AcpiGbl_FnExitStr, + AcpiFormatException (Status)); + } + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtStatusExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValueExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit value also. + * + ******************************************************************************/ + +void +AcpiUtValueExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT64 Value) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr, + ACPI_FORMAT_UINT64 (Value)); + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtValueExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPtrExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Ptr - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit value also. + * + ******************************************************************************/ + +void +AcpiUtPtrExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT8 *Ptr) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FnExitStr, Ptr); + + AcpiGbl_NestingLevel--; +} + +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * ComponentID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDumpBuffer2 ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display) +{ + UINT32 i = 0; + UINT32 j; + UINT32 Temp32; + UINT8 BufChar; + + + if (!Buffer) + { + AcpiOsPrintf ("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((Count < 4) || (Count & 0x01)) + { + Display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < Count) + { + /* Print current offset */ + + AcpiOsPrintf ("%6.4X: ", i); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) + { + if (i + j >= Count) + { + /* Dump fill spaces */ + + AcpiOsPrintf ("%*s", ((Display * 2) + 1), " "); + j += Display; + continue; + } + + switch (Display) + { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + AcpiOsPrintf ("%02X ", Buffer[(ACPI_SIZE) i + j]); + break; + + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%04X ", Temp32); + break; + + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%08X ", Temp32); + break; + + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%08X", Temp32); + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j + 4]); + AcpiOsPrintf ("%08X ", Temp32); + break; + } + + j += Display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + AcpiOsPrintf (" "); + for (j = 0; j < 16; j++) + { + if (i + j >= Count) + { + AcpiOsPrintf ("\n"); + return; + } + + BufChar = Buffer[(ACPI_SIZE) i + j]; + if (ACPI_IS_PRINT (BufChar)) + { + AcpiOsPrintf ("%c", BufChar); + } + else + { + AcpiOsPrintf ("."); + } + } + + /* Done with that line. */ + + AcpiOsPrintf ("\n"); + i += 16; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * ComponentID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 ComponentId) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & AcpiDbgLevel) && + (ComponentId & AcpiDbgLayer))) + { + return; + } + + AcpiUtDumpBuffer2 (Buffer, Count, Display); +} + + diff --git a/source/components/utilities/utdecode.c b/source/components/utilities/utdecode.c new file mode 100644 index 000000000000..718d73db4e3b --- /dev/null +++ b/source/components/utilities/utdecode.c @@ -0,0 +1,637 @@ +/****************************************************************************** + * + * Module Name: utdecode - Utility decoding routines (value-to-string) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDECODE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdecode") + + +/******************************************************************************* + * + * FUNCTION: AcpiFormatException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string + * It is here instead of utxface.c so it is always present. + * + ******************************************************************************/ + +const char * +AcpiFormatException ( + ACPI_STATUS Status) +{ + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + Exception = AcpiUtValidateException (Status); + if (!Exception) + { + /* Exception code was not recognized */ + + ACPI_ERROR ((AE_INFO, + "Unknown exception code: 0x%8.8X", Status)); + + Exception = "UNKNOWN_STATUS_CODE"; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} + +ACPI_EXPORT_SYMBOL (AcpiFormatException) + + +/* + * Properties of the ACPI Object Types, both internal and external. + * The table is indexed by values of ACPI_OBJECT_TYPE + */ +const UINT8 AcpiGbl_NsProperties[ACPI_NUM_NS_TYPES] = +{ + ACPI_NS_NORMAL, /* 00 Any */ + ACPI_NS_NORMAL, /* 01 Number */ + ACPI_NS_NORMAL, /* 02 String */ + ACPI_NS_NORMAL, /* 03 Buffer */ + ACPI_NS_NORMAL, /* 04 Package */ + ACPI_NS_NORMAL, /* 05 FieldUnit */ + ACPI_NS_NEWSCOPE, /* 06 Device */ + ACPI_NS_NORMAL, /* 07 Event */ + ACPI_NS_NEWSCOPE, /* 08 Method */ + ACPI_NS_NORMAL, /* 09 Mutex */ + ACPI_NS_NORMAL, /* 10 Region */ + ACPI_NS_NEWSCOPE, /* 11 Power */ + ACPI_NS_NEWSCOPE, /* 12 Processor */ + ACPI_NS_NEWSCOPE, /* 13 Thermal */ + ACPI_NS_NORMAL, /* 14 BufferField */ + ACPI_NS_NORMAL, /* 15 DdbHandle */ + ACPI_NS_NORMAL, /* 16 Debug Object */ + ACPI_NS_NORMAL, /* 17 DefField */ + ACPI_NS_NORMAL, /* 18 BankField */ + ACPI_NS_NORMAL, /* 19 IndexField */ + ACPI_NS_NORMAL, /* 20 Reference */ + ACPI_NS_NORMAL, /* 21 Alias */ + ACPI_NS_NORMAL, /* 22 MethodAlias */ + ACPI_NS_NORMAL, /* 23 Notify */ + ACPI_NS_NORMAL, /* 24 Address Handler */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ + ACPI_NS_NEWSCOPE, /* 27 Scope */ + ACPI_NS_NORMAL, /* 28 Extra */ + ACPI_NS_NORMAL, /* 29 Data */ + ACPI_NS_NORMAL /* 30 Invalid */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtHexToAsciiChar + * + * PARAMETERS: Integer - Contains the hex digit + * Position - bit position of the digit within the + * integer (multiple of 4) + * + * RETURN: The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +/* Hex to ASCII conversion table */ + +static const char AcpiGbl_HexToAscii[] = +{ + '0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F' +}; + +char +AcpiUtHexToAsciiChar ( + UINT64 Integer, + UINT32 Position) +{ + + return (AcpiGbl_HexToAscii[(Integer >> Position) & 0xF]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetRegionName + * + * PARAMETERS: Space ID - ID for the region + * + * RETURN: Decoded region SpaceId name + * + * DESCRIPTION: Translate a Space ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Region type decoding */ + +const char *AcpiGbl_RegionTypes[ACPI_NUM_PREDEFINED_REGIONS] = +{ + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + "SystemCMOS", + "PCIBARTarget", + "IPMI", + "GeneralPurposeIo", + "GenericSerialBus" +}; + + +char * +AcpiUtGetRegionName ( + UINT8 SpaceId) +{ + + if (SpaceId >= ACPI_USER_REGION_BEGIN) + { + return ("UserDefinedRegion"); + } + else if (SpaceId == ACPI_ADR_SPACE_DATA_TABLE) + { + return ("DataTable"); + } + else if (SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE) + { + return ("FunctionalFixedHW"); + } + else if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) + { + return ("InvalidSpaceId"); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_RegionTypes[SpaceId])); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetEventName + * + * PARAMETERS: EventId - Fixed event ID + * + * RETURN: Decoded event ID name + * + * DESCRIPTION: Translate a Event ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Event type decoding */ + +static const char *AcpiGbl_EventTypes[ACPI_NUM_FIXED_EVENTS] = +{ + "PM_Timer", + "GlobalLock", + "PowerButton", + "SleepButton", + "RealTimeClock", +}; + + +char * +AcpiUtGetEventName ( + UINT32 EventId) +{ + + if (EventId > ACPI_EVENT_MAX) + { + return ("InvalidEventID"); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_EventTypes[EventId])); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetTypeName + * + * PARAMETERS: Type - An ACPI object type + * + * RETURN: Decoded ACPI object type name + * + * DESCRIPTION: Translate a Type ID into a name string (Debug only) + * + ******************************************************************************/ + +/* + * Elements of AcpiGbl_NsTypeNames below must match + * one-to-one with values of ACPI_OBJECT_TYPE + * + * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; + * when stored in a table it really means that we have thus far seen no + * evidence to indicate what type is actually going to be stored for this entry. + */ +static const char AcpiGbl_BadType[] = "UNDEFINED"; + +/* Printable names of the ACPI object types */ + +static const char *AcpiGbl_NsTypeNames[] = +{ + /* 00 */ "Untyped", + /* 01 */ "Integer", + /* 02 */ "String", + /* 03 */ "Buffer", + /* 04 */ "Package", + /* 05 */ "FieldUnit", + /* 06 */ "Device", + /* 07 */ "Event", + /* 08 */ "Method", + /* 09 */ "Mutex", + /* 10 */ "Region", + /* 11 */ "Power", + /* 12 */ "Processor", + /* 13 */ "Thermal", + /* 14 */ "BufferField", + /* 15 */ "DdbHandle", + /* 16 */ "DebugObject", + /* 17 */ "RegionField", + /* 18 */ "BankField", + /* 19 */ "IndexField", + /* 20 */ "Reference", + /* 21 */ "Alias", + /* 22 */ "MethodAlias", + /* 23 */ "Notify", + /* 24 */ "AddrHandler", + /* 25 */ "ResourceDesc", + /* 26 */ "ResourceFld", + /* 27 */ "Scope", + /* 28 */ "Extra", + /* 29 */ "Data", + /* 30 */ "Invalid" +}; + + +char * +AcpiUtGetTypeName ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type > ACPI_TYPE_INVALID) + { + return (ACPI_CAST_PTR (char, AcpiGbl_BadType)); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_NsTypeNames[Type])); +} + + +char * +AcpiUtGetObjectTypeName ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + + if (!ObjDesc) + { + return ("[NULL Object Descriptor]"); + } + + return (AcpiUtGetTypeName (ObjDesc->Common.Type)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetNodeName + * + * PARAMETERS: Object - A namespace node + * + * RETURN: ASCII name of the node + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ******************************************************************************/ + +char * +AcpiUtGetNodeName ( + void *Object) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) Object; + + + /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + + if (!Object) + { + return ("NULL"); + } + + /* Check for Root node */ + + if ((Object == ACPI_ROOT_OBJECT) || + (Object == AcpiGbl_RootNode)) + { + return ("\"\\\" "); + } + + /* Descriptor must be a namespace node */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + return ("####"); + } + + /* + * Ensure name is valid. The name was validated/repaired when the node + * was created, but make sure it has not been corrupted. + */ + AcpiUtRepairName (Node->Name.Ascii); + + /* Return the name */ + + return (Node->Name.Ascii); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetDescriptorName + * + * PARAMETERS: Object - An ACPI object + * + * RETURN: Decoded name of the descriptor type + * + * DESCRIPTION: Validate object and return the descriptor type + * + ******************************************************************************/ + +/* Printable names of object descriptor types */ + +static const char *AcpiGbl_DescTypeNames[] = +{ + /* 00 */ "Not a Descriptor", + /* 01 */ "Cached", + /* 02 */ "State-Generic", + /* 03 */ "State-Update", + /* 04 */ "State-Package", + /* 05 */ "State-Control", + /* 06 */ "State-RootParseScope", + /* 07 */ "State-ParseScope", + /* 08 */ "State-WalkScope", + /* 09 */ "State-Result", + /* 10 */ "State-Notify", + /* 11 */ "State-Thread", + /* 12 */ "Walk", + /* 13 */ "Parser", + /* 14 */ "Operand", + /* 15 */ "Node" +}; + + +char * +AcpiUtGetDescriptorName ( + void *Object) +{ + + if (!Object) + { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) > ACPI_DESC_TYPE_MAX) + { + return ("Not a Descriptor"); + } + + return (ACPI_CAST_PTR (char, + AcpiGbl_DescTypeNames[ACPI_GET_DESCRIPTOR_TYPE (Object)])); + +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetReferenceName + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Decoded name of the type of reference + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *AcpiGbl_RefClassNames[] = +{ + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + +const char * +AcpiUtGetReferenceName ( + ACPI_OPERAND_OBJECT *Object) +{ + + if (!Object) + { + return ("NULL Object"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) + { + return ("Not an Operand object"); + } + + if (Object->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) + { + return ("Not a Reference object"); + } + + if (Object->Reference.Class > ACPI_REFCLASS_MAX) + { + return ("Unknown Reference class"); + } + + return (AcpiGbl_RefClassNames[Object->Reference.Class]); +} + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetMutexName + * + * PARAMETERS: MutexId - The predefined ID for this mutex. + * + * RETURN: Decoded name of the internal mutex + * + * DESCRIPTION: Translate a mutex ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Names for internal mutex objects, used for debug output */ + +static char *AcpiGbl_MutexNames[ACPI_NUM_MUTEX] = +{ + "ACPI_MTX_Interpreter", + "ACPI_MTX_Namespace", + "ACPI_MTX_Tables", + "ACPI_MTX_Events", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", + "ACPI_MTX_CommandComplete", + "ACPI_MTX_CommandReady" +}; + +char * +AcpiUtGetMutexName ( + UINT32 MutexId) +{ + + if (MutexId > ACPI_MAX_MUTEX) + { + return ("Invalid Mutex ID"); + } + + return (AcpiGbl_MutexNames[MutexId]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetNotifyName + * + * PARAMETERS: NotifyValue - Value from the Notify() request + * + * RETURN: Decoded name for the notify value + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *AcpiGbl_NotifyValueNames[ACPI_NOTIFY_MAX + 1] = +{ + /* 00 */ "Bus Check", + /* 01 */ "Device Check", + /* 02 */ "Device Wake", + /* 03 */ "Eject Request", + /* 04 */ "Device Check Light", + /* 05 */ "Frequency Mismatch", + /* 06 */ "Bus Mode Mismatch", + /* 07 */ "Power Fault", + /* 08 */ "Capabilities Check", + /* 09 */ "Device PLD Check", + /* 10 */ "Reserved", + /* 11 */ "System Locality Update", + /* 12 */ "Shutdown Request" +}; + +const char * +AcpiUtGetNotifyName ( + UINT32 NotifyValue) +{ + + if (NotifyValue <= ACPI_NOTIFY_MAX) + { + return (AcpiGbl_NotifyValueNames[NotifyValue]); + } + else if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) + { + return ("Reserved"); + } + else if (NotifyValue <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) + { + return ("Device Specific"); + } + else + { + return ("Hardware Specific"); + } +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidObjectType + * + * PARAMETERS: Type - Object type to be validated + * + * RETURN: TRUE if valid object type, FALSE otherwise + * + * DESCRIPTION: Validate an object type + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidObjectType ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type > ACPI_TYPE_LOCAL_MAX) + { + /* Note: Assumes all TYPEs are contiguous (external/local) */ + + return (FALSE); + } + + return (TRUE); +} diff --git a/source/components/utilities/utdelete.c b/source/components/utilities/utdelete.c new file mode 100644 index 000000000000..90baa15d225e --- /dev/null +++ b/source/components/utilities/utdelete.c @@ -0,0 +1,766 @@ +/******************************************************************************* + * + * Module Name: utdelete - object deletion and reference count utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDELETE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdelete") + +/* Local prototypes */ + +static void +AcpiUtDeleteInternalObj ( + ACPI_OPERAND_OBJECT *Object); + +static void +AcpiUtUpdateRefCount ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Action); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteInternalObj + * + * PARAMETERS: Object - Object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +static void +AcpiUtDeleteInternalObj ( + ACPI_OPERAND_OBJECT *Object) +{ + void *ObjPointer = NULL; + ACPI_OPERAND_OBJECT *HandlerDesc; + ACPI_OPERAND_OBJECT *SecondDesc; + ACPI_OPERAND_OBJECT *NextDesc; + ACPI_OPERAND_OBJECT **LastObjPtr; + + + ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object); + + + if (!Object) + { + return_VOID; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + switch (Object->Common.Type) + { + case ACPI_TYPE_STRING: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n", + Object, Object->String.Pointer)); + + /* Free the actual string buffer */ + + if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) + { + /* But only if it is NOT a pointer into an ACPI table */ + + ObjPointer = Object->String.Pointer; + } + break; + + + case ACPI_TYPE_BUFFER: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n", + Object, Object->Buffer.Pointer)); + + /* Free the actual buffer */ + + if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) + { + /* But only if it is NOT a pointer into an ACPI table */ + + ObjPointer = Object->Buffer.Pointer; + } + break; + + + case ACPI_TYPE_PACKAGE: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n", + Object->Package.Count)); + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + ObjPointer = Object->Package.Elements; + break; + + + /* + * These objects have a possible list of notify handlers. + * Device object also may have a GPE block. + */ + case ACPI_TYPE_DEVICE: + + if (Object->Device.GpeBlock) + { + (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock); + } + + /*lint -fallthrough */ + + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Walk the notify handler list for this object */ + + HandlerDesc = Object->CommonNotify.Handler; + while (HandlerDesc) + { + NextDesc = HandlerDesc->AddressSpace.Next; + AcpiUtRemoveReference (HandlerDesc); + HandlerDesc = NextDesc; + } + break; + + + case ACPI_TYPE_MUTEX: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Mutex %p, OS Mutex %p\n", + Object, Object->Mutex.OsMutex)); + + if (Object == AcpiGbl_GlobalLockMutex) + { + /* Global Lock has extra semaphore */ + + (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore); + AcpiGbl_GlobalLockSemaphore = NULL; + + AcpiOsDeleteMutex (Object->Mutex.OsMutex); + AcpiGbl_GlobalLockMutex = NULL; + } + else + { + AcpiExUnlinkMutex (Object); + AcpiOsDeleteMutex (Object->Mutex.OsMutex); + } + break; + + + case ACPI_TYPE_EVENT: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Event %p, OS Semaphore %p\n", + Object, Object->Event.OsSemaphore)); + + (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore); + Object->Event.OsSemaphore = NULL; + break; + + + case ACPI_TYPE_METHOD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Method %p\n", Object)); + + /* Delete the method mutex if it exists */ + + if (Object->Method.Mutex) + { + AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex); + AcpiUtDeleteObjectDesc (Object->Method.Mutex); + Object->Method.Mutex = NULL; + } + break; + + + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Region %p\n", Object)); + + /* + * Update AddressRange list. However, only permanent regions + * are installed in this list. (Not created within a method) + */ + if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY)) + { + AcpiUtRemoveAddressRange (Object->Region.SpaceId, + Object->Region.Node); + } + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + /* + * Free the RegionContext if and only if the handler is one of the + * default handlers -- and therefore, we created the context object + * locally, it was not created by an external caller. + */ + HandlerDesc = Object->Region.Handler; + if (HandlerDesc) + { + NextDesc = HandlerDesc->AddressSpace.RegionList; + LastObjPtr = &HandlerDesc->AddressSpace.RegionList; + + /* Remove the region object from the handler's list */ + + while (NextDesc) + { + if (NextDesc == Object) + { + *LastObjPtr = NextDesc->Region.Next; + break; + } + + /* Walk the linked list of handler */ + + LastObjPtr = &NextDesc->Region.Next; + NextDesc = NextDesc->Region.Next; + } + + if (HandlerDesc->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + { + /* Deactivate region and free region context */ + + if (HandlerDesc->AddressSpace.Setup) + { + (void) HandlerDesc->AddressSpace.Setup (Object, + ACPI_REGION_DEACTIVATE, + HandlerDesc->AddressSpace.Context, + &SecondDesc->Extra.RegionContext); + } + } + + AcpiUtRemoveReference (HandlerDesc); + } + + /* Now we can free the Extra object */ + + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Buffer Field %p\n", Object)); + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Bank Field %p\n", Object)); + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + default: + break; + } + + /* Free any allocated memory (pointer within the object) found above */ + + if (ObjPointer) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", + ObjPointer)); + ACPI_FREE (ObjPointer); + } + + /* Now the object can be safely deleted */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", + Object, AcpiUtGetObjectTypeName (Object))); + + AcpiUtDeleteObjectDesc (Object); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteInternalObjectList + * + * PARAMETERS: ObjList - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +void +AcpiUtDeleteInternalObjectList ( + ACPI_OPERAND_OBJECT **ObjList) +{ + ACPI_OPERAND_OBJECT **InternalObj; + + + ACPI_FUNCTION_TRACE (UtDeleteInternalObjectList); + + + /* Walk the null-terminated internal list */ + + for (InternalObj = ObjList; *InternalObj; InternalObj++) + { + AcpiUtRemoveReference (*InternalObj); + } + + /* Free the combined parameter pointer list and object array */ + + ACPI_FREE (ObjList); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateRefCount + * + * PARAMETERS: Object - Object whose ref count is to be updated + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +static void +AcpiUtUpdateRefCount ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Action) +{ + UINT16 Count; + UINT16 NewCount; + + + ACPI_FUNCTION_NAME (UtUpdateRefCount); + + + if (!Object) + { + return; + } + + Count = Object->Common.ReferenceCount; + NewCount = Count; + + /* + * Perform the reference count action (increment, decrement, force delete) + */ + switch (Action) + { + case REF_INCREMENT: + + NewCount++; + Object->Common.ReferenceCount = NewCount; + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Incremented]\n", + Object, NewCount)); + break; + + case REF_DECREMENT: + + if (Count < 1) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, can't decrement! (Set to 0)\n", + Object, NewCount)); + + NewCount = 0; + } + else + { + NewCount--; + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Decremented]\n", + Object, NewCount)); + } + + if (Object->Common.Type == ACPI_TYPE_METHOD) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount)); + } + + Object->Common.ReferenceCount = NewCount; + if (NewCount == 0) + { + AcpiUtDeleteInternalObj (Object); + } + break; + + case REF_FORCE_DELETE: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count)); + + NewCount = 0; + Object->Common.ReferenceCount = NewCount; + AcpiUtDeleteInternalObj (Object); + break; + + default: + + ACPI_ERROR ((AE_INFO, "Unknown action (0x%X)", Action)); + break; + } + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + if (Count > ACPI_MAX_REFERENCE_COUNT) + { + ACPI_WARNING ((AE_INFO, + "Large Reference Count (0x%X) in object %p", Count, Object)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateObjectReference + * + * PARAMETERS: Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is attached to a Node (namespace object) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is detached from an Node + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtUpdateObjectReference ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *StateList = NULL; + ACPI_OPERAND_OBJECT *NextObject = NULL; + ACPI_GENERIC_STATE *State; + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (UtUpdateObjectReference, Object); + + + while (Object) + { + /* Make sure that this isn't a namespace handle */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Object %p is NS handle\n", Object)); + return_ACPI_STATUS (AE_OK); + } + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (Object->Common.Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + case ACPI_TYPE_THERMAL: + + /* Update the notify objects for these types (if present) */ + + AcpiUtUpdateRefCount (Object->CommonNotify.SystemNotify, Action); + AcpiUtUpdateRefCount (Object->CommonNotify.DeviceNotify, Action); + break; + + case ACPI_TYPE_PACKAGE: + /* + * We must update all the sub-objects of the package, + * each of whom may have their own sub-objects. + */ + for (i = 0; i < Object->Package.Count; i++) + { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + Status = AcpiUtCreateUpdateStateAndPush ( + Object->Package.Elements[i], Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + } + break; + + case ACPI_TYPE_BUFFER_FIELD: + + NextObject = Object->BufferField.BufferObj; + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + NextObject = Object->Field.RegionObj; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + NextObject = Object->BankField.BankObj; + Status = AcpiUtCreateUpdateStateAndPush ( + Object->BankField.RegionObj, Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + NextObject = Object->IndexField.IndexObj; + Status = AcpiUtCreateUpdateStateAndPush ( + Object->IndexField.DataObj, Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * The target of an Index (a package, string, or buffer) or a named + * reference must track changes to the ref count of the index or + * target object. + */ + if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || + (Object->Reference.Class== ACPI_REFCLASS_NAME)) + { + NextObject = Object->Reference.Object; + } + break; + + case ACPI_TYPE_REGION: + default: + break; /* No subobjects for all other types */ + } + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + AcpiUtUpdateRefCount (Object, Action); + Object = NULL; + + /* Move on to the next object to be updated */ + + if (NextObject) + { + Object = NextObject; + NextObject = NULL; + } + else if (StateList) + { + State = AcpiUtPopGenericState (&StateList); + Object = State->Update.Object; + AcpiUtDeleteGenericState (State); + } + } + + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not update object reference count")); + + /* Free any stacked Update State objects */ + + while (StateList) + { + State = AcpiUtPopGenericState (&StateList); + AcpiUtDeleteGenericState (State); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAddReference + * + * PARAMETERS: Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void +AcpiUtAddReference ( + ACPI_OPERAND_OBJECT *Object) +{ + + ACPI_FUNCTION_TRACE_PTR (UtAddReference, Object); + + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return_VOID; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Incremented]\n", + Object, Object->Common.ReferenceCount)); + + /* Increment the reference count */ + + (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveReference + * + * PARAMETERS: Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void +AcpiUtRemoveReference ( + ACPI_OPERAND_OBJECT *Object) +{ + + ACPI_FUNCTION_TRACE_PTR (UtRemoveReference, Object); + + + /* + * Allow a NULL pointer to be passed in, just ignore it. This saves + * each caller from having to check. Also, ignore NS nodes. + * + */ + if (!Object || + (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)) + + { + return_VOID; + } + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return_VOID; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Decremented]\n", + Object, Object->Common.ReferenceCount)); + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT); + return_VOID; +} + + diff --git a/source/components/utilities/uteval.c b/source/components/utilities/uteval.c new file mode 100644 index 000000000000..0bcb894b5889 --- /dev/null +++ b/source/components/utilities/uteval.c @@ -0,0 +1,370 @@ +/****************************************************************************** + * + * Module Name: uteval - Object evaluation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTEVAL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("uteval") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtEvaluateObject + * + * PARAMETERS: PrefixNode - Starting node + * Path - Path to object from starting node + * ExpectedReturnTypes - Bitmap of allowed return types + * ReturnDesc - Where a return value is stored + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a namespace object and verifies the type of the + * return object. Common code that simplifies accessing objects + * that have required return objects of fixed types. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtEvaluateObject ( + ACPI_NAMESPACE_NODE *PrefixNode, + char *Path, + UINT32 ExpectedReturnBtypes, + ACPI_OPERAND_OBJECT **ReturnDesc) +{ + ACPI_EVALUATE_INFO *Info; + ACPI_STATUS Status; + UINT32 ReturnBtype; + + + ACPI_FUNCTION_TRACE (UtEvaluateObject); + + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->PrefixNode = PrefixNode; + Info->Pathname = Path; + + /* Evaluate the object/method */ + + Status = AcpiNsEvaluate (Info); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", + AcpiUtGetNodeName (PrefixNode), Path)); + } + else + { + ACPI_ERROR_METHOD ("Method execution failed", + PrefixNode, Path, Status); + } + + goto Cleanup; + } + + /* Did we get a return object? */ + + if (!Info->ReturnObject) + { + if (ExpectedReturnBtypes) + { + ACPI_ERROR_METHOD ("No object was returned from", + PrefixNode, Path, AE_NOT_EXIST); + + Status = AE_NOT_EXIST; + } + + goto Cleanup; + } + + /* Map the return object type to the bitmapped type */ + + switch ((Info->ReturnObject)->Common.Type) + { + case ACPI_TYPE_INTEGER: + ReturnBtype = ACPI_BTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + ReturnBtype = ACPI_BTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + ReturnBtype = ACPI_BTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + ReturnBtype = ACPI_BTYPE_PACKAGE; + break; + + default: + ReturnBtype = 0; + break; + } + + if ((AcpiGbl_EnableInterpreterSlack) && + (!ExpectedReturnBtypes)) + { + /* + * We received a return object, but one was not expected. This can + * happen frequently if the "implicit return" feature is enabled. + * Just delete the return object and return AE_OK. + */ + AcpiUtRemoveReference (Info->ReturnObject); + goto Cleanup; + } + + /* Is the return object one of the expected types? */ + + if (!(ExpectedReturnBtypes & ReturnBtype)) + { + ACPI_ERROR_METHOD ("Return object type is incorrect", + PrefixNode, Path, AE_TYPE); + + ACPI_ERROR ((AE_INFO, + "Type returned from %s was incorrect: %s, expected Btypes: 0x%X", + Path, AcpiUtGetObjectTypeName (Info->ReturnObject), + ExpectedReturnBtypes)); + + /* On error exit, we must delete the return object */ + + AcpiUtRemoveReference (Info->ReturnObject); + Status = AE_TYPE; + goto Cleanup; + } + + /* Object type is OK, return it */ + + *ReturnDesc = Info->ReturnObject; + +Cleanup: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtEvaluateNumericObject + * + * PARAMETERS: ObjectName - Object name to be evaluated + * DeviceNode - Node for the device + * Value - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a numeric namespace object for a selected device + * and stores result in *Value. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtEvaluateNumericObject ( + char *ObjectName, + ACPI_NAMESPACE_NODE *DeviceNode, + UINT64 *Value) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtEvaluateNumericObject); + + + Status = AcpiUtEvaluateObject (DeviceNode, ObjectName, + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the returned Integer */ + + *Value = ObjDesc->Integer.Value; + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_STA + * + * PARAMETERS: DeviceNode - Node for the device + * Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_STA ( + ACPI_NAMESPACE_NODE *DeviceNode, + UINT32 *Flags) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_STA); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA, + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + if (AE_NOT_FOUND == Status) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "_STA on %4.4s was not found, assuming device is present\n", + AcpiUtGetNodeName (DeviceNode))); + + *Flags = ACPI_UINT32_MAX; + Status = AE_OK; + } + + return_ACPI_STATUS (Status); + } + + /* Extract the status flags */ + + *Flags = (UINT32) ObjDesc->Integer.Value; + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecutePowerMethods + * + * PARAMETERS: DeviceNode - Node for the device + * MethodNames - Array of power method names + * MethodCount - Number of methods to execute + * OutValues - Where the power method values are returned + * + * RETURN: Status, OutValues + * + * DESCRIPTION: Executes the specified power methods for the device and returns + * the result(s). + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecutePowerMethods ( + ACPI_NAMESPACE_NODE *DeviceNode, + const char **MethodNames, + UINT8 MethodCount, + UINT8 *OutValues) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_STATUS FinalStatus = AE_NOT_FOUND; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtExecutePowerMethods); + + + for (i = 0; i < MethodCount; i++) + { + /* + * Execute the power method (_SxD or _SxW). The only allowable + * return type is an Integer. + */ + Status = AcpiUtEvaluateObject (DeviceNode, + ACPI_CAST_PTR (char, MethodNames[i]), + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_SUCCESS (Status)) + { + OutValues[i] = (UINT8) ObjDesc->Integer.Value; + + /* Delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + FinalStatus = AE_OK; /* At least one value is valid */ + continue; + } + + OutValues[i] = ACPI_UINT8_MAX; + if (Status == AE_NOT_FOUND) + { + continue; /* Ignore if not found */ + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Failed %s on Device %4.4s, %s\n", + ACPI_CAST_PTR (char, MethodNames[i]), + AcpiUtGetNodeName (DeviceNode), AcpiFormatException (Status))); + } + + return_ACPI_STATUS (FinalStatus); +} diff --git a/source/components/utilities/utglobal.c b/source/components/utilities/utglobal.c new file mode 100644 index 000000000000..faccfb201bb6 --- /dev/null +++ b/source/components/utilities/utglobal.c @@ -0,0 +1,365 @@ +/****************************************************************************** + * + * Module Name: utglobal - Global variables for the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTGLOBAL_C__ +#define DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utglobal") + + +/******************************************************************************* + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ + +/* Debug switch - level and trace mask */ + +#ifdef ACPI_DEBUG_OUTPUT +UINT32 AcpiDbgLevel = ACPI_DEBUG_DEFAULT; +#else +UINT32 AcpiDbgLevel = ACPI_NORMAL_DEFAULT; +#endif + +/* Debug switch - layer (component) mask */ + +UINT32 AcpiDbgLayer = ACPI_COMPONENT_DEFAULT; +UINT32 AcpiGbl_NestingLevel = 0; + +/* Debugger globals */ + +BOOLEAN AcpiGbl_DbTerminateThreads = FALSE; +BOOLEAN AcpiGbl_AbortMethod = FALSE; +BOOLEAN AcpiGbl_MethodExecuting = FALSE; + +/* System flags */ + +UINT32 AcpiGbl_StartupFlags = 0; + +/* System starts uninitialized */ + +BOOLEAN AcpiGbl_Shutdown = TRUE; + +const char *AcpiGbl_SleepStateNames[ACPI_S_STATE_COUNT] = +{ + "\\_S0_", + "\\_S1_", + "\\_S2_", + "\\_S3_", + "\\_S4_", + "\\_S5_" +}; + +const char *AcpiGbl_LowestDstateNames[ACPI_NUM_SxW_METHODS] = +{ + "_S0W", + "_S1W", + "_S2W", + "_S3W", + "_S4W" +}; + +const char *AcpiGbl_HighestDstateNames[ACPI_NUM_SxD_METHODS] = +{ + "_S1D", + "_S2D", + "_S3D", + "_S4D" +}; + + +/******************************************************************************* + * + * Namespace globals + * + ******************************************************************************/ + +/* + * Predefined ACPI Names (Built-in to the Interpreter) + * + * NOTES: + * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run + * during the initialization sequence. + * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to + * perform a Notify() operation on it. 09/2010: Changed to type Device. + * This still allows notifies, but does not confuse host code that + * searches for valid ThermalZone objects. + */ +const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames[] = +{ + {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_SB_", ACPI_TYPE_DEVICE, NULL}, + {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_TZ_", ACPI_TYPE_DEVICE, NULL}, + {"_REV", ACPI_TYPE_INTEGER, (char *) ACPI_CA_SUPPORT_LEVEL}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, (char *) 1}, + +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) + {"_OSI", ACPI_TYPE_METHOD, (char *) 1}, +#endif + + /* Table terminator */ + + {NULL, ACPI_TYPE_ANY, NULL} +}; + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * Event and Hardware globals + * + ******************************************************************************/ + +ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG] = +{ + /* Name Parent Register Register Bit Position Register Bit Mask */ + + /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_TIMER_STATUS, ACPI_BITMASK_TIMER_STATUS}, + /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_BUS_MASTER_STATUS, ACPI_BITMASK_BUS_MASTER_STATUS}, + /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_STATUS}, + /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_STATUS}, + /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS}, + /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS}, + /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS}, + /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS}, + + /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, + /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, + + /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE}, + /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD}, + /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, + /* ACPI_BITREG_SLEEP_TYPE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE, ACPI_BITMASK_SLEEP_TYPE}, + /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE}, + + /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, ACPI_BITPOSITION_ARB_DISABLE, ACPI_BITMASK_ARB_DISABLE} +}; + + +ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS] = +{ + /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, ACPI_BITREG_TIMER_ENABLE, ACPI_BITMASK_TIMER_STATUS, ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, +}; +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitGlobals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init ACPICA globals. All globals that require specific + * initialization should be initialized here! + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitGlobals ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtInitGlobals); + + + /* Create all memory caches */ + + Status = AcpiUtCreateCaches (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Address Range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) + { + AcpiGbl_AddressRangeList[i] = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + AcpiGbl_MutexInfo[i].Mutex = NULL; + AcpiGbl_MutexInfo[i].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + AcpiGbl_MutexInfo[i].UseCount = 0; + } + + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) + { + AcpiGbl_OwnerIdMask[i] = 0; + } + + /* Last OwnerID is never valid */ + + AcpiGbl_OwnerIdMask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + + /* Event counters */ + + AcpiMethodCount = 0; + AcpiSciCount = 0; + AcpiGpeCount = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + AcpiFixedEventCount[i] = 0; + } + +#if (!ACPI_REDUCED_HARDWARE) + + /* GPE support */ + + AcpiGbl_AllGpesInitialized = FALSE; + AcpiGbl_GpeXruptListHead = NULL; + AcpiGbl_GpeFadtBlocks[0] = NULL; + AcpiGbl_GpeFadtBlocks[1] = NULL; + AcpiCurrentGpeCount = 0; + + AcpiGbl_GlobalEventHandler = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Global handlers */ + + AcpiGbl_SystemNotify.Handler = NULL; + AcpiGbl_DeviceNotify.Handler = NULL; + AcpiGbl_ExceptionHandler = NULL; + AcpiGbl_InitHandler = NULL; + AcpiGbl_TableHandler = NULL; + AcpiGbl_InterfaceHandler = NULL; + + /* Global Lock support */ + + AcpiGbl_GlobalLockSemaphore = NULL; + AcpiGbl_GlobalLockMutex = NULL; + AcpiGbl_GlobalLockAcquired = FALSE; + AcpiGbl_GlobalLockHandle = 0; + AcpiGbl_GlobalLockPresent = FALSE; + + /* Miscellaneous variables */ + + AcpiGbl_DSDT = NULL; + AcpiGbl_CmSingleStep = FALSE; + AcpiGbl_DbTerminateThreads = FALSE; + AcpiGbl_Shutdown = FALSE; + AcpiGbl_NsLookupCount = 0; + AcpiGbl_PsFindCount = 0; + AcpiGbl_AcpiHardwarePresent = TRUE; + AcpiGbl_LastOwnerIdIndex = 0; + AcpiGbl_NextOwnerIdOffset = 0; + AcpiGbl_TraceMethodName = 0; + AcpiGbl_TraceDbgLevel = 0; + AcpiGbl_TraceDbgLayer = 0; + AcpiGbl_DebuggerConfiguration = DEBUGGER_THREADING; + AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; + AcpiGbl_OsiData = 0; + AcpiGbl_OsiMutex = NULL; + AcpiGbl_RegMethodsExecuted = FALSE; + + /* Hardware oriented */ + + AcpiGbl_EventsInitialized = FALSE; + AcpiGbl_SystemAwakeAndRunning = TRUE; + + /* Namespace */ + + AcpiGbl_ModuleCodeList = NULL; + AcpiGbl_RootNode = NULL; + AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; + AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; + AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; + AcpiGbl_RootNodeStruct.Parent = NULL; + AcpiGbl_RootNodeStruct.Child = NULL; + AcpiGbl_RootNodeStruct.Peer = NULL; + AcpiGbl_RootNodeStruct.Object = NULL; + + +#ifdef ACPI_DISASSEMBLER + AcpiGbl_ExternalList = NULL; +#endif + +#ifdef ACPI_DEBUG_OUTPUT + AcpiGbl_LowestStackPointer = ACPI_CAST_PTR (ACPI_SIZE, ACPI_SIZE_MAX); +#endif + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiGbl_DisplayFinalMemStats = FALSE; + AcpiGbl_DisableMemTracking = FALSE; +#endif + + return_ACPI_STATUS (AE_OK); +} + +/* Public globals */ + +ACPI_EXPORT_SYMBOL (AcpiGbl_FADT) +ACPI_EXPORT_SYMBOL (AcpiDbgLevel) +ACPI_EXPORT_SYMBOL (AcpiDbgLayer) +ACPI_EXPORT_SYMBOL (AcpiGpeCount) +ACPI_EXPORT_SYMBOL (AcpiCurrentGpeCount) diff --git a/source/components/utilities/utids.c b/source/components/utilities/utids.c new file mode 100644 index 000000000000..226d8c1631b6 --- /dev/null +++ b/source/components/utilities/utids.c @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Module Name: utids - support for device IDs - HID, UID, CID + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTIDS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utids") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_HID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the string HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. The HID is either an 32-bit encoded EISAID + * Integer or a String. A string is always returned. An EISAID + * is converted to a string. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_HID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID *Hid; + UINT32 Length; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_HID); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + Length = ACPI_EISAID_STRING_SIZE; + } + else + { + Length = ObjDesc->String.Length + 1; + } + + /* Allocate a buffer for the HID */ + + Hid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Hid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after DEVICE_ID struct */ + + Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_DEVICE_ID)); + + /* Convert EISAID to a string or simply copy existing string */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value); + } + else + { + ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer); + } + + Hid->Length = Length; + *ReturnId = Hid; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_UID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the string UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the unique + * ID of the device. The UID is either a 64-bit Integer (NOT an + * EISAID) or a string. Always returns a string. A 64-bit integer + * is converted to a decimal string. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_UID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID *Uid; + UINT32 Length; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_UID); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + Length = ACPI_MAX64_DECIMAL_DIGITS + 1; + } + else + { + Length = ObjDesc->String.Length + 1; + } + + /* Allocate a buffer for the UID */ + + Uid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Uid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after DEVICE_ID struct */ + + Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_DEVICE_ID)); + + /* Convert an Integer to string, or just copy an existing string */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value); + } + else + { + ACPI_STRCPY (Uid->String, ObjDesc->String.Pointer); + } + + Uid->Length = Length; + *ReturnId = Uid; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_CID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnCidList - Where the CID list is returned + * + * RETURN: Status, list of CID strings + * + * DESCRIPTION: Executes the _CID control method that returns one or more + * compatible hardware IDs for the device. + * + * NOTE: Internal function, no parameter validation + * + * A _CID method can return either a single compatible ID or a package of + * compatible IDs. Each compatible ID can be one of the following: + * 1) Integer (32 bit compressed EISA ID) or + * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") + * + * The Integer CIDs are converted to string format by this function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_CID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID_LIST **ReturnCidList) +{ + ACPI_OPERAND_OBJECT **CidObjects; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID_LIST *CidList; + char *NextIdString; + UINT32 StringAreaSize; + UINT32 Length; + UINT32 CidListSize; + ACPI_STATUS Status; + UINT32 Count; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtExecute_CID); + + + /* Evaluate the _CID method for this device */ + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, + &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Get the count and size of the returned _CIDs. _CID can return either + * a Package of Integers/Strings or a single Integer or String. + * Note: This section also validates that all CID elements are of the + * correct type (Integer or String). + */ + if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + Count = ObjDesc->Package.Count; + CidObjects = ObjDesc->Package.Elements; + } + else /* Single Integer or String CID */ + { + Count = 1; + CidObjects = &ObjDesc; + } + + StringAreaSize = 0; + for (i = 0; i < Count; i++) + { + /* String lengths include null terminator */ + + switch (CidObjects[i]->Common.Type) + { + case ACPI_TYPE_INTEGER: + StringAreaSize += ACPI_EISAID_STRING_SIZE; + break; + + case ACPI_TYPE_STRING: + StringAreaSize += CidObjects[i]->String.Length + 1; + break; + + default: + Status = AE_TYPE; + goto Cleanup; + } + } + + /* + * Now that we know the length of the CIDs, allocate return buffer: + * 1) Size of the base structure + + * 2) Size of the CID DEVICE_ID array + + * 3) Size of the actual CID strings + */ + CidListSize = sizeof (ACPI_DEVICE_ID_LIST) + + ((Count - 1) * sizeof (ACPI_DEVICE_ID)) + + StringAreaSize; + + CidList = ACPI_ALLOCATE_ZEROED (CidListSize); + if (!CidList) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for CID strings starts after the CID DEVICE_ID array */ + + NextIdString = ACPI_CAST_PTR (char, CidList->Ids) + + ((ACPI_SIZE) Count * sizeof (ACPI_DEVICE_ID)); + + /* Copy/convert the CIDs to the return buffer */ + + for (i = 0; i < Count; i++) + { + if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER) + { + /* Convert the Integer (EISAID) CID to a string */ + + AcpiExEisaIdToString (NextIdString, CidObjects[i]->Integer.Value); + Length = ACPI_EISAID_STRING_SIZE; + } + else /* ACPI_TYPE_STRING */ + { + /* Copy the String CID from the returned object */ + + ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer); + Length = CidObjects[i]->String.Length + 1; + } + + CidList->Ids[i].String = NextIdString; + CidList->Ids[i].Length = Length; + NextIdString += Length; + } + + /* Finish the CID list */ + + CidList->Count = Count; + CidList->ListSize = CidListSize; + *ReturnCidList = CidList; + + +Cleanup: + + /* On exit, we must delete the _CID return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/utilities/utinit.c b/source/components/utilities/utinit.c new file mode 100644 index 000000000000..6831595e686b --- /dev/null +++ b/source/components/utilities/utinit.c @@ -0,0 +1,192 @@ +/****************************************************************************** + * + * Module Name: utinit - Common ACPI subsystem initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTINIT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" +#include "actables.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utinit") + +/* Local prototypes */ + +static void AcpiUtTerminate ( + void); + +#if (!ACPI_REDUCED_HARDWARE) + +static void +AcpiUtFreeGpeLists ( + void); + +#else + +#define AcpiUtFreeGpeLists() +#endif /* !ACPI_REDUCED_HARDWARE */ + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * FUNCTION: AcpiUtFreeGpeLists + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global GPE lists + * + ******************************************************************************/ + +static void +AcpiUtFreeGpeLists ( + void) +{ + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_BLOCK_INFO *NextGpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_XRUPT_INFO *NextGpeXruptInfo; + + + /* Free global GPE blocks and related info structures */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + NextGpeBlock = GpeBlock->Next; + ACPI_FREE (GpeBlock->EventInfo); + ACPI_FREE (GpeBlock->RegisterInfo); + ACPI_FREE (GpeBlock); + + GpeBlock = NextGpeBlock; + } + NextGpeXruptInfo = GpeXruptInfo->Next; + ACPI_FREE (GpeXruptInfo); + GpeXruptInfo = NextGpeXruptInfo; + } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/****************************************************************************** + * + * FUNCTION: AcpiUtTerminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global memory + * + ******************************************************************************/ + +static void +AcpiUtTerminate ( + void) +{ + ACPI_FUNCTION_TRACE (UtTerminate); + + AcpiUtFreeGpeLists (); + AcpiUtDeleteAddressLists (); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtSubsystemShutdown + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Shutdown the various components. Do not delete the mutex + * objects here, because the AML debugger may be still running. + * + ******************************************************************************/ + +void +AcpiUtSubsystemShutdown ( + void) +{ + ACPI_FUNCTION_TRACE (UtSubsystemShutdown); + + +#ifndef ACPI_ASL_COMPILER + + /* Close the AcpiEvent Handling */ + + AcpiEvTerminate (); + + /* Delete any dynamic _OSI interfaces */ + + AcpiUtInterfaceTerminate (); +#endif + + /* Close the Namespace */ + + AcpiNsTerminate (); + + /* Delete the ACPI tables */ + + AcpiTbTerminate (); + + /* Close the globals */ + + AcpiUtTerminate (); + + /* Purge the local caches */ + + (void) AcpiUtDeleteCaches (); + return_VOID; +} + + diff --git a/source/components/utilities/utlock.c b/source/components/utilities/utlock.c new file mode 100644 index 000000000000..61585ad499cd --- /dev/null +++ b/source/components/utilities/utlock.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Module Name: utlock - Reader/Writer lock interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTLOCK_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utlock") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateRwLock + * AcpiUtDeleteRwLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader/writer lock creation and deletion interfaces. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateRwLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Lock->NumReaders = 0; + Status = AcpiOsCreateMutex (&Lock->ReaderMutex); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateMutex (&Lock->WriterMutex); + return (Status); +} + + +void +AcpiUtDeleteRwLock ( + ACPI_RW_LOCK *Lock) +{ + + AcpiOsDeleteMutex (Lock->ReaderMutex); + AcpiOsDeleteMutex (Lock->WriterMutex); + + Lock->NumReaders = 0; + Lock->ReaderMutex = NULL; + Lock->WriterMutex = NULL; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireReadLock + * AcpiUtReleaseReadLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition, + * only the first reader acquires the write mutex. On release, + * only the last reader releases the write mutex. Although this + * algorithm can in theory starve writers, this should not be a + * problem with ACPICA since the subsystem is infrequently used + * in comparison to (for example) an I/O system. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireReadLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Acquire the write lock only for the first reader */ + + Lock->NumReaders++; + if (Lock->NumReaders == 1) + { + Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER); + } + + AcpiOsReleaseMutex (Lock->ReaderMutex); + return (Status); +} + + +ACPI_STATUS +AcpiUtReleaseReadLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Release the write lock only for the very last reader */ + + Lock->NumReaders--; + if (Lock->NumReaders == 0) + { + AcpiOsReleaseMutex (Lock->WriterMutex); + } + + AcpiOsReleaseMutex (Lock->ReaderMutex); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireWriteLock + * AcpiUtReleaseWriteLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or + * release the writer mutex associated with the lock. Acquisition + * of the lock is fully exclusive and will block all readers and + * writers until it is released. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireWriteLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER); + return (Status); +} + + +void +AcpiUtReleaseWriteLock ( + ACPI_RW_LOCK *Lock) +{ + + AcpiOsReleaseMutex (Lock->WriterMutex); +} + diff --git a/source/components/utilities/utmath.c b/source/components/utilities/utmath.c new file mode 100644 index 000000000000..d0fad7cb6cab --- /dev/null +++ b/source/components/utilities/utmath.c @@ -0,0 +1,379 @@ +/******************************************************************************* + * + * Module Name: utmath - Integer math support routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMATH_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmath") + +/* + * Optional support for 64-bit double-precision integer divide. This code + * is configurable and is implemented in order to support 32-bit kernel + * environments where a 64-bit double-precision math library is not available. + * + * Support for a more normal 64-bit divide/modulo (with check for a divide- + * by-zero) appears after this optional section of code. + */ +#ifndef ACPI_USE_NATIVE_DIVIDE + +/* Structures used only for 64-bit divide */ + +typedef struct uint64_struct +{ + UINT32 Lo; + UINT32 Hi; + +} UINT64_STRUCT; + +typedef union uint64_overlay +{ + UINT64 Full; + UINT64_STRUCT Part; + +} UINT64_OVERLAY; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortDivide + * + * PARAMETERS: Dividend - 64-bit dividend + * Divisor - 32-bit divisor + * OutQuotient - Pointer to where the quotient is returned + * OutRemainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) + * divide and modulo. The result is a 64-bit quotient and a + * 32-bit remainder. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortDivide ( + UINT64 Dividend, + UINT32 Divisor, + UINT64 *OutQuotient, + UINT32 *OutRemainder) +{ + UINT64_OVERLAY DividendOvl; + UINT64_OVERLAY Quotient; + UINT32 Remainder32; + + + ACPI_FUNCTION_TRACE (UtShortDivide); + + + /* Always check for a zero divisor */ + + if (Divisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + DividendOvl.Full = Dividend; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor, + Quotient.Part.Hi, Remainder32); + ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor, + Quotient.Part.Lo, Remainder32); + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = Quotient.Full; + } + if (OutRemainder) + { + *OutRemainder = Remainder32; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDivide + * + * PARAMETERS: InDividend - Dividend + * InDivisor - Divisor + * OutQuotient - Pointer to where the quotient is returned + * OutRemainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a divide and modulo. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtDivide ( + UINT64 InDividend, + UINT64 InDivisor, + UINT64 *OutQuotient, + UINT64 *OutRemainder) +{ + UINT64_OVERLAY Dividend; + UINT64_OVERLAY Divisor; + UINT64_OVERLAY Quotient; + UINT64_OVERLAY Remainder; + UINT64_OVERLAY NormalizedDividend; + UINT64_OVERLAY NormalizedDivisor; + UINT32 Partial1; + UINT64_OVERLAY Partial2; + UINT64_OVERLAY Partial3; + + + ACPI_FUNCTION_TRACE (UtDivide); + + + /* Always check for a zero divisor */ + + if (InDivisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + Divisor.Full = InDivisor; + Dividend.Full = InDividend; + if (Divisor.Part.Hi == 0) + { + /* + * 1) Simplest case is where the divisor is 32 bits, we can + * just do two divides + */ + Remainder.Part.Hi = 0; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo, + Quotient.Part.Hi, Partial1); + ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo, + Quotient.Part.Lo, Remainder.Part.Lo); + } + + else + { + /* + * 2) The general case where the divisor is a full 64 bits + * is more difficult + */ + Quotient.Part.Hi = 0; + NormalizedDividend = Dividend; + NormalizedDivisor = Divisor; + + /* Normalize the operands (shift until the divisor is < 32 bits) */ + + do + { + ACPI_SHIFT_RIGHT_64 (NormalizedDivisor.Part.Hi, + NormalizedDivisor.Part.Lo); + ACPI_SHIFT_RIGHT_64 (NormalizedDividend.Part.Hi, + NormalizedDividend.Part.Lo); + + } while (NormalizedDivisor.Part.Hi != 0); + + /* Partial divide */ + + ACPI_DIV_64_BY_32 (NormalizedDividend.Part.Hi, + NormalizedDividend.Part.Lo, + NormalizedDivisor.Part.Lo, + Quotient.Part.Lo, Partial1); + + /* + * The quotient is always 32 bits, and simply requires adjustment. + * The 64-bit remainder must be generated. + */ + Partial1 = Quotient.Part.Lo * Divisor.Part.Hi; + Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo; + Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1; + + Remainder.Part.Hi = Partial3.Part.Lo; + Remainder.Part.Lo = Partial2.Part.Lo; + + if (Partial3.Part.Hi == 0) + { + if (Partial3.Part.Lo >= Dividend.Part.Hi) + { + if (Partial3.Part.Lo == Dividend.Part.Hi) + { + if (Partial2.Part.Lo > Dividend.Part.Lo) + { + Quotient.Part.Lo--; + Remainder.Full -= Divisor.Full; + } + } + else + { + Quotient.Part.Lo--; + Remainder.Full -= Divisor.Full; + } + } + + Remainder.Full = Remainder.Full - Dividend.Full; + Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi); + Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo); + + if (Remainder.Part.Lo) + { + Remainder.Part.Hi--; + } + } + } + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = Quotient.Full; + } + if (OutRemainder) + { + *OutRemainder = Remainder.Full; + } + + return_ACPI_STATUS (AE_OK); +} + +#else + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortDivide, AcpiUtDivide + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native versions of the UtDivide functions. Use these if either + * 1) The target is a 64-bit platform and therefore 64-bit + * integer math is supported directly by the machine. + * 2) The target is a 32-bit or 16-bit platform, and the + * double-precision integer math library is available to + * perform the divide. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortDivide ( + UINT64 InDividend, + UINT32 Divisor, + UINT64 *OutQuotient, + UINT32 *OutRemainder) +{ + + ACPI_FUNCTION_TRACE (UtShortDivide); + + + /* Always check for a zero divisor */ + + if (Divisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = InDividend / Divisor; + } + if (OutRemainder) + { + *OutRemainder = (UINT32) (InDividend % Divisor); + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_STATUS +AcpiUtDivide ( + UINT64 InDividend, + UINT64 InDivisor, + UINT64 *OutQuotient, + UINT64 *OutRemainder) +{ + ACPI_FUNCTION_TRACE (UtDivide); + + + /* Always check for a zero divisor */ + + if (InDivisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = InDividend / InDivisor; + } + if (OutRemainder) + { + *OutRemainder = InDividend % InDivisor; + } + + return_ACPI_STATUS (AE_OK); +} + +#endif + + diff --git a/source/components/utilities/utmisc.c b/source/components/utilities/utmisc.c new file mode 100644 index 000000000000..062c768e72a0 --- /dev/null +++ b/source/components/utilities/utmisc.c @@ -0,0 +1,1299 @@ +/******************************************************************************* + * + * Module Name: utmisc - common utility procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMISC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmisc") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. NULL if exception is + * not valid. + * + * DESCRIPTION: This function validates and translates an ACPI exception into + * an ASCII string. + * + ******************************************************************************/ + +const char * +AcpiUtValidateException ( + ACPI_STATUS Status) +{ + UINT32 SubStatus; + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Status is composed of two parts, a "type" and an actual code + */ + SubStatus = (Status & ~AE_CODE_MASK); + + switch (Status & AE_CODE_MASK) + { + case AE_CODE_ENVIRONMENTAL: + + if (SubStatus <= AE_CODE_ENV_MAX) + { + Exception = AcpiGbl_ExceptionNames_Env [SubStatus]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (SubStatus <= AE_CODE_PGM_MAX) + { + Exception = AcpiGbl_ExceptionNames_Pgm [SubStatus]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (SubStatus <= AE_CODE_TBL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Tbl [SubStatus]; + } + break; + + case AE_CODE_AML: + + if (SubStatus <= AE_CODE_AML_MAX) + { + Exception = AcpiGbl_ExceptionNames_Aml [SubStatus]; + } + break; + + case AE_CODE_CONTROL: + + if (SubStatus <= AE_CODE_CTRL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Ctrl [SubStatus]; + } + break; + + default: + break; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtIsPciRootBridge + * + * PARAMETERS: Id - The HID/CID in string format + * + * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtIsPciRootBridge ( + char *Id) +{ + + /* + * Check if this is a PCI root bridge. + * ACPI 3.0+: check for a PCI Express root also. + */ + if (!(ACPI_STRCMP (Id, + PCI_ROOT_HID_STRING)) || + + !(ACPI_STRCMP (Id, + PCI_EXPRESS_ROOT_HID_STRING))) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtIsAmlTable + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: TRUE if table contains executable AML; FALSE otherwise + * + * DESCRIPTION: Check ACPI Signature for a table that contains AML code. + * Currently, these are DSDT,SSDT,PSDT. All other table types are + * data tables that do not contain AML code. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtIsAmlTable ( + ACPI_TABLE_HEADER *Table) +{ + + /* These are the only tables that contain executable AML */ + + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_PSDT) || + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT)) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateOwnerId + * + * PARAMETERS: OwnerId - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAllocateOwnerId ( + ACPI_OWNER_ID *OwnerId) +{ + UINT32 i; + UINT32 j; + UINT32 k; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtAllocateOwnerId); + + + /* Guard against multiple allocations of ID to the same location */ + + if (*OwnerId) + { + ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId)); + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = AcpiGbl_LastOwnerIdIndex; + i < (ACPI_NUM_OWNERID_MASKS + 1); + i++, j++) + { + if (j >= ACPI_NUM_OWNERID_MASKS) + { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++) + { + if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX) + { + /* There are no free IDs in this mask */ + + break; + } + + if (!(AcpiGbl_OwnerIdMask[j] & (1 << k))) + { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + AcpiGbl_OwnerIdMask[j] |= (1 << k); + + AcpiGbl_LastOwnerIdIndex = (UINT8) j; + AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j)); + + ACPI_DEBUG_PRINT ((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId)); + goto Exit; + } + } + + AcpiGbl_NextOwnerIdOffset = 0; + } + + /* + * All OwnerIds have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + Status = AE_OWNER_ID_LIMIT; + ACPI_ERROR ((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + +Exit: + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtReleaseOwnerId + * + * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void +AcpiUtReleaseOwnerId ( + ACPI_OWNER_ID *OwnerIdPtr) +{ + ACPI_OWNER_ID OwnerId = *OwnerIdPtr; + ACPI_STATUS Status; + UINT32 Index; + UINT32 Bit; + + + ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId); + + + /* Always clear the input OwnerId (zero is an invalid ID) */ + + *OwnerIdPtr = 0; + + /* Zero is not a valid OwnerID */ + + if (OwnerId == 0) + { + ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* Normalize the ID to zero */ + + OwnerId--; + + /* Decode ID to index/offset pair */ + + Index = ACPI_DIV_32 (OwnerId); + Bit = 1 << ACPI_MOD_32 (OwnerId); + + /* Free the owner ID only if it is valid */ + + if (AcpiGbl_OwnerIdMask[Index] & Bit) + { + AcpiGbl_OwnerIdMask[Index] ^= Bit; + } + else + { + ACPI_ERROR ((AE_INFO, + "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrupr (strupr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void +AcpiUtStrupr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) ACPI_TOUPPER (*String); + } + + return; +} + + +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlwr (strlwr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to lowercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void +AcpiUtStrlwr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) ACPI_TOLOWER (*String); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiUtStricmp + * + * PARAMETERS: String1 - first string to compare + * String2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int +AcpiUtStricmp ( + char *String1, + char *String2) +{ + int c1; + int c2; + + + do + { + c1 = tolower ((int) *String1); + c2 = tolower ((int) *String2); + + String1++; + String2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPrintString + * + * PARAMETERS: String - Null terminated ASCII string + * MaxLength - Maximum output length + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void +AcpiUtPrintString ( + char *String, + UINT8 MaxLength) +{ + UINT32 i; + + + if (!String) + { + AcpiOsPrintf ("<\"NULL STRING PTR\">"); + return; + } + + AcpiOsPrintf ("\""); + for (i = 0; String[i] && (i < MaxLength); i++) + { + /* Escape sequences */ + + switch (String[i]) + { + case 0x07: + AcpiOsPrintf ("\\a"); /* BELL */ + break; + + case 0x08: + AcpiOsPrintf ("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + AcpiOsPrintf ("\\f"); /* FORMFEED */ + break; + + case 0x0A: + AcpiOsPrintf ("\\n"); /* LINEFEED */ + break; + + case 0x0D: + AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/ + break; + + case 0x09: + AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + AcpiOsPrintf ("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + AcpiOsPrintf ("\\%c", (int) String[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT (String[i])) + { + /* This is a normal character */ + + AcpiOsPrintf ("%c", (int) String[i]); + } + else + { + /* All others will be Hex escapes */ + + AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]); + } + break; + } + } + AcpiOsPrintf ("\""); + + if (i == MaxLength && String[i]) + { + AcpiOsPrintf ("..."); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDwordByteSwap + * + * PARAMETERS: Value - Value to be converted + * + * RETURN: UINT32 integer with bytes swapped + * + * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +UINT32 +AcpiUtDwordByteSwap ( + UINT32 Value) +{ + union + { + UINT32 Value; + UINT8 Bytes[4]; + } Out; + union + { + UINT32 Value; + UINT8 Bytes[4]; + } In; + + + ACPI_FUNCTION_ENTRY (); + + + In.Value = Value; + + Out.Bytes[0] = In.Bytes[3]; + Out.Bytes[1] = In.Bytes[2]; + Out.Bytes[2] = In.Bytes[1]; + Out.Bytes[3] = In.Bytes[0]; + + return (Out.Value); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtSetIntegerWidth + * + * PARAMETERS: Revision From DSDT header + * + * RETURN: None + * + * DESCRIPTION: Set the global integer bit width based upon the revision + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this + * makes a difference. + * + ******************************************************************************/ + +void +AcpiUtSetIntegerWidth ( + UINT8 Revision) +{ + + if (Revision < 2) + { + /* 32-bit case */ + + AcpiGbl_IntegerBitWidth = 32; + AcpiGbl_IntegerNybbleWidth = 8; + AcpiGbl_IntegerByteWidth = 4; + } + else + { + /* 64-bit case (ACPI 2.0+) */ + + AcpiGbl_IntegerBitWidth = 64; + AcpiGbl_IntegerNybbleWidth = 16; + AcpiGbl_IntegerByteWidth = 8; + } +} + + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: AcpiUtDisplayInitPathname + * + * PARAMETERS: Type - Object type of the node + * ObjHandle - Handle whose pathname will be displayed + * Path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +AcpiUtDisplayInitPathname ( + UINT8 Type, + ACPI_NAMESPACE_NODE *ObjHandle, + char *Path) +{ + ACPI_STATUS Status; + ACPI_BUFFER Buffer; + + + ACPI_FUNCTION_ENTRY (); + + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) + { + return; + } + + /* Get the full pathname to the node */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Print what we're doing */ + + switch (Type) + { + case ACPI_TYPE_METHOD: + AcpiOsPrintf ("Executing "); + break; + + default: + AcpiOsPrintf ("Initializing "); + break; + } + + /* Print the object type and pathname */ + + AcpiOsPrintf ("%-12s %s", + AcpiUtGetTypeName (Type), (char *) Buffer.Pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (Path) + { + AcpiOsPrintf (".%s", Path); + } + AcpiOsPrintf ("\n"); + + ACPI_FREE (Buffer.Pointer); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidAcpiChar + * + * PARAMETERS: Char - The character to be examined + * Position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidAcpiChar ( + char Character, + UINT32 Position) +{ + + if (!((Character >= 'A' && Character <= 'Z') || + (Character >= '0' && Character <= '9') || + (Character == '_'))) + { + /* Allow a '!' in the last position */ + + if (Character == '!' && Position == 3) + { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidAcpiName + * + * PARAMETERS: Name - The name to be examined + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidAcpiName ( + UINT32 Name) +{ + UINT32 i; + + + ACPI_FUNCTION_ENTRY (); + + + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i)) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRepairName + * + * PARAMETERS: Name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. NOTE: the Name parameter must reside in + * read/write memory, cannot be a const. + * + * An ACPI Name must consist of valid ACPI characters. We will repair the name + * if necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + * + ******************************************************************************/ + +void +AcpiUtRepairName ( + char *Name) +{ + UINT32 i; + BOOLEAN FoundBadChar = FALSE; + + + ACPI_FUNCTION_NAME (UtRepairName); + + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (AcpiUtValidAcpiChar (Name[i], i)) + { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + Name[i] = '*'; + FoundBadChar = TRUE; + } + + if (FoundBadChar) + { + /* Report warning only if in strict mode or debug mode */ + + if (!AcpiGbl_EnableInterpreterSlack) + { + ACPI_WARNING ((AE_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", Name)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", Name)); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul64 + * + * PARAMETERS: String - Null terminated string + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of ToInteger' + * RetInteger - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger) +{ + UINT32 ThisDigit = 0; + UINT64 ReturnValue = 0; + UINT64 Quotient; + UINT64 Dividend; + UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE); + UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4); + UINT8 ValidDigits = 0; + UINT8 SignOf0x = 0; + UINT8 Term = 0; + + + ACPI_FUNCTION_TRACE_STR (UtStroul64, String); + + + switch (Base) + { + case ACPI_ANY_BASE: + case 16: + break; + + default: + /* Invalid Base */ + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!String) + { + goto ErrorExit; + } + + /* Skip over any white space in the buffer */ + + while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t')) + { + String++; + } + + if (ToIntegerOp) + { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x')) + { + SignOf0x = 1; + Base = 16; + + /* Skip over the leading '0x' */ + String += 2; + } + else + { + Base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t') + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + goto AllDone; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*String) + { + if (ACPI_IS_DIGIT (*String)) + { + /* Convert ASCII 0-9 to Decimal value */ + + ThisDigit = ((UINT8) *String) - '0'; + } + else if (Base == 10) + { + /* Digit is out of range; possible in ToInteger case only */ + + Term = 1; + } + else + { + ThisDigit = (UINT8) ACPI_TOUPPER (*String); + if (ACPI_IS_XDIGIT ((char) ThisDigit)) + { + /* Convert ASCII Hex char to value */ + + ThisDigit = ThisDigit - 'A' + 10; + } + else + { + Term = 1; + } + } + + if (Term) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x) + { + /* Skip zeros */ + String++; + continue; + } + + ValidDigits++; + + if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32))) + { + /* + * This is ToInteger operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto ErrorExit; + } + + /* Divide the digit into the correct position */ + + (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit), + Base, &Quotient, NULL); + + if (ReturnValue > Quotient) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + + ReturnValue *= Base; + ReturnValue += ThisDigit; + String++; + } + + /* All done, normal exit */ + +AllDone: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ReturnValue))); + + *RetInteger = ReturnValue; + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + /* Base was set/validated above */ + + if (Base == 10) + { + return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); + } + else + { + return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateUpdateStateAndPush + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * StateList - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateUpdateStateAndPush ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action, + ACPI_GENERIC_STATE **StateList) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + /* Ignore null objects; these are expected */ + + if (!Object) + { + return (AE_OK); + } + + State = AcpiUtCreateUpdateState (Object, Action); + if (!State) + { + return (AE_NO_MEMORY); + } + + AcpiUtPushGenericState (StateList, State); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtWalkPackageTree + * + * PARAMETERS: SourceObject - The package to walk + * TargetObject - Target object (if package is being copied) + * WalkCallback - Called once for each package element + * Context - Passed to the callback function + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtWalkPackageTree ( + ACPI_OPERAND_OBJECT *SourceObject, + void *TargetObject, + ACPI_PKG_CALLBACK WalkCallback, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *StateList = NULL; + ACPI_GENERIC_STATE *State; + UINT32 ThisIndex; + ACPI_OPERAND_OBJECT *ThisSourceObj; + + + ACPI_FUNCTION_TRACE (UtWalkPackageTree); + + + State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0); + if (!State) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + while (State) + { + /* Get one element of the package */ + + ThisIndex = State->Pkg.Index; + ThisSourceObj = (ACPI_OPERAND_OBJECT *) + State->Pkg.SourceObject->Package.Elements[ThisIndex]; + + /* + * Check for: + * 1) An uninitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Not an internal object - can be a namespace node instead + * 3) Any type other than a package. Packages are handled in else + * case below. + */ + if ((!ThisSourceObj) || + (ACPI_GET_DESCRIPTOR_TYPE (ThisSourceObj) != ACPI_DESC_TYPE_OPERAND) || + (ThisSourceObj->Common.Type != ACPI_TYPE_PACKAGE)) + { + Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj, + State, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + State->Pkg.Index++; + while (State->Pkg.Index >= State->Pkg.SourceObject->Package.Count) + { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself. + * + * Delete this state and pop the previous state (package). + */ + AcpiUtDeleteGenericState (State); + State = AcpiUtPopGenericState (&StateList); + + /* Finished when there are no more states */ + + if (!State) + { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return_ACPI_STATUS (AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + State->Pkg.Index++; + } + } + else + { + /* This is a subobject of type package */ + + Status = WalkCallback (ACPI_COPY_TYPE_PACKAGE, ThisSourceObj, + State, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Push the current state and create a new one + * The callback above returned a new target package object. + */ + AcpiUtPushGenericState (&StateList, State); + State = AcpiUtCreatePkgState (ThisSourceObj, + State->Pkg.ThisTargetObj, 0); + if (!State) + { + /* Free any stacked Update State objects */ + + while (StateList) + { + State = AcpiUtPopGenericState (&StateList); + AcpiUtDeleteGenericState (State); + } + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + } + + /* We should never get here */ + + return_ACPI_STATUS (AE_AML_INTERNAL); +} + + diff --git a/source/components/utilities/utmutex.c b/source/components/utilities/utmutex.c new file mode 100644 index 000000000000..f1cdb0180442 --- /dev/null +++ b/source/components/utilities/utmutex.c @@ -0,0 +1,397 @@ +/******************************************************************************* + * + * Module Name: utmutex - local mutex support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMUTEX_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmutex") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtCreateMutex ( + ACPI_MUTEX_HANDLE MutexId); + +static void +AcpiUtDeleteMutex ( + ACPI_MUTEX_HANDLE MutexId); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMutexInitialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtMutexInitialize ( + void) +{ + UINT32 i; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtMutexInitialize); + + + /* Create each of the predefined mutex objects */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + Status = AcpiUtCreateMutex (i); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Create the spinlocks for use at interrupt level */ + + Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Mutex for _OSI support */ + Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create the reader/writer lock for namespace access */ + + Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMutexTerminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. + * + ******************************************************************************/ + +void +AcpiUtMutexTerminate ( + void) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtMutexTerminate); + + + /* Delete each predefined mutex object */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + AcpiUtDeleteMutex (i); + } + + AcpiOsDeleteMutex (AcpiGbl_OsiMutex); + + /* Delete the spinlocks */ + + AcpiOsDeleteLock (AcpiGbl_GpeLock); + AcpiOsDeleteLock (AcpiGbl_HardwareLock); + + /* Delete the reader/writer lock */ + + AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateMutex + * + * PARAMETERS: MutexID - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCreateMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); + + + if (!AcpiGbl_MutexInfo[MutexId].Mutex) + { + Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + AcpiGbl_MutexInfo[MutexId].UseCount = 0; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteMutex + * + * PARAMETERS: MutexID - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +static void +AcpiUtDeleteMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + + ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); + + + AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); + + AcpiGbl_MutexInfo[MutexId].Mutex = NULL; + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireMutex + * + * PARAMETERS: MutexID - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_STATUS Status; + ACPI_THREAD_ID ThisThreadId; + + + ACPI_FUNCTION_NAME (UtAcquireMutex); + + + if (MutexId > ACPI_MAX_MUTEX) + { + return (AE_BAD_PARAMETER); + } + + ThisThreadId = AcpiOsGetThreadId (); + +#ifdef ACPI_MUTEX_DEBUG + { + UINT32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = MutexId; i < ACPI_NUM_MUTEX; i++) + { + if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) + { + if (i == MutexId) + { + ACPI_ERROR ((AE_INFO, + "Mutex [%s] already acquired by this thread [%u]", + AcpiUtGetMutexName (MutexId), + (UINT32) ThisThreadId)); + + return (AE_ALREADY_ACQUIRED); + } + + ACPI_ERROR ((AE_INFO, + "Invalid acquire order: Thread %u owns [%s], wants [%s]", + (UINT32) ThisThreadId, AcpiUtGetMutexName (i), + AcpiUtGetMutexName (MutexId))); + + return (AE_ACQUIRE_DEADLOCK); + } + } + } +#endif + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, + "Thread %u attempting to acquire Mutex [%s]\n", + (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); + + Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, + ACPI_WAIT_FOREVER); + if (ACPI_SUCCESS (Status)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", + (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); + + AcpiGbl_MutexInfo[MutexId].UseCount++; + AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; + } + else + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Thread %u could not acquire Mutex [0x%X]", + (UINT32) ThisThreadId, MutexId)); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtReleaseMutex + * + * PARAMETERS: MutexID - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtReleaseMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_FUNCTION_NAME (UtReleaseMutex); + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", + (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); + + if (MutexId > ACPI_MAX_MUTEX) + { + return (AE_BAD_PARAMETER); + } + + /* + * Mutex must be acquired in order to release it! + */ + if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) + { + ACPI_ERROR ((AE_INFO, + "Mutex [0x%X] is not acquired, cannot release", MutexId)); + + return (AE_NOT_ACQUIRED); + } + +#ifdef ACPI_MUTEX_DEBUG + { + UINT32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = MutexId; i < ACPI_NUM_MUTEX; i++) + { + if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) + { + if (i == MutexId) + { + continue; + } + + ACPI_ERROR ((AE_INFO, + "Invalid release order: owns [%s], releasing [%s]", + AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); + + return (AE_RELEASE_DEADLOCK); + } + } + } +#endif + + /* Mark unlocked FIRST */ + + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + + AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); + return (AE_OK); +} + + diff --git a/source/components/utilities/utobject.c b/source/components/utilities/utobject.c new file mode 100644 index 000000000000..fea140946c2c --- /dev/null +++ b/source/components/utilities/utobject.c @@ -0,0 +1,787 @@ +/****************************************************************************** + * + * Module Name: utobject - ACPI object create/delete/size/cache routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTOBJECT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utobject") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtGetSimpleObjectSize ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_SIZE *ObjLength); + +static ACPI_STATUS +AcpiUtGetPackageObjectSize ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_SIZE *ObjLength); + +static ACPI_STATUS +AcpiUtGetElementLength ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateInternalObjectDbg + * + * PARAMETERS: ModuleName - Source file name of caller + * LineNumber - Line number of caller + * ComponentId - Component type of caller + * Type - ACPI Type of the new object + * + * RETURN: A new internal object, null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: We always allocate the worst-case object descriptor because + * these objects are cached, and we want them to be + * one-size-satisifies-any-request. This in itself may not be + * the most memory efficient, but the efficiency of the object + * cache should more than make up for this! + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateInternalObjectDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId, + ACPI_OBJECT_TYPE Type) +{ + ACPI_OPERAND_OBJECT *Object; + ACPI_OPERAND_OBJECT *SecondObject; + + + ACPI_FUNCTION_TRACE_STR (UtCreateInternalObjectDbg, + AcpiUtGetTypeName (Type)); + + + /* Allocate the raw object descriptor */ + + Object = AcpiUtAllocateObjectDescDbg (ModuleName, LineNumber, ComponentId); + if (!Object) + { + return_PTR (NULL); + } + + switch (Type) + { + case ACPI_TYPE_REGION: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* These types require a secondary object */ + + SecondObject = AcpiUtAllocateObjectDescDbg (ModuleName, + LineNumber, ComponentId); + if (!SecondObject) + { + AcpiUtDeleteObjectDesc (Object); + return_PTR (NULL); + } + + SecondObject->Common.Type = ACPI_TYPE_LOCAL_EXTRA; + SecondObject->Common.ReferenceCount = 1; + + /* Link the second object to the first */ + + Object->Common.NextObject = SecondObject; + break; + + default: + /* All others have no secondary object */ + break; + } + + /* Save the object type in the object descriptor */ + + Object->Common.Type = (UINT8) Type; + + /* Init the reference count */ + + Object->Common.ReferenceCount = 1; + + /* Any per-type initialization should go here */ + + return_PTR (Object); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePackageObject + * + * PARAMETERS: Count - Number of package elements + * + * RETURN: Pointer to a new Package object, null on failure + * + * DESCRIPTION: Create a fully initialized package object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreatePackageObject ( + UINT32 Count) +{ + ACPI_OPERAND_OBJECT *PackageDesc; + ACPI_OPERAND_OBJECT **PackageElements; + + + ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count); + + + /* Create a new Package object */ + + PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); + if (!PackageDesc) + { + return_PTR (NULL); + } + + /* + * Create the element array. Count+1 allows the array to be null + * terminated. + */ + PackageElements = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) Count + 1) * sizeof (void *)); + if (!PackageElements) + { + ACPI_FREE (PackageDesc); + return_PTR (NULL); + } + + PackageDesc->Package.Count = Count; + PackageDesc->Package.Elements = PackageElements; + return_PTR (PackageDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateIntegerObject + * + * PARAMETERS: InitialValue - Initial value for the integer + * + * RETURN: Pointer to a new Integer object, null on failure + * + * DESCRIPTION: Create an initialized integer object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateIntegerObject ( + UINT64 InitialValue) +{ + ACPI_OPERAND_OBJECT *IntegerDesc; + + + ACPI_FUNCTION_TRACE (UtCreateIntegerObject); + + + /* Create and initialize a new integer object */ + + IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!IntegerDesc) + { + return_PTR (NULL); + } + + IntegerDesc->Integer.Value = InitialValue; + return_PTR (IntegerDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateBufferObject + * + * PARAMETERS: BufferSize - Size of buffer to be created + * + * RETURN: Pointer to a new Buffer object, null on failure + * + * DESCRIPTION: Create a fully initialized buffer object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateBufferObject ( + ACPI_SIZE BufferSize) +{ + ACPI_OPERAND_OBJECT *BufferDesc; + UINT8 *Buffer = NULL; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize); + + + /* Create a new Buffer object */ + + BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); + if (!BufferDesc) + { + return_PTR (NULL); + } + + /* Create an actual buffer only if size > 0 */ + + if (BufferSize > 0) + { + /* Allocate the actual buffer */ + + Buffer = ACPI_ALLOCATE_ZEROED (BufferSize); + if (!Buffer) + { + ACPI_ERROR ((AE_INFO, "Could not allocate size %u", + (UINT32) BufferSize)); + AcpiUtRemoveReference (BufferDesc); + return_PTR (NULL); + } + } + + /* Complete buffer object initialization */ + + BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; + BufferDesc->Buffer.Pointer = Buffer; + BufferDesc->Buffer.Length = (UINT32) BufferSize; + + /* Return the new buffer descriptor */ + + return_PTR (BufferDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateStringObject + * + * PARAMETERS: StringSize - Size of string to be created. Does not + * include NULL terminator, this is added + * automatically. + * + * RETURN: Pointer to a new String object + * + * DESCRIPTION: Create a fully initialized string object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateStringObject ( + ACPI_SIZE StringSize) +{ + ACPI_OPERAND_OBJECT *StringDesc; + char *String; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize); + + + /* Create a new String object */ + + StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); + if (!StringDesc) + { + return_PTR (NULL); + } + + /* + * Allocate the actual string buffer -- (Size + 1) for NULL terminator. + * NOTE: Zero-length strings are NULL terminated + */ + String = ACPI_ALLOCATE_ZEROED (StringSize + 1); + if (!String) + { + ACPI_ERROR ((AE_INFO, "Could not allocate size %u", + (UINT32) StringSize)); + AcpiUtRemoveReference (StringDesc); + return_PTR (NULL); + } + + /* Complete string object initialization */ + + StringDesc->String.Pointer = String; + StringDesc->String.Length = (UINT32) StringSize; + + /* Return the new string descriptor */ + + return_PTR (StringDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidInternalObject + * + * PARAMETERS: Object - Object to be validated + * + * RETURN: TRUE if object is valid, FALSE otherwise + * + * DESCRIPTION: Validate a pointer to be an ACPI_OPERAND_OBJECT + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidInternalObject ( + void *Object) +{ + + ACPI_FUNCTION_NAME (UtValidInternalObject); + + + /* Check for a null pointer */ + + if (!Object) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Null Object Ptr\n")); + return (FALSE); + } + + /* Check the descriptor type field */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (Object)) + { + case ACPI_DESC_TYPE_OPERAND: + + /* The object appears to be a valid ACPI_OPERAND_OBJECT */ + + return (TRUE); + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%p is not not an ACPI operand obj [%s]\n", + Object, AcpiUtGetDescriptorName (Object))); + break; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateObjectDescDbg + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * ComponentId - Caller's component ID (for error output) + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ******************************************************************************/ + +void * +AcpiUtAllocateObjectDescDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId) +{ + ACPI_OPERAND_OBJECT *Object; + + + ACPI_FUNCTION_TRACE (UtAllocateObjectDescDbg); + + + Object = AcpiOsAcquireObject (AcpiGbl_OperandCache); + if (!Object) + { + ACPI_ERROR ((ModuleName, LineNumber, + "Could not allocate an object descriptor")); + + return_PTR (NULL); + } + + /* Mark the descriptor type */ + + ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_OPERAND); + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n", + Object, (UINT32) sizeof (ACPI_OPERAND_OBJECT))); + + return_PTR (Object); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteObjectDesc + * + * PARAMETERS: Object - An Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ******************************************************************************/ + +void +AcpiUtDeleteObjectDesc ( + ACPI_OPERAND_OBJECT *Object) +{ + ACPI_FUNCTION_TRACE_PTR (UtDeleteObjectDesc, Object); + + + /* Object must be an ACPI_OPERAND_OBJECT */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) + { + ACPI_ERROR ((AE_INFO, + "%p is not an ACPI Operand object [%s]", Object, + AcpiUtGetDescriptorName (Object))); + return_VOID; + } + + (void) AcpiOsReleaseObject (AcpiGbl_OperandCache, Object); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetSimpleObjectSize + * + * PARAMETERS: InternalObject - An ACPI operand object + * ObjLength - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an external user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetSimpleObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_SIZE Length; + ACPI_SIZE Size; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (UtGetSimpleObjectSize, InternalObject); + + + /* Start with the length of the (external) Acpi object */ + + Length = sizeof (ACPI_OBJECT); + + /* A NULL object is allowed, can be a legal uninitialized package element */ + + if (!InternalObject) + { + /* + * Object is NULL, just return the length of ACPI_OBJECT + * (A NULL ACPI_OBJECT is an object of all zeroes.) + */ + *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); + return_ACPI_STATUS (AE_OK); + } + + /* A Namespace Node should never appear here */ + + if (ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_NAMED) + { + /* A namespace node should never get here */ + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems on + * certain processors + */ + switch (InternalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + Length += (ACPI_SIZE) InternalObject->String.Length + 1; + break; + + + case ACPI_TYPE_BUFFER: + + Length += (ACPI_SIZE) InternalObject->Buffer.Length; + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* No extra data for these types */ + + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (InternalObject->Reference.Class) + { + case ACPI_REFCLASS_NAME: + + /* + * Get the actual length of the full pathname to this object. + * The reference will be converted to the pathname to the object + */ + Size = AcpiNsGetPathnameLength (InternalObject->Reference.Node); + if (!Size) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Length += ACPI_ROUND_UP_TO_NATIVE_WORD (Size); + break; + + default: + + /* + * No other reference opcodes are supported. + * Notably, Locals and Args are not supported, but this may be + * required eventually. + */ + ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " + "unsupported Reference Class [%s] 0x%X in object %p", + AcpiUtGetReferenceName (InternalObject), + InternalObject->Reference.Class, InternalObject)); + Status = AE_TYPE; + break; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " + "unsupported type [%s] 0x%X in object %p", + AcpiUtGetObjectTypeName (InternalObject), + InternalObject->Common.Type, InternalObject)); + Status = AE_TYPE; + break; + } + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetElementLength + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Get the length of one package element. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetElementLength ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; + ACPI_SIZE ObjectSpace; + + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * Simple object - just get the size (Null object/entry is handled + * here also) and sum it into the running package length + */ + Status = AcpiUtGetSimpleObjectSize (SourceObject, &ObjectSpace); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Info->Length += ObjectSpace; + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* Package object - nothing much to do here, let the walk handle it */ + + Info->NumPackages++; + State->Pkg.ThisTargetObj = NULL; + break; + + + default: + + /* No other types allowed */ + + return (AE_BAD_PARAMETER); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetPackageObjectSize + * + * PARAMETERS: InternalObject - An ACPI internal object + * ObjLength - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a package object for return to an external user. + * + * This is moderately complex since a package contains other + * objects including packages. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetPackageObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_STATUS Status; + ACPI_PKG_INFO Info; + + + ACPI_FUNCTION_TRACE_PTR (UtGetPackageObjectSize, InternalObject); + + + Info.Length = 0; + Info.ObjectSpace = 0; + Info.NumPackages = 1; + + Status = AcpiUtWalkPackageTree (InternalObject, NULL, + AcpiUtGetElementLength, &Info); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * We have handled all of the objects in all levels of the package. + * just add the length of the package objects themselves. + * Round up to the next machine word. + */ + Info.Length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) * + (ACPI_SIZE) Info.NumPackages; + + /* Return the total package length */ + + *ObjLength = Info.Length; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetObjectSize + * + * PARAMETERS: InternalObject - An ACPI internal object + * ObjLength - Where the length will be returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtGetObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if ((ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_OPERAND) && + (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)) + { + Status = AcpiUtGetPackageObjectSize (InternalObject, ObjLength); + } + else + { + Status = AcpiUtGetSimpleObjectSize (InternalObject, ObjLength); + } + + return (Status); +} + + diff --git a/source/components/utilities/utosi.c b/source/components/utilities/utosi.c new file mode 100644 index 000000000000..dcce8a99e18a --- /dev/null +++ b/source/components/utilities/utosi.c @@ -0,0 +1,422 @@ +/****************************************************************************** + * + * Module Name: utosi - Support for the _OSI predefined control method + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTOSI_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utosi") + +/* + * Strings supported by the _OSI predefined control method (which is + * implemented internally within this module.) + * + * March 2009: Removed "Linux" as this host no longer wants to respond true + * for this string. Basically, the only safe OS strings are windows-related + * and in many or most cases represent the only test path within the + * BIOS-provided ASL code. + * + * The last element of each entry is used to track the newest version of + * Windows that the BIOS has requested. + */ +static ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] = +{ + /* Operating System Vendor Strings */ + + {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ + {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ + {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ + {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ + {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ + {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ + {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ + {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ + {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ + {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ + {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ + + /* Feature Group Strings */ + + {"Extended Address Space Descriptor", NULL, 0, 0} + + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be dynamically added by the host via + * AcpiInstallInterface and should not be manually added here. + * + * Examples of optional feature group strings: + * + * "Module Device" + * "Processor Device" + * "3.0 Thermal Model" + * "3.0 _SCP Extensions" + * "Processor Aggregator Device" + */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitializeInterfaces + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the global _OSI supported interfaces list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitializeInterfaces ( + void) +{ + UINT32 i; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces; + + /* Link the static list of supported interfaces */ + + for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++) + { + AcpiDefaultSupportedInterfaces[i].Next = + &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1]; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInterfaceTerminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all interfaces in the global list. Sets + * AcpiGbl_SupportedInterfaces to NULL. + * + ******************************************************************************/ + +void +AcpiUtInterfaceTerminate ( + void) +{ + ACPI_INTERFACE_INFO *NextInterface; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + NextInterface = AcpiGbl_SupportedInterfaces; + + while (NextInterface) + { + AcpiGbl_SupportedInterfaces = NextInterface->Next; + + /* Only interfaces added at runtime can be freed */ + + if (NextInterface->Flags & ACPI_OSI_DYNAMIC) + { + ACPI_FREE (NextInterface->Name); + ACPI_FREE (NextInterface); + } + + NextInterface = AcpiGbl_SupportedInterfaces; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInstallInterface + * + * PARAMETERS: InterfaceName - The interface to install + * + * RETURN: Status + * + * DESCRIPTION: Install the interface into the global interface list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInstallInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *InterfaceInfo; + + + /* Allocate info block and space for the name string */ + + InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO)); + if (!InterfaceInfo) + { + return (AE_NO_MEMORY); + } + + InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1); + if (!InterfaceInfo->Name) + { + ACPI_FREE (InterfaceInfo); + return (AE_NO_MEMORY); + } + + /* Initialize new info and insert at the head of the global list */ + + ACPI_STRCPY (InterfaceInfo->Name, InterfaceName); + InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; + InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; + + AcpiGbl_SupportedInterfaces = InterfaceInfo; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveInterface + * + * PARAMETERS: InterfaceName - The interface to remove + * + * RETURN: Status + * + * DESCRIPTION: Remove the interface from the global interface list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtRemoveInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *PreviousInterface; + ACPI_INTERFACE_INFO *NextInterface; + + + PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + { + /* Found: name is in either the static list or was added at runtime */ + + if (NextInterface->Flags & ACPI_OSI_DYNAMIC) + { + /* Interface was added dynamically, remove and free it */ + + if (PreviousInterface == NextInterface) + { + AcpiGbl_SupportedInterfaces = NextInterface->Next; + } + else + { + PreviousInterface->Next = NextInterface->Next; + } + + ACPI_FREE (NextInterface->Name); + ACPI_FREE (NextInterface); + } + else + { + /* + * Interface is in static list. If marked invalid, then it + * does not actually exist. Else, mark it invalid. + */ + if (NextInterface->Flags & ACPI_OSI_INVALID) + { + return (AE_NOT_EXIST); + } + + NextInterface->Flags |= ACPI_OSI_INVALID; + } + + return (AE_OK); + } + + PreviousInterface = NextInterface; + NextInterface = NextInterface->Next; + } + + /* Interface was not found */ + + return (AE_NOT_EXIST); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetInterface + * + * PARAMETERS: InterfaceName - The interface to find + * + * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found. + * + * DESCRIPTION: Search for the specified interface name in the global list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_INTERFACE_INFO * +AcpiUtGetInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *NextInterface; + + + NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + { + return (NextInterface); + } + + NextInterface = NextInterface->Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtOsiImplementation + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Implementation of the _OSI predefined control method. When + * an invocation of _OSI is encountered in the system AML, + * control is transferred to this function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtOsiImplementation ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *StringDesc; + ACPI_OPERAND_OBJECT *ReturnDesc; + ACPI_INTERFACE_INFO *InterfaceInfo; + ACPI_INTERFACE_HANDLER InterfaceHandler; + UINT32 ReturnValue; + + + ACPI_FUNCTION_TRACE (UtOsiImplementation); + + + /* Validate the string input argument (from the AML caller) */ + + StringDesc = WalkState->Arguments[0].Object; + if (!StringDesc || + (StringDesc->Common.Type != ACPI_TYPE_STRING)) + { + return_ACPI_STATUS (AE_TYPE); + } + + /* Create a return object */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Default return value is 0, NOT SUPPORTED */ + + ReturnValue = 0; + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + /* Lookup the interface in the global _OSI list */ + + InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer); + if (InterfaceInfo && + !(InterfaceInfo->Flags & ACPI_OSI_INVALID)) + { + /* + * The interface is supported. + * Update the OsiData if necessary. We keep track of the latest + * version of Windows that has been requested by the BIOS. + */ + if (InterfaceInfo->Value > AcpiGbl_OsiData) + { + AcpiGbl_OsiData = InterfaceInfo->Value; + } + + ReturnValue = ACPI_UINT32_MAX; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + + /* + * Invoke an optional _OSI interface handler. The host OS may wish + * to do some interface-specific handling. For example, warn about + * certain interfaces or override the true/false support value. + */ + InterfaceHandler = AcpiGbl_InterfaceHandler; + if (InterfaceHandler) + { + ReturnValue = InterfaceHandler ( + StringDesc->String.Pointer, ReturnValue); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", + StringDesc->String.Pointer, ReturnValue == 0 ? "not " : "")); + + /* Complete the return object */ + + ReturnDesc->Integer.Value = ReturnValue; + WalkState->ReturnDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} diff --git a/source/components/utilities/utresrc.c b/source/components/utilities/utresrc.c new file mode 100644 index 000000000000..c2c135b7d233 --- /dev/null +++ b/source/components/utilities/utresrc.c @@ -0,0 +1,923 @@ +/******************************************************************************* + * + * Module Name: utresrc - Resource managment utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTRESRC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utresrc") + + +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +/* + * Strings used to decode resource descriptors. + * Used by both the disasssembler and the debugger resource dump routines + */ +const char *AcpiGbl_BmDecode[] = +{ + "NotBusMaster", + "BusMaster" +}; + +const char *AcpiGbl_ConfigDecode[] = +{ + "0 - Good Configuration", + "1 - Acceptable Configuration", + "2 - Suboptimal Configuration", + "3 - ***Invalid Configuration***", +}; + +const char *AcpiGbl_ConsumeDecode[] = +{ + "ResourceProducer", + "ResourceConsumer" +}; + +const char *AcpiGbl_DecDecode[] = +{ + "PosDecode", + "SubDecode" +}; + +const char *AcpiGbl_HeDecode[] = +{ + "Level", + "Edge" +}; + +const char *AcpiGbl_IoDecode[] = +{ + "Decode10", + "Decode16" +}; + +const char *AcpiGbl_LlDecode[] = +{ + "ActiveHigh", + "ActiveLow" +}; + +const char *AcpiGbl_MaxDecode[] = +{ + "MaxNotFixed", + "MaxFixed" +}; + +const char *AcpiGbl_MemDecode[] = +{ + "NonCacheable", + "Cacheable", + "WriteCombining", + "Prefetchable" +}; + +const char *AcpiGbl_MinDecode[] = +{ + "MinNotFixed", + "MinFixed" +}; + +const char *AcpiGbl_MtpDecode[] = +{ + "AddressRangeMemory", + "AddressRangeReserved", + "AddressRangeACPI", + "AddressRangeNVS" +}; + +const char *AcpiGbl_RngDecode[] = +{ + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" +}; + +const char *AcpiGbl_RwDecode[] = +{ + "ReadOnly", + "ReadWrite" +}; + +const char *AcpiGbl_ShrDecode[] = +{ + "Exclusive", + "Shared" +}; + +const char *AcpiGbl_SizDecode[] = +{ + "Transfer8", + "Transfer8_16", + "Transfer16", + "InvalidSize" +}; + +const char *AcpiGbl_TrsDecode[] = +{ + "DenseTranslation", + "SparseTranslation" +}; + +const char *AcpiGbl_TtpDecode[] = +{ + "TypeStatic", + "TypeTranslation" +}; + +const char *AcpiGbl_TypDecode[] = +{ + "Compatibility", + "TypeA", + "TypeB", + "TypeF" +}; + +const char *AcpiGbl_PpcDecode[] = +{ + "PullDefault", + "PullUp", + "PullDown", + "PullNone" +}; + +const char *AcpiGbl_IorDecode[] = +{ + "IoRestrictionNone", + "IoRestrictionInputOnly", + "IoRestrictionOutputOnly", + "IoRestrictionNoneAndPreserve" +}; + +const char *AcpiGbl_DtsDecode[] = +{ + "Width8bit", + "Width16bit", + "Width32bit", + "Width64bit", + "Width128bit", + "Width256bit", +}; + +/* GPIO connection type */ + +const char *AcpiGbl_CtDecode[] = +{ + "Interrupt", + "I/O" +}; + +/* Serial bus type */ + +const char *AcpiGbl_SbtDecode[] = +{ + "/* UNKNOWN serial bus type */", + "I2C", + "SPI", + "UART" +}; + +/* I2C serial bus access mode */ + +const char *AcpiGbl_AmDecode[] = +{ + "AddressingMode7Bit", + "AddressingMode10Bit" +}; + +/* I2C serial bus slave mode */ + +const char *AcpiGbl_SmDecode[] = +{ + "ControllerInitiated", + "DeviceInitiated" +}; + +/* SPI serial bus wire mode */ + +const char *AcpiGbl_WmDecode[] = +{ + "FourWireMode", + "ThreeWireMode" +}; + +/* SPI serial clock phase */ + +const char *AcpiGbl_CphDecode[] = +{ + "ClockPhaseFirst", + "ClockPhaseSecond" +}; + +/* SPI serial bus clock polarity */ + +const char *AcpiGbl_CpoDecode[] = +{ + "ClockPolarityLow", + "ClockPolarityHigh" +}; + +/* SPI serial bus device polarity */ + +const char *AcpiGbl_DpDecode[] = +{ + "PolarityLow", + "PolarityHigh" +}; + +/* UART serial bus endian */ + +const char *AcpiGbl_EdDecode[] = +{ + "LittleEndian", + "BigEndian" +}; + +/* UART serial bus bits per byte */ + +const char *AcpiGbl_BpbDecode[] = +{ + "DataBitsFive", + "DataBitsSix", + "DataBitsSeven", + "DataBitsEight", + "DataBitsNine", + "/* UNKNOWN Bits per byte */", + "/* UNKNOWN Bits per byte */", + "/* UNKNOWN Bits per byte */" +}; + +/* UART serial bus stop bits */ + +const char *AcpiGbl_SbDecode[] = +{ + "StopBitsNone", + "StopBitsOne", + "StopBitsOnePlusHalf", + "StopBitsTwo" +}; + +/* UART serial bus flow control */ + +const char *AcpiGbl_FcDecode[] = +{ + "FlowControlNone", + "FlowControlHardware", + "FlowControlXON", + "/* UNKNOWN flow control keyword */" +}; + +/* UART serial bus parity type */ + +const char *AcpiGbl_PtDecode[] = +{ + "ParityTypeNone", + "ParityTypeEven", + "ParityTypeOdd", + "ParityTypeMark", + "ParityTypeSpace", + "/* UNKNOWN parity keyword */", + "/* UNKNOWN parity keyword */", + "/* UNKNOWN parity keyword */" +}; + +#endif + + +/* + * Base sizes of the raw AML resource descriptors, indexed by resource type. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +const UINT8 AcpiGbl_ResourceAmlSizes[] = +{ + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA), + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG), + + /* Large descriptors */ + + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER), + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO), + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS), +}; + +const UINT8 AcpiGbl_ResourceAmlSerialBusSizes[] = +{ + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS), +}; + + +/* + * Resource types, used to validate the resource length field. + * The length of fixed-length types must match exactly, variable + * lengths must meet the minimum required length, etc. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +static const UINT8 AcpiGbl_ResourceTypes[] = +{ + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ + ACPI_FIXED_LENGTH, /* 05 DMA */ + ACPI_SMALL_VARIABLE_LENGTH, /* 06 StartDependentFunctions */ + ACPI_FIXED_LENGTH, /* 07 EndDependentFunctions */ + ACPI_FIXED_LENGTH, /* 08 IO */ + ACPI_FIXED_LENGTH, /* 09 FixedIO */ + ACPI_FIXED_LENGTH, /* 0A FixedDMA */ + 0, + 0, + 0, + ACPI_VARIABLE_LENGTH, /* 0E VendorShort */ + ACPI_FIXED_LENGTH, /* 0F EndTag */ + + /* Large descriptors */ + + 0, + ACPI_FIXED_LENGTH, /* 01 Memory24 */ + ACPI_FIXED_LENGTH, /* 02 GenericRegister */ + 0, + ACPI_VARIABLE_LENGTH, /* 04 VendorLong */ + ACPI_FIXED_LENGTH, /* 05 Memory32 */ + ACPI_FIXED_LENGTH, /* 06 Memory32Fixed */ + ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ + ACPI_VARIABLE_LENGTH, /* 08 Word* address */ + ACPI_VARIABLE_LENGTH, /* 09 ExtendedIRQ */ + ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ + ACPI_FIXED_LENGTH, /* 0B Extended* address */ + ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ + 0, + ACPI_VARIABLE_LENGTH /* 0E *SerialBus */ +}; + +/* + * For the iASL compiler/disassembler, we don't want any error messages + * because the disassembler uses the resource validation code to determine + * if Buffer objects are actually Resource Templates. + */ +#ifdef ACPI_ASL_COMPILER +#define ACPI_RESOURCE_ERROR(plist) +#else +#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtWalkAmlResources + * + * PARAMETERS: Aml - Pointer to the raw AML resource template + * AmlLength - Length of the entire template + * UserFunction - Called once for each descriptor found. If + * NULL, a pointer to the EndTag is returned + * Context - Passed to UserFunction + * + * RETURN: Status + * + * DESCRIPTION: Walk a raw AML resource list(buffer). User function called + * once for each resource found. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtWalkAmlResources ( + UINT8 *Aml, + ACPI_SIZE AmlLength, + ACPI_WALK_AML_CALLBACK UserFunction, + void *Context) +{ + ACPI_STATUS Status; + UINT8 *EndAml; + UINT8 ResourceIndex; + UINT32 Length; + UINT32 Offset = 0; + UINT8 EndTag[2] = {0x79, 0x00}; + + + ACPI_FUNCTION_TRACE (UtWalkAmlResources); + + + /* The absolute minimum resource template is one EndTag descriptor */ + + if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) + { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); + } + + /* Point to the end of the resource template buffer */ + + EndAml = Aml + AmlLength; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + while (Aml < EndAml) + { + /* Validate the Resource Type and Resource Length */ + + Status = AcpiUtValidateResource (Aml, &ResourceIndex); + if (ACPI_FAILURE (Status)) + { + /* + * Exit on failure. Cannot continue because the descriptor length + * may be bogus also. + */ + return_ACPI_STATUS (Status); + } + + /* Get the length of this descriptor */ + + Length = AcpiUtGetDescriptorLength (Aml); + + /* Invoke the user function */ + + if (UserFunction) + { + Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* An EndTag descriptor terminates this resource template */ + + if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG) + { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the EndTag + */ + if ((Aml + 1) >= EndAml) + { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the EndTag if requested */ + + if (!UserFunction) + { + *(void **) Context = Aml; + } + + /* Normal exit */ + + return_ACPI_STATUS (AE_OK); + } + + Aml += Length; + Offset += Length; + } + + /* Did not find an EndTag descriptor */ + + if (UserFunction) + { + /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */ + + (void) AcpiUtValidateResource (EndTag, &ResourceIndex); + Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateResource + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * ReturnIndex - Where the resource index is returned. NULL + * if the index is not required. + * + * RETURN: Status, and optionally the Index into the global resource tables + * + * DESCRIPTION: Validate an AML resource descriptor by checking the Resource + * Type and Resource Length. Returns an index into the global + * resource information/dispatch tables for later use. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtValidateResource ( + void *Aml, + UINT8 *ReturnIndex) +{ + AML_RESOURCE *AmlResource; + UINT8 ResourceType; + UINT8 ResourceIndex; + ACPI_RS_LENGTH ResourceLength; + ACPI_RS_LENGTH MinimumResourceLength; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * 1) Validate the ResourceType field (Byte 0) + */ + ResourceType = ACPI_GET8 (Aml); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ResourceType & ACPI_RESOURCE_NAME_LARGE) + { + /* Verify the large resource type (name) against the max */ + + if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX) + { + goto InvalidResource; + } + + /* + * Large Resource Type -- bits 6:0 contain the name + * Translate range 0x80-0x8B to index range 0x10-0x1B + */ + ResourceIndex = (UINT8) (ResourceType - 0x70); + } + else + { + /* + * Small Resource Type -- bits 6:3 contain the name + * Shift range to index range 0x00-0x0F + */ + ResourceIndex = (UINT8) + ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); + } + + /* + * Check validity of the resource type, via AcpiGbl_ResourceTypes. Zero + * indicates an invalid resource. + */ + if (!AcpiGbl_ResourceTypes[ResourceIndex]) + { + goto InvalidResource; + } + + /* + * Validate the ResourceLength field. This ensures that the length + * is at least reasonable, and guarantees that it is non-zero. + */ + ResourceLength = AcpiUtGetResourceLength (Aml); + MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; + + /* Validate based upon the type of resource - fixed length or variable */ + + switch (AcpiGbl_ResourceTypes[ResourceIndex]) + { + case ACPI_FIXED_LENGTH: + + /* Fixed length resource, length must match exactly */ + + if (ResourceLength != MinimumResourceLength) + { + goto BadResourceLength; + } + break; + + case ACPI_VARIABLE_LENGTH: + + /* Variable length resource, length must be at least the minimum */ + + if (ResourceLength < MinimumResourceLength) + { + goto BadResourceLength; + } + break; + + case ACPI_SMALL_VARIABLE_LENGTH: + + /* Small variable length resource, length can be (Min) or (Min-1) */ + + if ((ResourceLength > MinimumResourceLength) || + (ResourceLength < (MinimumResourceLength - 1))) + { + goto BadResourceLength; + } + break; + + default: + + /* Shouldn't happen (because of validation earlier), but be sure */ + + goto InvalidResource; + } + + AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml); + if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS) + { + /* Validate the BusType field */ + + if ((AmlResource->CommonSerialBus.Type == 0) || + (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE)) + { + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", + AmlResource->CommonSerialBus.Type)); + return (AE_AML_INVALID_RESOURCE_TYPE); + } + } + + /* Optionally return the resource table index */ + + if (ReturnIndex) + { + *ReturnIndex = ResourceIndex; + } + + return (AE_OK); + + +InvalidResource: + + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + ResourceType)); + return (AE_AML_INVALID_RESOURCE_TYPE); + +BadResourceLength: + + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid resource descriptor length: Type " + "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", + ResourceType, ResourceLength, MinimumResourceLength)); + return (AE_AML_BAD_RESOURCE_LENGTH); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceType + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: The Resource Type with no extraneous bits (except the + * Large/Small descriptor bit -- this is left alone) + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +UINT8 +AcpiUtGetResourceType ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + /* Large Resource Type -- bits 6:0 contain the name */ + + return (ACPI_GET8 (Aml)); + } + else + { + /* Small Resource Type -- bits 6:3 contain the name */ + + return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte Length + * + * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By + * definition, this does not include the size of the descriptor + * header or the length field itself. + * + ******************************************************************************/ + +UINT16 +AcpiUtGetResourceLength ( + void *Aml) +{ + ACPI_RS_LENGTH ResourceLength; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1)); + + } + else + { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + ResourceLength = (UINT16) (ACPI_GET8 (Aml) & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + } + + return (ResourceLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceHeaderLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Length of the AML header (depends on large/small descriptor) + * + * DESCRIPTION: Get the length of the header for this resource. + * + ******************************************************************************/ + +UINT8 +AcpiUtGetResourceHeaderLength ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Examine the large/small bit in the resource header */ + + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + return (sizeof (AML_RESOURCE_LARGE_HEADER)); + } + else + { + return (sizeof (AML_RESOURCE_SMALL_HEADER)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetDescriptorLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte length + * + * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the + * length of the descriptor header and the length field itself. + * Used to walk descriptor lists. + * + ******************************************************************************/ + +UINT32 +AcpiUtGetDescriptorLength ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * Get the Resource Length (does not include header length) and add + * the header length (depends on if this is a small or large resource) + */ + return (AcpiUtGetResourceLength (Aml) + + AcpiUtGetResourceHeaderLength (Aml)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceEndTag + * + * PARAMETERS: ObjDesc - The resource template buffer object + * EndTag - Where the pointer to the EndTag is returned + * + * RETURN: Status, pointer to the end tag + * + * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template + * Note: allows a buffer length of zero. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtGetResourceEndTag ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 **EndTag) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtGetResourceEndTag); + + + /* Allow a buffer length of zero */ + + if (!ObjDesc->Buffer.Length) + { + *EndTag = ObjDesc->Buffer.Pointer; + return_ACPI_STATUS (AE_OK); + } + + /* Validate the template and get a pointer to the EndTag */ + + Status = AcpiUtWalkAmlResources (ObjDesc->Buffer.Pointer, + ObjDesc->Buffer.Length, NULL, EndTag); + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/utilities/utstate.c b/source/components/utilities/utstate.c new file mode 100644 index 000000000000..62a1aefec7d4 --- /dev/null +++ b/source/components/utilities/utstate.c @@ -0,0 +1,398 @@ +/******************************************************************************* + * + * Module Name: utstate - state object support procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTSTATE_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstate") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePkgStateAndPush + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * StateList - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreatePkgStateAndPush ( + void *InternalObject, + void *ExternalObject, + UINT16 Index, + ACPI_GENERIC_STATE **StateList) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + State = AcpiUtCreatePkgState (InternalObject, ExternalObject, Index); + if (!State) + { + return (AE_NO_MEMORY); + } + + AcpiUtPushGenericState (StateList, State); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPushGenericState + * + * PARAMETERS: ListHead - Head of the state stack + * State - State object to push + * + * RETURN: None + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +AcpiUtPushGenericState ( + ACPI_GENERIC_STATE **ListHead, + ACPI_GENERIC_STATE *State) +{ + ACPI_FUNCTION_TRACE (UtPushGenericState); + + + /* Push the state object onto the front of the list (stack) */ + + State->Common.Next = *ListHead; + *ListHead = State; + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPopGenericState + * + * PARAMETERS: ListHead - Head of the state stack + * + * RETURN: The popped state object + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtPopGenericState ( + ACPI_GENERIC_STATE **ListHead) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtPopGenericState); + + + /* Remove the state object at the head of the list (stack) */ + + State = *ListHead; + if (State) + { + /* Update the list head */ + + *ListHead = State->Common.Next; + } + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateGenericState + * + * PARAMETERS: None + * + * RETURN: The new state object. NULL on failure. + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateGenericState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + State = AcpiOsAcquireObject (AcpiGbl_StateCache); + if (State) + { + /* Initialize */ + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE; + } + + return (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateThreadState + * + * PARAMETERS: None + * + * RETURN: New Thread State. NULL on failure + * + * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used + * to track per-thread info during method execution + * + ******************************************************************************/ + +ACPI_THREAD_STATE * +AcpiUtCreateThreadState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtCreateThreadState); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_THREAD; + State->Thread.ThreadId = AcpiOsGetThreadId (); + + /* Check for invalid thread ID - zero is very bad, it will break things */ + + if (!State->Thread.ThreadId) + { + ACPI_ERROR ((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId")); + State->Thread.ThreadId = (ACPI_THREAD_ID) 1; + } + + return_PTR ((ACPI_THREAD_STATE *) State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateUpdateState + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateUpdateState ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE_PTR (UtCreateUpdateState, Object); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_UPDATE; + State->Update.Object = Object; + State->Update.Value = Action; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePkgState + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Package State" + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreatePkgState ( + void *InternalObject, + void *ExternalObject, + UINT16 Index) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE_PTR (UtCreatePkgState, InternalObject); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_PACKAGE; + State->Pkg.SourceObject = (ACPI_OPERAND_OBJECT *) InternalObject; + State->Pkg.DestObject = ExternalObject; + State->Pkg.Index= Index; + State->Pkg.NumPackages = 1; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateControlState + * + * PARAMETERS: None + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateControlState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtCreateControlState); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the control struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_CONTROL; + State->Common.State = ACPI_CONTROL_CONDITIONAL_EXECUTING; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteGenericState + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Release a state object to the state cache. NULL state objects + * are ignored. + * + ******************************************************************************/ + +void +AcpiUtDeleteGenericState ( + ACPI_GENERIC_STATE *State) +{ + ACPI_FUNCTION_TRACE (UtDeleteGenericState); + + + /* Ignore null state */ + + if (State) + { + (void) AcpiOsReleaseObject (AcpiGbl_StateCache, State); + } + return_VOID; +} + + diff --git a/source/components/utilities/uttrack.c b/source/components/utilities/uttrack.c new file mode 100644 index 000000000000..106cc243ecde --- /dev/null +++ b/source/components/utilities/uttrack.c @@ -0,0 +1,711 @@ +/****************************************************************************** + * + * Module Name: uttrack - Memory allocation tracking routines (debug only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These procedures are used for tracking memory leaks in the subsystem, and + * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. + * + * Each memory allocation is tracked via a doubly linked list. Each + * element contains the caller's component, module name, function name, and + * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call + * AcpiUtTrackAllocation to add an element to the list; deletion + * occurs in the body of AcpiUtFree. + */ + +#define __UTTRACK_C__ + +#include "acpi.h" +#include "accommon.h" + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("uttrack") + +/* Local prototypes */ + +static ACPI_DEBUG_MEM_BLOCK * +AcpiUtFindAllocation ( + void *Allocation); + +static ACPI_STATUS +AcpiUtTrackAllocation ( + ACPI_DEBUG_MEM_BLOCK *Address, + ACPI_SIZE Size, + UINT8 AllocType, + UINT32 Component, + const char *Module, + UINT32 Line); + +static ACPI_STATUS +AcpiUtRemoveAllocation ( + ACPI_DEBUG_MEM_BLOCK *Address, + UINT32 Component, + const char *Module, + UINT32 Line); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateList + * + * PARAMETERS: CacheName - Ascii name for the cache + * ObjectSize - Size of each cached object + * ReturnCache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a local memory list for tracking purposed + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateList ( + char *ListName, + UINT16 ObjectSize, + ACPI_MEMORY_LIST **ReturnCache) +{ + ACPI_MEMORY_LIST *Cache; + + + Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); + if (!Cache) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + + Cache->ListName = ListName; + Cache->ObjectSize = ObjectSize; + + *ReturnCache = Cache; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateAndTrack + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocateAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *Allocation; + ACPI_STATUS Status; + + + Allocation = AcpiUtAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER), + Component, Module, Line); + if (!Allocation) + { + return (NULL); + } + + Status = AcpiUtTrackAllocation (Allocation, Size, + ACPI_MEM_MALLOC, Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + AcpiOsFree (Allocation); + return (NULL); + } + + AcpiGbl_GlobalList->TotalAllocated++; + AcpiGbl_GlobalList->TotalSize += (UINT32) Size; + AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; + if (AcpiGbl_GlobalList->CurrentTotalSize > AcpiGbl_GlobalList->MaxOccupied) + { + AcpiGbl_GlobalList->MaxOccupied = AcpiGbl_GlobalList->CurrentTotalSize; + } + + return ((void *) &Allocation->UserSpace); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateZeroedAndTrack + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocateZeroedAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *Allocation; + ACPI_STATUS Status; + + + Allocation = AcpiUtAllocateZeroed (Size + sizeof (ACPI_DEBUG_MEM_HEADER), + Component, Module, Line); + if (!Allocation) + { + /* Report allocation error */ + + ACPI_ERROR ((Module, Line, + "Could not allocate size %u", (UINT32) Size)); + return (NULL); + } + + Status = AcpiUtTrackAllocation (Allocation, Size, + ACPI_MEM_CALLOC, Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + AcpiOsFree (Allocation); + return (NULL); + } + + AcpiGbl_GlobalList->TotalAllocated++; + AcpiGbl_GlobalList->TotalSize += (UINT32) Size; + AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; + if (AcpiGbl_GlobalList->CurrentTotalSize > AcpiGbl_GlobalList->MaxOccupied) + { + AcpiGbl_GlobalList->MaxOccupied = AcpiGbl_GlobalList->CurrentTotalSize; + } + + return ((void *) &Allocation->UserSpace); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFreeAndTrack + * + * PARAMETERS: Allocation - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Allocation + * + ******************************************************************************/ + +void +AcpiUtFreeAndTrack ( + void *Allocation, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *DebugBlock; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation); + + + if (NULL == Allocation) + { + ACPI_ERROR ((Module, Line, + "Attempt to delete a NULL address")); + + return_VOID; + } + + DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK, + (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER))); + + AcpiGbl_GlobalList->TotalFreed++; + AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size; + + Status = AcpiUtRemoveAllocation (DebugBlock, + Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory")); + } + + AcpiOsFree (DebugBlock); + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", Allocation)); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFindAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * + * RETURN: A list element if found; NULL otherwise. + * + * DESCRIPTION: Searches for an element in the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_DEBUG_MEM_BLOCK * +AcpiUtFindAllocation ( + void *Allocation) +{ + ACPI_DEBUG_MEM_BLOCK *Element; + + + ACPI_FUNCTION_ENTRY (); + + + Element = AcpiGbl_GlobalList->ListHead; + + /* Search for the address. */ + + while (Element) + { + if (Element == Allocation) + { + return (Element); + } + + Element = Element->Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrackAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * Size - Size of the allocation + * AllocType - MEM_MALLOC or MEM_CALLOC + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None. + * + * DESCRIPTION: Inserts an element into the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtTrackAllocation ( + ACPI_DEBUG_MEM_BLOCK *Allocation, + ACPI_SIZE Size, + UINT8 AllocType, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_MEMORY_LIST *MemList; + ACPI_DEBUG_MEM_BLOCK *Element; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); + + + if (AcpiGbl_DisableMemTracking) + { + return_ACPI_STATUS (AE_OK); + } + + MemList = AcpiGbl_GlobalList; + Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Search list for this address to make sure it is not already on the list. + * This will catch several kinds of problems. + */ + Element = AcpiUtFindAllocation (Allocation); + if (Element) + { + ACPI_ERROR ((AE_INFO, + "UtTrackAllocation: Allocation already present in list! (%p)", + Allocation)); + + ACPI_ERROR ((AE_INFO, "Element %p Address %p", + Element, Allocation)); + + goto UnlockAndExit; + } + + /* Fill in the instance data. */ + + Allocation->Size = (UINT32) Size; + Allocation->AllocType = AllocType; + Allocation->Component = Component; + Allocation->Line = Line; + + ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); + Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; + + /* Insert at list head */ + + if (MemList->ListHead) + { + ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation; + } + + Allocation->Next = MemList->ListHead; + Allocation->Previous = NULL; + + MemList->ListHead = Allocation; + + +UnlockAndExit: + Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: + * + * DESCRIPTION: Deletes an element from the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtRemoveAllocation ( + ACPI_DEBUG_MEM_BLOCK *Allocation, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_MEMORY_LIST *MemList; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtRemoveAllocation); + + + if (AcpiGbl_DisableMemTracking) + { + return_ACPI_STATUS (AE_OK); + } + + MemList = AcpiGbl_GlobalList; + if (NULL == MemList->ListHead) + { + /* No allocations! */ + + ACPI_ERROR ((Module, Line, + "Empty allocation list, nothing to free!")); + + return_ACPI_STATUS (AE_OK); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Unlink */ + + if (Allocation->Previous) + { + (Allocation->Previous)->Next = Allocation->Next; + } + else + { + MemList->ListHead = Allocation->Next; + } + + if (Allocation->Next) + { + (Allocation->Next)->Previous = Allocation->Previous; + } + + /* Mark the segment as deleted */ + + ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size); + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", + Allocation->Size)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpAllocationInfo + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: Print some info about the outstanding allocations. + * + ******************************************************************************/ + +void +AcpiUtDumpAllocationInfo ( + void) +{ +/* + ACPI_MEMORY_LIST *MemList; +*/ + + ACPI_FUNCTION_TRACE (UtDumpAllocationInfo); + +/* + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current allocations", + MemList->CurrentCount, + ROUND_UP_TO_1K (MemList->CurrentSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", + MemList->MaxConcurrentCount, + ROUND_UP_TO_1K (MemList->MaxConcurrentSize))); + + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", + RunningObjectCount, + ROUND_UP_TO_1K (RunningObjectSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", + RunningAllocCount, + ROUND_UP_TO_1K (RunningAllocSize))); + + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current Nodes", + AcpiGbl_CurrentNodeCount, + ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max Nodes", + AcpiGbl_MaxConcurrentNodeCount, + ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount * + sizeof (ACPI_NAMESPACE_NODE))))); +*/ + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpAllocations + * + * PARAMETERS: Component - Component(s) to dump info for. + * Module - Module to dump info for. NULL means all. + * + * RETURN: None + * + * DESCRIPTION: Print a list of all outstanding allocations. + * + ******************************************************************************/ + +void +AcpiUtDumpAllocations ( + UINT32 Component, + const char *Module) +{ + ACPI_DEBUG_MEM_BLOCK *Element; + ACPI_DESCRIPTOR *Descriptor; + UINT32 NumOutstanding = 0; + UINT8 DescriptorType; + + + ACPI_FUNCTION_TRACE (UtDumpAllocations); + + + if (AcpiGbl_DisableMemTracking) + { + return; + } + + /* + * Walk the allocation list. + */ + if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) + { + return; + } + + Element = AcpiGbl_GlobalList->ListHead; + while (Element) + { + if ((Element->Component & Component) && + ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) + { + Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); + + if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) + { + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u " + "[Not a Descriptor - too small]\n", + Descriptor, Element->Size, Element->Module, + Element->Line); + } + else + { + /* Ignore allocated objects that are in a cache */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) + { + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ", + Descriptor, Element->Size, Element->Module, + Element->Line, AcpiUtGetDescriptorName (Descriptor)); + + /* Validate the descriptor type using Type field and length */ + + DescriptorType = 0; /* Not a valid descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) + { + case ACPI_DESC_TYPE_OPERAND: + if (Element->Size == sizeof (ACPI_DESC_TYPE_OPERAND)) + { + DescriptorType = ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + if (Element->Size == sizeof (ACPI_DESC_TYPE_PARSER)) + { + DescriptorType = ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + if (Element->Size == sizeof (ACPI_DESC_TYPE_NAMED)) + { + DescriptorType = ACPI_DESC_TYPE_NAMED; + } + break; + + default: + break; + } + + /* Display additional info for the major descriptor types */ + + switch (DescriptorType) + { + case ACPI_DESC_TYPE_OPERAND: + AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", + AcpiUtGetTypeName (Descriptor->Object.Common.Type), + Descriptor->Object.Common.ReferenceCount); + break; + + case ACPI_DESC_TYPE_PARSER: + AcpiOsPrintf ("AmlOpcode 0x%04hX\n", + Descriptor->Op.Asl.AmlOpcode); + break; + + case ACPI_DESC_TYPE_NAMED: + AcpiOsPrintf ("%4.4s\n", + AcpiUtGetNodeName (&Descriptor->Node)); + break; + + default: + AcpiOsPrintf ( "\n"); + break; + } + } + } + + NumOutstanding++; + } + + Element = Element->Next; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + + /* Print summary */ + + if (!NumOutstanding) + { + ACPI_INFO ((AE_INFO, "No outstanding allocations")); + } + else + { + ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations", + NumOutstanding, NumOutstanding)); + } + + return_VOID; +} + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + diff --git a/source/components/utilities/utxface.c b/source/components/utilities/utxface.c new file mode 100644 index 000000000000..3e858c9b0ffe --- /dev/null +++ b/source/components/utilities/utxface.c @@ -0,0 +1,837 @@ +/****************************************************************************** + * + * Module Name: utxface - External interfaces for "global" ACPI functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "actables.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxface") + + +#ifndef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiInitializeSubsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInitializeSubsystem ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInitializeSubsystem); + + + AcpiGbl_StartupFlags = ACPI_SUBSYSTEM_INITIALIZE; + ACPI_DEBUG_EXEC (AcpiUtInitStackPtrTrace ()); + + /* Initialize the OS-Dependent layer */ + + Status = AcpiOsInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During OSL initialization")); + return_ACPI_STATUS (Status); + } + + /* Initialize all globals used by the subsystem */ + + Status = AcpiUtInitGlobals (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During initialization of globals")); + return_ACPI_STATUS (Status); + } + + /* Create the default mutex objects */ + + Status = AcpiUtMutexInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During Global Mutex creation")); + return_ACPI_STATUS (Status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + Status = AcpiNsRootInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During Namespace initialization")); + return_ACPI_STATUS (Status); + } + + /* Initialize the global OSI interfaces list with the static names */ + + Status = AcpiUtInitializeInterfaces (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During OSI interfaces initialization")); + return_ACPI_STATUS (Status); + } + + /* If configured, initialize the AML debugger */ + + ACPI_DEBUGGER_EXEC (Status = AcpiDbInitialize ()); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInitializeSubsystem) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnableSubsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableSubsystem ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiEnableSubsystem); + + +#if (!ACPI_REDUCED_HARDWARE) + + /* Enable ACPI mode */ + + if (!(Flags & ACPI_NO_ACPI_ENABLE)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n")); + + AcpiGbl_OriginalMode = AcpiHwGetMode(); + + Status = AcpiEnable (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "AcpiEnable failed")); + return_ACPI_STATUS (Status); + } + } + + /* + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ + Status = AcpiTbInitializeFacs (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS (Status); + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* + * Install the default OpRegion handlers. These are installed unless + * other handlers have already been installed via the + * InstallAddressSpaceHandler interface. + */ + if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Installing default address space handlers\n")); + + Status = AcpiEvInstallRegionHandlers (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + +#if (!ACPI_REDUCED_HARDWARE) + /* + * Initialize ACPI Event handling (Fixed and General Purpose) + * + * Note1: We must have the hardware and events initialized before we can + * execute any control methods safely. Any control method can require + * ACPI hardware support, so the hardware must be fully initialized before + * any method execution! + * + * Note2: Fixed events are initialized and enabled here. GPEs are + * initialized, but cannot be enabled until after the hardware is + * completely initialized (SCI and GlobalLock activated) and the various + * initialization control methods are run (_REG, _STA, _INI) on the + * entire namespace. + */ + if (!(Flags & ACPI_NO_EVENT_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Initializing ACPI events\n")); + + Status = AcpiEvInitializeEvents (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Install the SCI handler and Global Lock handler. This completes the + * hardware initialization. + */ + if (!(Flags & ACPI_NO_HANDLER_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Installing SCI/GL handlers\n")); + + Status = AcpiEvInstallXruptHandlers (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableSubsystem) + + +/******************************************************************************* + * + * FUNCTION: AcpiInitializeObjects + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes namespace initialization by initializing device + * objects and executing AML code for Regions, buffers, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInitializeObjects ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiInitializeObjects); + + + /* + * Run all _REG methods + * + * Note: Any objects accessed by the _REG methods will be automatically + * initialized, even if they contain executable AML (see the call to + * AcpiNsInitializeObjects below). + */ + if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Executing _REG OpRegion methods\n")); + + Status = AcpiEvInitializeOpRegions (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Execute any module-level code that was detected during the table load + * phase. Although illegal since ACPI 2.0, there are many machines that + * contain this type of code. Each block of detected executable AML code + * outside of any control method is wrapped with a temporary control + * method object and placed on a global list. The methods on this list + * are executed below. + */ + AcpiNsExecModuleCodeList (); + + /* + * Initialize the objects that remain uninitialized. This runs the + * executable AML that may be part of the declaration of these objects: + * OperationRegions, BufferFields, Buffers, and Packages. + */ + if (!(Flags & ACPI_NO_OBJECT_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Completing Initialization of ACPI Objects\n")); + + Status = AcpiNsInitializeObjects (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Initialize all device objects in the namespace. This runs the device + * _STA and _INI methods. + */ + if (!(Flags & ACPI_NO_DEVICE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Initializing ACPI Devices\n")); + + Status = AcpiNsInitializeDevices (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Empty the caches (delete the cached objects) on the assumption that + * the table load filled them up more than they will be at runtime -- + * thus wasting non-paged memory. + */ + Status = AcpiPurgeCachedObjects (); + + AcpiGbl_StartupFlags |= ACPI_INITIALIZED_OK; + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInitializeObjects) + + +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTerminate ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiTerminate); + + + /* Just exit if subsystem is already shutdown */ + + if (AcpiGbl_Shutdown) + { + ACPI_ERROR ((AE_INFO, "ACPI Subsystem is already terminated")); + return_ACPI_STATUS (AE_OK); + } + + /* Subsystem appears active, go ahead and shut it down */ + + AcpiGbl_Shutdown = TRUE; + AcpiGbl_StartupFlags = 0; + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); + + /* Terminate the AML Debugger if present */ + + ACPI_DEBUGGER_EXEC (AcpiGbl_DbTerminateThreads = TRUE); + + /* Shutdown and free all resources */ + + AcpiUtSubsystemShutdown (); + + /* Free the mutex objects */ + + AcpiUtMutexTerminate (); + + +#ifdef ACPI_DEBUGGER + + /* Shut down the debugger */ + + AcpiDbTerminate (); +#endif + + /* Now we can shutdown the OS-dependent layer */ + + Status = AcpiOsTerminate (); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiTerminate) + + +#ifndef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiSubsystemStatus + * + * PARAMETERS: None + * + * RETURN: Status of the ACPI subsystem + * + * DESCRIPTION: Other drivers that use the ACPI subsystem should call this + * before making any other calls, to ensure the subsystem + * initialized successfully. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSubsystemStatus ( + void) +{ + + if (AcpiGbl_StartupFlags & ACPI_INITIALIZED_OK) + { + return (AE_OK); + } + else + { + return (AE_ERROR); + } +} + +ACPI_EXPORT_SYMBOL (AcpiSubsystemStatus) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetSystemInfo + * + * PARAMETERS: OutBuffer - A buffer to receive the resources for the + * device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the OutBuffer. + * + * If the function fails an appropriate status will be returned + * and the value of OutBuffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetSystemInfo ( + ACPI_BUFFER *OutBuffer) +{ + ACPI_SYSTEM_INFO *InfoPtr; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetSystemInfo); + + + /* Parameter validation */ + + Status = AcpiUtValidateBuffer (OutBuffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutBuffer, sizeof (ACPI_SYSTEM_INFO)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Populate the return buffer + */ + InfoPtr = (ACPI_SYSTEM_INFO *) OutBuffer->Pointer; + + InfoPtr->AcpiCaVersion = ACPI_CA_VERSION; + + /* System flags (ACPI capabilities) */ + + InfoPtr->Flags = ACPI_SYS_MODE_ACPI; + + /* Timer resolution - 24 or 32 bits */ + + if (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) + { + InfoPtr->TimerResolution = 24; + } + else + { + InfoPtr->TimerResolution = 32; + } + + /* Clear the reserved fields */ + + InfoPtr->Reserved1 = 0; + InfoPtr->Reserved2 = 0; + + /* Current debug levels */ + + InfoPtr->DebugLayer = AcpiDbgLayer; + InfoPtr->DebugLevel = AcpiDbgLevel; + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetSystemInfo) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetStatistics + * + * PARAMETERS: Stats - Where the statistics are returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Get the contents of the various system counters + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetStatistics ( + ACPI_STATISTICS *Stats) +{ + ACPI_FUNCTION_TRACE (AcpiGetStatistics); + + + /* Parameter validation */ + + if (!Stats) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Various interrupt-based event counters */ + + Stats->SciCount = AcpiSciCount; + Stats->GpeCount = AcpiGpeCount; + + ACPI_MEMCPY (Stats->FixedEventCount, AcpiFixedEventCount, + sizeof (AcpiFixedEventCount)); + + + /* Other counters */ + + Stats->MethodCount = AcpiMethodCount; + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetStatistics) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInitializationHandler + * + * PARAMETERS: Handler - Callback procedure + * Function - Not (currently) used, see below + * + * RETURN: Status + * + * DESCRIPTION: Install an initialization handler + * + * TBD: When a second function is added, must save the Function also. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInitializationHandler ( + ACPI_INIT_HANDLER Handler, + UINT32 Function) +{ + + if (!Handler) + { + return (AE_BAD_PARAMETER); + } + + if (AcpiGbl_InitHandler) + { + return (AE_ALREADY_EXISTS); + } + + AcpiGbl_InitHandler = Handler; + return AE_OK; +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInitializationHandler) + + +/***************************************************************************** + * + * FUNCTION: AcpiPurgeCachedObjects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Empty all caches (delete the cached objects) + * + ****************************************************************************/ + +ACPI_STATUS +AcpiPurgeCachedObjects ( + void) +{ + ACPI_FUNCTION_TRACE (AcpiPurgeCachedObjects); + + (void) AcpiOsPurgeCache (AcpiGbl_StateCache); + (void) AcpiOsPurgeCache (AcpiGbl_OperandCache); + (void) AcpiOsPurgeCache (AcpiGbl_PsNodeCache); + (void) AcpiOsPurgeCache (AcpiGbl_PsNodeExtCache); + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiPurgeCachedObjects) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInterface + * + * PARAMETERS: InterfaceName - The interface to install + * + * RETURN: Status + * + * DESCRIPTION: Install an _OSI interface to the global list + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_STATUS Status; + ACPI_INTERFACE_INFO *InterfaceInfo; + + + /* Parameter validation */ + + if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + /* Check if the interface name is already in the global list */ + + InterfaceInfo = AcpiUtGetInterface (InterfaceName); + if (InterfaceInfo) + { + /* + * The interface already exists in the list. This is OK if the + * interface has been marked invalid -- just clear the bit. + */ + if (InterfaceInfo->Flags & ACPI_OSI_INVALID) + { + InterfaceInfo->Flags &= ~ACPI_OSI_INVALID; + Status = AE_OK; + } + else + { + Status = AE_ALREADY_EXISTS; + } + } + else + { + /* New interface name, install into the global list */ + + Status = AcpiUtInstallInterface (InterfaceName); + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInterface) + + +/***************************************************************************** + * + * FUNCTION: AcpiRemoveInterface + * + * PARAMETERS: InterfaceName - The interface to remove + * + * RETURN: Status + * + * DESCRIPTION: Remove an _OSI interface from the global list + * + ****************************************************************************/ + +ACPI_STATUS +AcpiRemoveInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + Status = AcpiUtRemoveInterface (InterfaceName); + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveInterface) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInterfaceHandler + * + * PARAMETERS: Handler - The _OSI interface handler to install + * NULL means "remove existing handler" + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the predefined _OSI ACPI method. + * invoked during execution of the internal implementation of + * _OSI. A NULL handler simply removes any existing handler. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInterfaceHandler ( + ACPI_INTERFACE_HANDLER Handler) +{ + ACPI_STATUS Status = AE_OK; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + if (Handler && AcpiGbl_InterfaceHandler) + { + Status = AE_ALREADY_EXISTS; + } + else + { + AcpiGbl_InterfaceHandler = Handler; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInterfaceHandler) + + +/***************************************************************************** + * + * FUNCTION: AcpiCheckAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - Start address + * Length - Length + * Warn - TRUE if warning on overlap desired + * + * RETURN: Count of the number of conflicts detected. + * + * DESCRIPTION: Check if the input address range overlaps any of the + * ASL operation region address ranges. + * + ****************************************************************************/ + +UINT32 +AcpiCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + ACPI_SIZE Length, + BOOLEAN Warn) +{ + UINT32 Overlaps; + ACPI_STATUS Status; + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (0); + } + + Overlaps = AcpiUtCheckAddressRange (SpaceId, Address, + (UINT32) Length, Warn); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Overlaps); +} + +ACPI_EXPORT_SYMBOL (AcpiCheckAddressRange) + +#endif /* !ACPI_ASL_COMPILER */ diff --git a/source/components/utilities/utxferror.c b/source/components/utilities/utxferror.c new file mode 100644 index 000000000000..8ffb27489497 --- /dev/null +++ b/source/components/utilities/utxferror.c @@ -0,0 +1,478 @@ +/******************************************************************************* + * + * Module Name: utxferror - Various error/warning output functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTXFERROR_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxferror") + +/* + * This module is used for the in-kernel ACPICA as well as the ACPICA + * tools/applications. + * + * For the iASL compiler case, the output is redirected to stderr so that + * any of the various ACPI errors and warnings do not appear in the output + * files, for either the compiler or disassembler portions of the tool. + */ +#ifdef ACPI_ASL_COMPILER +#include + +extern FILE *AcpiGbl_OutputFile; + +#define ACPI_MSG_REDIRECT_BEGIN \ + FILE *OutputFile = AcpiGbl_OutputFile; \ + AcpiOsRedirectOutput (stderr); + +#define ACPI_MSG_REDIRECT_END \ + AcpiOsRedirectOutput (OutputFile); + +#else +/* + * non-iASL case - no redirection, nothing to do + */ +#define ACPI_MSG_REDIRECT_BEGIN +#define ACPI_MSG_REDIRECT_END +#endif + +/* + * Common message prefixes + */ +#define ACPI_MSG_ERROR "ACPI Error: " +#define ACPI_MSG_EXCEPTION "ACPI Exception: " +#define ACPI_MSG_WARNING "ACPI Warning: " +#define ACPI_MSG_INFO "ACPI: " + +/* + * Common message suffix + */ +#define ACPI_MSG_SUFFIX \ + AcpiOsPrintf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, ModuleName, LineNumber) + + +/******************************************************************************* + * + * FUNCTION: AcpiError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Error" message with module/line/version info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiError) + + +/******************************************************************************* + * + * FUNCTION: AcpiException + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Status - Status to be formatted + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Exception" message with module/line/version info + * and decoded ACPI_STATUS. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_EXCEPTION "%s, ", AcpiFormatException (Status)); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiException) + + +/******************************************************************************* + * + * FUNCTION: AcpiWarning + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Warning" message with module/line/version info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_WARNING); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiWarning) + + +/******************************************************************************* + * + * FUNCTION: AcpiInfo + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print generic "ACPI:" information message. There is no + * module/line/version info in order to keep the message simple. + * + * TBD: ModuleName and LineNumber args are not needed, should be removed. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiInfo ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_INFO); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + AcpiOsPrintf ("\n"); + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiInfo) + + +/* + * The remainder of this module contains internal error functions that may + * be configured out. + */ +#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP) + +/******************************************************************************* + * + * FUNCTION: AcpiUtPredefinedWarning + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Pathname - Full pathname to the node + * NodeFlags - From Namespace node for the method/object + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Warnings for the predefined validation module. Messages are + * only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of error + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedWarning ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...) +{ + va_list ArgList; + + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (NodeFlags & ANOBJ_EVALUATED) + { + return; + } + + AcpiOsPrintf (ACPI_MSG_WARNING "For %s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPredefinedInfo + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Pathname - Full pathname to the node + * NodeFlags - From Namespace node for the method/object + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Info messages for the predefined validation module. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedInfo ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...) +{ + va_list ArgList; + + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (NodeFlags & ANOBJ_EVALUATED) + { + return; + } + + AcpiOsPrintf (ACPI_MSG_INFO "For %s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtNamespaceError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * InternalName - Name or path of the namespace node + * LookupStatus - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the NS node. + * + ******************************************************************************/ + +void +AcpiUtNamespaceError ( + const char *ModuleName, + UINT32 LineNumber, + const char *InternalName, + ACPI_STATUS LookupStatus) +{ + ACPI_STATUS Status; + UINT32 BadName; + char *Name = NULL; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + if (LookupStatus == AE_BAD_CHARACTER) + { + /* There is a non-ascii character in the name */ + + ACPI_MOVE_32_TO_32 (&BadName, ACPI_CAST_PTR (UINT32, InternalName)); + AcpiOsPrintf ("[0x%4.4X] (NON-ASCII)", BadName); + } + else + { + /* Convert path to external format */ + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, + InternalName, NULL, &Name); + + /* Print target name */ + + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf ("[%s]", Name); + } + else + { + AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]"); + } + + if (Name) + { + ACPI_FREE (Name); + } + } + + AcpiOsPrintf (" Namespace lookup failure, %s", + AcpiFormatException (LookupStatus)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMethodError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Message - Error message to use on failure + * PrefixNode - Prefix relative to the path + * Path - Path to the node (optional) + * MethodStatus - Execution status + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the method. + * + ******************************************************************************/ + +void +AcpiUtMethodError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Message, + ACPI_NAMESPACE_NODE *PrefixNode, + const char *Path, + ACPI_STATUS MethodStatus) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node = PrefixNode; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + if (Path) + { + Status = AcpiNsGetNode (PrefixNode, Path, ACPI_NS_NO_UPSEARCH, + &Node); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("[Could not get node by pathname]"); + } + } + + AcpiNsPrintNodePathname (Node, Message); + AcpiOsPrintf (", %s", AcpiFormatException (MethodStatus)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/source/components/utilities/utxfmutex.c b/source/components/utilities/utxfmutex.c new file mode 100644 index 000000000000..c4784310d3f8 --- /dev/null +++ b/source/components/utilities/utxfmutex.c @@ -0,0 +1,213 @@ +/******************************************************************************* + * + * Module Name: utxfmutex - external AML mutex access functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTXFMUTEX_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxfmutex") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtGetMutexObject ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OPERAND_OBJECT **RetObj); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetMutexObject + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * RetObj - Where the mutex object is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an AML mutex object. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetMutexObject ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OPERAND_OBJECT **RetObj) +{ + ACPI_NAMESPACE_NODE *MutexNode; + ACPI_OPERAND_OBJECT *MutexObj; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!RetObj || (!Handle && !Pathname)) + { + return (AE_BAD_PARAMETER); + } + + /* Get a the namespace node for the mutex */ + + MutexNode = Handle; + if (Pathname != NULL) + { + Status = AcpiGetHandle (Handle, Pathname, + ACPI_CAST_PTR (ACPI_HANDLE, &MutexNode)); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + /* Ensure that we actually have a Mutex object */ + + if (!MutexNode || + (MutexNode->Type != ACPI_TYPE_MUTEX)) + { + return (AE_TYPE); + } + + /* Get the low-level mutex object */ + + MutexObj = AcpiNsGetAttachedObject (MutexNode); + if (!MutexObj) + { + return (AE_NULL_OBJECT); + } + + *RetObj = MutexObj; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiAcquireMutex + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * Timeout - Max time to wait for the lock (millisec) + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex. This is a device driver interface to + * AML mutex objects, and allows for transaction locking between + * drivers and AML code. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiAcquireMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + UINT16 Timeout) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *MutexObj; + + + /* Get the low-level mutex associated with Handle:Pathname */ + + Status = AcpiUtGetMutexObject (Handle, Pathname, &MutexObj); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Acquire the OS mutex */ + + Status = AcpiOsAcquireMutex (MutexObj->Mutex.OsMutex, Timeout); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiReleaseMutex + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * + * RETURN: Status + * + * DESCRIPTION: Release an AML mutex. This is a device driver interface to + * AML mutex objects, and allows for transaction locking between + * drivers and AML code. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReleaseMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *MutexObj; + + + /* Get the low-level mutex associated with Handle:Pathname */ + + Status = AcpiUtGetMutexObject (Handle, Pathname, &MutexObj); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Release the OS mutex */ + + AcpiOsReleaseMutex (MutexObj->Mutex.OsMutex); + return (AE_OK); +} diff --git a/source/include/acapps.h b/source/include/acapps.h new file mode 100644 index 000000000000..0382ca85475c --- /dev/null +++ b/source/include/acapps.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * Module Name: acapps - common include for ACPI applications/tools + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACAPPS +#define _ACAPPS + + +#ifdef _MSC_VER /* disable some level-4 warnings */ +#pragma warning(disable:4100) /* warning C4100: unreferenced formal parameter */ +#endif + +/* Common info for tool signons */ + +#define ACPICA_NAME "Intel ACPI Component Architecture" +#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2012 Intel Corporation" + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_WIDTH "-64" + +#elif ACPI_MACHINE_WIDTH == 32 +#define ACPI_WIDTH "-32" + +#else +#error unknown ACPI_MACHINE_WIDTH +#define ACPI_WIDTH "-??" + +#endif + +/* Macros for signons and file headers */ + +#define ACPI_COMMON_SIGNON(UtilityName) \ + "\n%s\n%s version %8.8X%s [%s]\n%s\n\n", \ + ACPICA_NAME, \ + UtilityName, ((UINT32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + ACPICA_COPYRIGHT + +#define ACPI_COMMON_HEADER(UtilityName, Prefix) \ + "%s%s\n%s%s version %8.8X%s [%s]\n%s%s\n%s\n", \ + Prefix, ACPICA_NAME, \ + Prefix, UtilityName, ((UINT32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + Prefix, ACPICA_COPYRIGHT, \ + Prefix + +/* Macros for usage messages */ + +#define ACPI_USAGE_HEADER(Usage) \ + printf ("Usage: %s\nOptions:\n", Usage); + +#define ACPI_OPTION(Name, Description) \ + printf (" %-18s%s\n", Name, Description); + + +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define ACPI_TABLE_FILE_SUFFIX ".dat" + + +/* + * getopt + */ +int +AcpiGetopt( + int argc, + char **argv, + char *opts); + +extern int AcpiGbl_Optind; +extern int AcpiGbl_Opterr; +extern char *AcpiGbl_Optarg; + + +/* + * adisasm + */ +ACPI_STATUS +AdAmlDisassemble ( + BOOLEAN OutToFile, + char *Filename, + char *Prefix, + char **OutFilename, + BOOLEAN GetAllTables); + +void +AdPrintStatistics ( + void); + +ACPI_STATUS +AdFindDsdt( + UINT8 **DsdtPtr, + UINT32 *DsdtLength); + +void +AdDumpTables ( + void); + +ACPI_STATUS +AdGetLocalTables ( + char *Filename, + BOOLEAN GetAllTables); + +ACPI_STATUS +AdParseTable ( + ACPI_TABLE_HEADER *Table, + ACPI_OWNER_ID *OwnerId, + BOOLEAN LoadTable, + BOOLEAN External); + +ACPI_STATUS +AdDisplayTables ( + char *Filename, + ACPI_TABLE_HEADER *Table); + +ACPI_STATUS +AdDisplayStatistics ( + void); + + +/* + * adwalk + */ +void +AcpiDmCrossReferenceNamespace ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot, + ACPI_OWNER_ID OwnerId); + +void +AcpiDmDumpTree ( + ACPI_PARSE_OBJECT *Origin); + +void +AcpiDmFindOrphanMethods ( + ACPI_PARSE_OBJECT *Origin); + +void +AcpiDmFinishNamespaceLoad ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot, + ACPI_OWNER_ID OwnerId); + +void +AcpiDmConvertResourceIndexes ( + ACPI_PARSE_OBJECT *ParseTreeRoot, + ACPI_NAMESPACE_NODE *NamespaceRoot); + + +/* + * adfile + */ +ACPI_STATUS +AdInitialize ( + void); + +char * +FlGenerateFilename ( + char *InputFilename, + char *Suffix); + +ACPI_STATUS +FlSplitInputPathname ( + char *InputPath, + char **OutDirectoryPath, + char **OutFilename); + +char * +AdGenerateFilename ( + char *Prefix, + char *TableId); + +void +AdWriteTable ( + ACPI_TABLE_HEADER *Table, + UINT32 Length, + char *TableName, + char *OemTableId); + +#endif /* _ACAPPS */ + diff --git a/source/include/accommon.h b/source/include/accommon.h new file mode 100644 index 000000000000..7e6d05aa8d06 --- /dev/null +++ b/source/include/accommon.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * + * Name: accommon.h - Common include files for generation of ACPICA source + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACCOMMON_H__ +#define __ACCOMMON_H__ + +/* + * Common set of includes for all ACPICA source files. + * We put them here because we don't want to duplicate them + * in the the source code again and again. + * + * Note: The order of these include files is important. + */ +#include "acconfig.h" /* Global configuration constants */ +#include "acmacros.h" /* C macros */ +#include "aclocal.h" /* Internal data types */ +#include "acobject.h" /* ACPI internal object */ +#include "acstruct.h" /* Common structures */ +#include "acglobal.h" /* All global variables */ +#include "achware.h" /* Hardware defines and interfaces */ +#include "acutils.h" /* Utility interfaces */ + + +#endif /* __ACCOMMON_H__ */ diff --git a/source/include/acconfig.h b/source/include/acconfig.h new file mode 100644 index 000000000000..7880516e4755 --- /dev/null +++ b/source/include/acconfig.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * Name: acconfig.h - Global configuration constants + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACCONFIG_H +#define _ACCONFIG_H + + +/****************************************************************************** + * + * Configuration options + * + *****************************************************************************/ + +/* + * ACPI_DEBUG_OUTPUT - This switch enables all the debug facilities of the + * ACPI subsystem. This includes the DEBUG_PRINT output + * statements. When disabled, all DEBUG_PRINT + * statements are compiled out. + * + * ACPI_APPLICATION - Use this switch if the subsystem is going to be run + * at the application level. + * + */ + +/* + * OS name, used for the _OS object. The _OS object is essentially obsolete, + * but there is a large base of ASL/AML code in existing machines that check + * for the string below. The use of this string usually guarantees that + * the ASL will execute down the most tested code path. Also, there is some + * code that will not execute the _OSI method unless _OS matches the string + * below. Therefore, change this string at your own risk. + */ +#define ACPI_OS_NAME "Microsoft Windows NT" + +/* Maximum objects in the various object caches */ + +#define ACPI_MAX_STATE_CACHE_DEPTH 96 /* State objects */ +#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ +#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 96 /* Parse tree objects */ +#define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */ +#define ACPI_MAX_NAMESPACE_CACHE_DEPTH 96 /* Namespace objects */ + +/* + * Should the subsystem abort the loading of an ACPI table if the + * table checksum is incorrect? + */ +#define ACPI_CHECKSUM_ABORT FALSE + +/* + * Generate a version of ACPICA that only supports "reduced hardware" + * platforms (as defined in ACPI 5.0). Set to TRUE to generate a specialized + * version of ACPICA that ONLY supports the ACPI 5.0 "reduced hardware" + * model. In other words, no ACPI hardware is supported. + * + * If TRUE, this means no support for the following: + * PM Event and Control registers + * SCI interrupt (and handler) + * Fixed Events + * General Purpose Events (GPEs) + * Global Lock + * ACPI PM timer + * FACS table (Waking vectors and Global Lock) + */ +#define ACPI_REDUCED_HARDWARE FALSE + + +/****************************************************************************** + * + * Subsystem Constants + * + *****************************************************************************/ + +/* Version of ACPI supported */ + +#define ACPI_CA_SUPPORT_LEVEL 5 + +/* Maximum count for a semaphore object */ + +#define ACPI_MAX_SEMAPHORE_COUNT 256 + +/* Maximum object reference count (detects object deletion issues) */ + +#define ACPI_MAX_REFERENCE_COUNT 0x800 + +/* Default page size for use in mapping memory for operation regions */ + +#define ACPI_DEFAULT_PAGE_SIZE 4096 /* Must be power of 2 */ + +/* OwnerId tracking. 8 entries allows for 255 OwnerIds */ + +#define ACPI_NUM_OWNERID_MASKS 8 + +/* Size of the root table array is increased by this increment */ + +#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 + +/* Maximum number of While() loop iterations before forced abort */ + +#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF + +/* Maximum sleep allowed via Sleep() operator */ + +#define ACPI_MAX_SLEEP 2000 /* 2000 millisec == two seconds */ + +/* Address Range lists are per-SpaceId (Memory and I/O only) */ + +#define ACPI_ADDRESS_RANGE_MAX 2 + + +/****************************************************************************** + * + * ACPI Specification constants (Do not change unless the specification changes) + * + *****************************************************************************/ + +/* Method info (in WALK_STATE), containing local variables and argumetns */ + +#define ACPI_METHOD_NUM_LOCALS 8 +#define ACPI_METHOD_MAX_LOCAL 7 + +#define ACPI_METHOD_NUM_ARGS 7 +#define ACPI_METHOD_MAX_ARG 6 + +/* + * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG + */ +#define ACPI_OBJ_NUM_OPERANDS 8 +#define ACPI_OBJ_MAX_OPERAND 7 + +/* Number of elements in the Result Stack frame, can be an arbitrary value */ + +#define ACPI_RESULTS_FRAME_OBJ_NUM 8 + +/* + * Maximal number of elements the Result Stack can contain, + * it may be an arbitray value not exceeding the types of + * ResultSize and ResultCount (now UINT8). + */ +#define ACPI_RESULTS_OBJ_NUM_MAX 255 + +/* Constants used in searching for the RSDP in low memory */ + +#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ +#define ACPI_EBDA_PTR_LENGTH 2 +#define ACPI_EBDA_WINDOW_SIZE 1024 +#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */ +#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000 +#define ACPI_RSDP_SCAN_STEP 16 + +/* Operation regions */ + +#define ACPI_USER_REGION_BEGIN 0x80 + +/* Maximum SpaceIds for Operation Regions */ + +#define ACPI_MAX_ADDRESS_SPACE 255 + +/* Array sizes. Used for range checking also */ + +#define ACPI_MAX_MATCH_OPCODE 5 + +/* RSDP checksums */ + +#define ACPI_RSDP_CHECKSUM_LENGTH 20 +#define ACPI_RSDP_XCHECKSUM_LENGTH 36 + +/* SMBus, GSBus and IPMI bidirectional buffer size */ + +#define ACPI_SMBUS_BUFFER_SIZE 34 +#define ACPI_GSBUS_BUFFER_SIZE 34 +#define ACPI_IPMI_BUFFER_SIZE 66 + +/* _SxD and _SxW control methods */ + +#define ACPI_NUM_SxD_METHODS 4 +#define ACPI_NUM_SxW_METHODS 5 + + +/****************************************************************************** + * + * ACPI AML Debugger + * + *****************************************************************************/ + +#define ACPI_DEBUGGER_MAX_ARGS ACPI_METHOD_NUM_ARGS + 2 /* Max command line arguments */ +#define ACPI_DB_LINE_BUFFER_SIZE 512 + +#define ACPI_DEBUGGER_COMMAND_PROMPT '-' +#define ACPI_DEBUGGER_EXECUTE_PROMPT '%' + + +#endif /* _ACCONFIG_H */ + diff --git a/source/include/acdebug.h b/source/include/acdebug.h new file mode 100644 index 000000000000..bcc505c8d511 --- /dev/null +++ b/source/include/acdebug.h @@ -0,0 +1,412 @@ +/****************************************************************************** + * + * Name: acdebug.h - ACPI/AML debugger + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACDEBUG_H__ +#define __ACDEBUG_H__ + + +#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ + +typedef struct CommandInfo +{ + char *Name; /* Command Name */ + UINT8 MinArgs; /* Minimum arguments required */ + +} COMMAND_INFO; + +typedef struct ArgumentInfo +{ + char *Name; /* Argument Name */ + +} ARGUMENT_INFO; + +typedef struct acpi_execute_walk +{ + UINT32 Count; + UINT32 MaxCount; + +} ACPI_EXECUTE_WALK; + + +#define PARAM_LIST(pl) pl +#define DBTEST_OUTPUT_LEVEL(lvl) if (AcpiGbl_DbOpt_verbose) +#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ + AcpiOsPrintf PARAM_LIST(fp);} + +#define EX_NO_SINGLE_STEP 1 +#define EX_SINGLE_STEP 2 + + +/* + * dbxface - external debugger interfaces + */ +ACPI_STATUS +AcpiDbInitialize ( + void); + +void +AcpiDbTerminate ( + void); + +ACPI_STATUS +AcpiDbSingleStep ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 OpType); + + +/* + * dbcmds - debug commands and output routines + */ +ACPI_NAMESPACE_NODE * +AcpiDbConvertToNode ( + char *InString); + +void +AcpiDbDisplayTableInfo ( + char *TableArg); + +void +AcpiDbDisplayTemplate ( + char *BufferArg); + +void +AcpiDbUnloadAcpiTable ( + char *TableArg, + char *InstanceArg); + +void +AcpiDbSendNotify ( + char *Name, + UINT32 Value); + +void +AcpiDbDisplayInterfaces ( + char *ActionArg, + char *InterfaceNameArg); + +ACPI_STATUS +AcpiDbSleep ( + char *ObjectArg); + +void +AcpiDbDisplayLocks ( + void); + +void +AcpiDbDisplayResources ( + char *ObjectArg); + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiDbDisplayGpes ( + void)) + +void +AcpiDbDisplayHandlers ( + void); + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiDbGenerateGpe ( + char *GpeArg, + char *BlockArg)) + + +/* + * dbmethod - control method commands + */ +void +AcpiDbSetMethodBreakpoint ( + char *Location, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDbSetMethodCallBreakpoint ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDbSetMethodData ( + char *TypeArg, + char *IndexArg, + char *ValueArg); + +ACPI_STATUS +AcpiDbDisassembleMethod ( + char *Name); + +void +AcpiDbDisassembleAml ( + char *Statements, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDbBatchExecute ( + char *CountArg); + + +/* + * dbnames - namespace commands + */ +void +AcpiDbSetScope ( + char *Name); + +void +AcpiDbDumpNamespace ( + char *StartArg, + char *DepthArg); + +void +AcpiDbDumpNamespaceByOwner ( + char *OwnerArg, + char *DepthArg); + +ACPI_STATUS +AcpiDbFindNameInNamespace ( + char *NameArg); + +void +AcpiDbCheckPredefinedNames ( + void); + +ACPI_STATUS +AcpiDbDisplayObjects ( + char *ObjTypeArg, + char *DisplayCountArg); + +void +AcpiDbCheckIntegrity ( + void); + +void +AcpiDbFindReferences ( + char *ObjectArg); + +void +AcpiDbGetBusInfo ( + void); + + +/* + * dbdisply - debug display commands + */ +void +AcpiDbDisplayMethodInfo ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDbDecodeAndDisplayObject ( + char *Target, + char *OutputType); + +void +AcpiDbDisplayResultObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDbDisplayAllMethods ( + char *DisplayCountArg); + +void +AcpiDbDisplayArguments ( + void); + +void +AcpiDbDisplayLocals ( + void); + +void +AcpiDbDisplayResults ( + void); + +void +AcpiDbDisplayCallingTree ( + void); + +void +AcpiDbDisplayObjectType ( + char *ObjectArg); + +void +AcpiDbDisplayArgumentObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + + +/* + * dbexec - debugger control method execution + */ +void +AcpiDbExecute ( + char *Name, + char **Args, + ACPI_OBJECT_TYPE *Types, + UINT32 Flags); + +void +AcpiDbCreateExecutionThreads ( + char *NumThreadsArg, + char *NumLoopsArg, + char *MethodNameArg); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +UINT32 +AcpiDbGetCacheInfo ( + ACPI_MEMORY_LIST *Cache); +#endif + + +/* + * dbfileio - Debugger file I/O commands + */ +ACPI_OBJECT_TYPE +AcpiDbMatchArgument ( + char *UserArgument, + ARGUMENT_INFO *Arguments); + +void +AcpiDbCloseDebugFile ( + void); + +void +AcpiDbOpenDebugFile ( + char *Name); + +ACPI_STATUS +AcpiDbLoadAcpiTable ( + char *Filename); + +ACPI_STATUS +AcpiDbGetTableFromFile ( + char *Filename, + ACPI_TABLE_HEADER **Table); + +ACPI_STATUS +AcpiDbReadTableFromFile ( + char *Filename, + ACPI_TABLE_HEADER **Table); + + +/* + * dbhistry - debugger HISTORY command + */ +void +AcpiDbAddToHistory ( + char *CommandLine); + +void +AcpiDbDisplayHistory ( + void); + +char * +AcpiDbGetFromHistory ( + char *CommandNumArg); + + +/* + * dbinput - user front-end to the AML debugger + */ +ACPI_STATUS +AcpiDbCommandDispatch ( + char *InputBuffer, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +void ACPI_SYSTEM_XFACE +AcpiDbExecuteThread ( + void *Context); + +ACPI_STATUS +AcpiDbUserCommands ( + char Prompt, + ACPI_PARSE_OBJECT *Op); + +char * +AcpiDbGetNextToken ( + char *String, + char **Next, + ACPI_OBJECT_TYPE *ReturnType); + + +/* + * dbstats - Generation and display of ACPI table statistics + */ +void +AcpiDbGenerateStatistics ( + ACPI_PARSE_OBJECT *Root, + BOOLEAN IsMethod); + +ACPI_STATUS +AcpiDbDisplayStatistics ( + char *TypeArg); + + +/* + * dbutils - AML debugger utilities + */ +void +AcpiDbSetOutputDestination ( + UINT32 Where); + +void +AcpiDbDumpExternalObject ( + ACPI_OBJECT *ObjDesc, + UINT32 Level); + +void +AcpiDbPrepNamestring ( + char *Name); + +ACPI_NAMESPACE_NODE * +AcpiDbLocalNsLookup ( + char *Name); + +void +AcpiDbUInt32ToHexString ( + UINT32 Value, + char *Buffer); + +#endif /* __ACDEBUG_H__ */ diff --git a/source/include/acdisasm.h b/source/include/acdisasm.h new file mode 100644 index 000000000000..9ec12713b499 --- /dev/null +++ b/source/include/acdisasm.h @@ -0,0 +1,864 @@ +/****************************************************************************** + * + * Name: acdisasm.h - AML disassembler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACDISASM_H__ +#define __ACDISASM_H__ + +#include "amlresrc.h" + + +#define BLOCK_NONE 0 +#define BLOCK_PAREN 1 +#define BLOCK_BRACE 2 +#define BLOCK_COMMA_LIST 4 +#define ACPI_DEFAULT_RESNAME *(UINT32 *) "__RD" + +/* + * Raw table data header. Used by disassembler and data table compiler. + * Do not change. + */ +#define ACPI_RAW_TABLE_DATA_HEADER "Raw Table Data" + + +typedef const struct acpi_dmtable_info +{ + UINT8 Opcode; + UINT16 Offset; + char *Name; + UINT8 Flags; + +} ACPI_DMTABLE_INFO; + +#define DT_LENGTH 0x01 /* Field is a subtable length */ +#define DT_FLAG 0x02 /* Field is a flag value */ +#define DT_NON_ZERO 0x04 /* Field must be non-zero */ + +/* TBD: Not used at this time */ + +#define DT_OPTIONAL 0x08 +#define DT_COUNT 0x10 + +/* + * Values for Opcode above. + * Note: 0-7 must not change, they are used as a flag shift value. Other + * than those, new values can be added wherever appropriate. + */ +typedef enum +{ + /* Simple Data Types */ + + ACPI_DMT_FLAG0 = 0, + ACPI_DMT_FLAG1 = 1, + ACPI_DMT_FLAG2 = 2, + ACPI_DMT_FLAG3 = 3, + ACPI_DMT_FLAG4 = 4, + ACPI_DMT_FLAG5 = 5, + ACPI_DMT_FLAG6 = 6, + ACPI_DMT_FLAG7 = 7, + ACPI_DMT_FLAGS0, + ACPI_DMT_FLAGS1, + ACPI_DMT_FLAGS2, + ACPI_DMT_FLAGS4, + ACPI_DMT_UINT8, + ACPI_DMT_UINT16, + ACPI_DMT_UINT24, + ACPI_DMT_UINT32, + ACPI_DMT_UINT40, + ACPI_DMT_UINT48, + ACPI_DMT_UINT56, + ACPI_DMT_UINT64, + ACPI_DMT_BUF7, + ACPI_DMT_BUF16, + ACPI_DMT_BUF128, + ACPI_DMT_SIG, + ACPI_DMT_STRING, + ACPI_DMT_NAME4, + ACPI_DMT_NAME6, + ACPI_DMT_NAME8, + + /* Types that are decoded to strings and miscellaneous */ + + ACPI_DMT_ACCWIDTH, + ACPI_DMT_CHKSUM, + ACPI_DMT_GAS, + ACPI_DMT_SPACEID, + ACPI_DMT_UNICODE, + ACPI_DMT_UUID, + + /* Types used only for the Data Table Compiler */ + + ACPI_DMT_BUFFER, + ACPI_DMT_DEVICE_PATH, + ACPI_DMT_LABEL, + ACPI_DMT_PCI_PATH, + + /* Types that are specific to particular ACPI tables */ + + ACPI_DMT_ASF, + ACPI_DMT_DMAR, + ACPI_DMT_EINJACT, + ACPI_DMT_EINJINST, + ACPI_DMT_ERSTACT, + ACPI_DMT_ERSTINST, + ACPI_DMT_FADTPM, + ACPI_DMT_HEST, + ACPI_DMT_HESTNTFY, + ACPI_DMT_HESTNTYP, + ACPI_DMT_IVRS, + ACPI_DMT_MADT, + ACPI_DMT_PMTT, + ACPI_DMT_SLIC, + ACPI_DMT_SRAT, + + /* Special opcodes */ + + ACPI_DMT_EXTRA_TEXT, + ACPI_DMT_EXIT + +} ACPI_ENTRY_TYPES; + +typedef +void (*ACPI_DMTABLE_HANDLER) ( + ACPI_TABLE_HEADER *Table); + +typedef +ACPI_STATUS (*ACPI_CMTABLE_HANDLER) ( + void **PFieldList); + +typedef struct acpi_dmtable_data +{ + char *Signature; + ACPI_DMTABLE_INFO *TableInfo; + ACPI_DMTABLE_HANDLER TableHandler; + ACPI_CMTABLE_HANDLER CmTableHandler; + const unsigned char *Template; + char *Name; + +} ACPI_DMTABLE_DATA; + + +typedef struct acpi_op_walk_info +{ + UINT32 Level; + UINT32 LastLevel; + UINT32 Count; + UINT32 BitOffset; + UINT32 Flags; + ACPI_WALK_STATE *WalkState; + +} ACPI_OP_WALK_INFO; + +/* + * TBD - another copy of this is in asltypes.h, fix + */ +#ifndef ASL_WALK_CALLBACK_DEFINED +typedef +ACPI_STATUS (*ASL_WALK_CALLBACK) ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level, + void *Context); +#define ASL_WALK_CALLBACK_DEFINED +#endif + +typedef +void (*ACPI_RESOURCE_HANDLER) ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +typedef struct acpi_resource_tag +{ + UINT32 BitIndex; + char *Tag; + +} ACPI_RESOURCE_TAG; + +/* Strings used for decoding flags to ASL keywords */ + +extern const char *AcpiGbl_WordDecode[]; +extern const char *AcpiGbl_IrqDecode[]; +extern const char *AcpiGbl_LockRule[]; +extern const char *AcpiGbl_AccessTypes[]; +extern const char *AcpiGbl_UpdateRules[]; +extern const char *AcpiGbl_MatchOps[]; + +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf2a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsf4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsfHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBoot[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBert[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBgrt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbgp[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmarHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmarScope[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEcdt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErst[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErst0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFacs[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFadt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFadt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFadt3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFadt5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFpdt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFpdtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFpdt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoFpdt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGas[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGtdt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHeader[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest7[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest8[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest9[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHestNotify[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHestBank[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHpet[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8c[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt7[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt8[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt9[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt10[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt11[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt12[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMchi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0A[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst0B[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmttHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRsdp1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRsdp2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoS3ptHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoS3pt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSbst[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSlicHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSlic0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSlic1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSlit[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSpcr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSpmi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSratHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWaet[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWddt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdrt[]; + +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGeneric[][2]; + + +/* + * dmtable + */ +extern ACPI_DMTABLE_DATA AcpiDmTableData[]; + +UINT8 +AcpiDmGenerateChecksum ( + void *Table, + UINT32 Length, + UINT8 OriginalChecksum); + +ACPI_DMTABLE_DATA * +AcpiDmGetTableData ( + char *Signature); + +void +AcpiDmDumpDataTable ( + ACPI_TABLE_HEADER *Table); + +ACPI_STATUS +AcpiDmDumpTable ( + UINT32 TableLength, + UINT32 TableOffset, + void *Table, + UINT32 SubTableLength, + ACPI_DMTABLE_INFO *Info); + +void +AcpiDmLineHeader ( + UINT32 Offset, + UINT32 ByteLength, + char *Name); + +void +AcpiDmLineHeader2 ( + UINT32 Offset, + UINT32 ByteLength, + char *Name, + UINT32 Value); + + +/* + * dmtbdump + */ +void +AcpiDmDumpAsf ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCpep ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpDmar ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpEinj ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpErst ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpFadt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpFpdt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpHest ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpIvrs ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMadt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMcfg ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMpst ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMsct ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPcct ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPmtt ( + ACPI_TABLE_HEADER *Table); + +UINT32 +AcpiDmDumpRsdp ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRsdt ( + ACPI_TABLE_HEADER *Table); + +UINT32 +AcpiDmDumpS3pt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSlic ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSlit ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSrat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpWdat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpXsdt ( + ACPI_TABLE_HEADER *Table); + + +/* + * dmwalk + */ +void +AcpiDmDisassemble ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Origin, + UINT32 NumOpcodes); + +void +AcpiDmWalkParseTree ( + ACPI_PARSE_OBJECT *Op, + ASL_WALK_CALLBACK DescendingCallback, + ASL_WALK_CALLBACK AscendingCallback, + void *Context); + + +/* + * dmopcode + */ +void +AcpiDmDisassembleOneOp ( + ACPI_WALK_STATE *WalkState, + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmDecodeInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +UINT32 +AcpiDmListType ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmMethodFlags ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmFieldFlags ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmAddressSpace ( + UINT8 SpaceId); + +void +AcpiDmRegionFlags ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmMatchOp ( + ACPI_PARSE_OBJECT *Op); + + +/* + * dmnames + */ +UINT32 +AcpiDmDumpName ( + UINT32 Name); + +ACPI_STATUS +AcpiPsDisplayObjectPathname ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmNamestring ( + char *Name); + + +/* + * dmobject + */ +void +AcpiDmDisplayInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiDmDisplayArguments ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDmDisplayLocals ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDmDumpMethodInfo ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + + +/* + * dmbuffer + */ +void +AcpiDmDisasmByteList ( + UINT32 Level, + UINT8 *ByteData, + UINT32 ByteCount); + +void +AcpiDmByteList ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmIsEisaId ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmEisaId ( + UINT32 EncodedId); + +BOOLEAN +AcpiDmIsUnicodeBuffer ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiDmIsStringBuffer ( + ACPI_PARSE_OBJECT *Op); + + +/* + * dmextern + */ + +ACPI_STATUS +AcpiDmAddToExternalFileList ( + char *PathList); + +void +AcpiDmClearExternalFileList ( + void); + +void +AcpiDmAddToExternalList ( + ACPI_PARSE_OBJECT *Op, + char *Path, + UINT8 Type, + UINT32 Value); + +void +AcpiDmAddExternalsToNamespace ( + void); + +UINT32 +AcpiDmGetExternalMethodCount ( + void); + +void +AcpiDmClearExternalList ( + void); + +void +AcpiDmEmitExternals ( + void); + + +/* + * dmresrc + */ +void +AcpiDmDumpInteger8 ( + UINT8 Value, + char *Name); + +void +AcpiDmDumpInteger16 ( + UINT16 Value, + char *Name); + +void +AcpiDmDumpInteger32 ( + UINT32 Value, + char *Name); + +void +AcpiDmDumpInteger64 ( + UINT64 Value, + char *Name); + +void +AcpiDmResourceTemplate ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op, + UINT8 *ByteData, + UINT32 ByteCount); + +ACPI_STATUS +AcpiDmIsResourceTemplate ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmBitList ( + UINT16 Mask); + +void +AcpiDmDescriptorName ( + void); + + +/* + * dmresrcl + */ +void +AcpiDmWordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmDwordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmExtendedDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmQwordDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmMemory24Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmMemory32Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedMemory32Descriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmGenericRegisterDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmInterruptDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorLargeDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmGpioDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmSerialBusDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorCommon ( + char *Name, + UINT8 *ByteData, + UINT32 Length, + UINT32 Level); + + +/* + * dmresrcs + */ +void +AcpiDmIrqDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmDmaDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedDmaDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmIoDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedIoDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmStartDependentDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmEndDependentDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorSmallDescriptor ( + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + + +/* + * dmutils + */ +void +AcpiDmDecodeAttribute ( + UINT8 Attribute); + +void +AcpiDmIndent ( + UINT32 Level); + +BOOLEAN +AcpiDmCommaIfListMember ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmCommaIfFieldMember ( + ACPI_PARSE_OBJECT *Op); + + +/* + * dmrestag + */ +void +AcpiDmFindResources ( + ACPI_PARSE_OBJECT *Root); + +void +AcpiDmCheckResourceReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + + +/* + * acdisasm + */ +void +AdDisassemblerHeader ( + char *Filename); + + +#endif /* __ACDISASM_H__ */ diff --git a/source/include/acdispat.h b/source/include/acdispat.h new file mode 100644 index 000000000000..0699ee77a1af --- /dev/null +++ b/source/include/acdispat.h @@ -0,0 +1,463 @@ +/****************************************************************************** + * + * Name: acdispat.h - dispatcher (parser to interpreter interface) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef _ACDISPAT_H_ +#define _ACDISPAT_H_ + + +#define NAMEOF_LOCAL_NTE "__L0" +#define NAMEOF_ARG_NTE "__A0" + + +/* + * dsargs - execution of dynamic arguments for static objects + */ +ACPI_STATUS +AcpiDsGetBufferFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiDsGetBankFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiDsGetRegionArguments ( + ACPI_OPERAND_OBJECT *RgnDesc); + +ACPI_STATUS +AcpiDsGetBufferArguments ( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiDsGetPackageArguments ( + ACPI_OPERAND_OBJECT *ObjDesc); + + +/* + * dscontrol - support for execution control opcodes + */ +ACPI_STATUS +AcpiDsExecBeginControlOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsExecEndControlOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + + +/* + * dsopcode - support for late operand evaluation + */ +ACPI_STATUS +AcpiDsEvalBufferFieldOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsEvalRegionOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsEvalTableRegionOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsEvalDataObjectOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiDsEvalBankFieldOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsInitializeRegion ( + ACPI_HANDLE ObjHandle); + + +/* + * dsexec - Parser/Interpreter interface, method execution callbacks + */ +ACPI_STATUS +AcpiDsGetPredicateValue ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ResultObj); + +ACPI_STATUS +AcpiDsExecBeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp); + +ACPI_STATUS +AcpiDsExecEndOp ( + ACPI_WALK_STATE *State); + + +/* + * dsfield - Parser/Interpreter interface for AML fields + */ +ACPI_STATUS +AcpiDsCreateField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsCreateBankField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsCreateIndexField ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *RegionNode, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsCreateBufferField ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsInitFieldObjects ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + + +/* + * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks + */ +ACPI_STATUS +AcpiDsInitCallbacks ( + ACPI_WALK_STATE *WalkState, + UINT32 PassNumber); + +ACPI_STATUS +AcpiDsLoad1BeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp); + +ACPI_STATUS +AcpiDsLoad1EndOp ( + ACPI_WALK_STATE *WalkState); + + +/* + * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks + */ +ACPI_STATUS +AcpiDsLoad2BeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp); + +ACPI_STATUS +AcpiDsLoad2EndOp ( + ACPI_WALK_STATE *WalkState); + + +/* + * dsmthdat - method data (locals/args) + */ +ACPI_STATUS +AcpiDsStoreObjectToLocal ( + UINT8 Type, + UINT32 Index, + ACPI_OPERAND_OBJECT *SrcDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsMethodDataGetEntry ( + UINT16 Opcode, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT ***Node); + +void +AcpiDsMethodDataDeleteAll ( + ACPI_WALK_STATE *WalkState); + +BOOLEAN +AcpiDsIsMethodValue ( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiDsMethodDataGetValue ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **DestDesc); + +ACPI_STATUS +AcpiDsMethodDataInitArgs ( + ACPI_OPERAND_OBJECT **Params, + UINT32 MaxParamCount, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsMethodDataGetNode ( + UINT8 Type, + UINT32 Index, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **Node); + +void +AcpiDsMethodDataInit ( + ACPI_WALK_STATE *WalkState); + + +/* + * dsmethod - Parser/Interpreter interface - control method parsing + */ +ACPI_STATUS +AcpiDsParseMethod ( + ACPI_NAMESPACE_NODE *Node); + +ACPI_STATUS +AcpiDsCallControlMethod ( + ACPI_THREAD_STATE *Thread, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiDsRestartControlMethod ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ReturnDesc); + +void +AcpiDsTerminateControlMethod ( + ACPI_OPERAND_OBJECT *MethodDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsBeginMethodExecution ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState); + +/* + * dsinit + */ +ACPI_STATUS +AcpiDsInitializeObjects ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode); + + +/* + * dsobject - Parser/Interpreter interface - object initialization and conversion + */ +ACPI_STATUS +AcpiDsBuildInternalBufferObj ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 BufferLength, + ACPI_OPERAND_OBJECT **ObjDescPtr); + +ACPI_STATUS +AcpiDsBuildInternalPackageObj ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *op, + UINT32 PackageLength, + ACPI_OPERAND_OBJECT **ObjDesc); + +ACPI_STATUS +AcpiDsInitObjectFromOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT16 Opcode, + ACPI_OPERAND_OBJECT **ObjDesc); + +ACPI_STATUS +AcpiDsCreateNode ( + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *Node, + ACPI_PARSE_OBJECT *Op); + + +/* + * dsutils - Parser/Interpreter interface utility routines + */ +void +AcpiDsClearImplicitReturn ( + ACPI_WALK_STATE *WalkState); + +BOOLEAN +AcpiDsDoImplicitReturn ( + ACPI_OPERAND_OBJECT *ReturnDesc, + ACPI_WALK_STATE *WalkState, + BOOLEAN AddReference); + +BOOLEAN +AcpiDsIsResultUsed ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +void +AcpiDsDeleteResultIfNotUsed ( + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT *ResultObj, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsCreateOperand ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Arg, + UINT32 ArgsRemaining); + +ACPI_STATUS +AcpiDsCreateOperands ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *FirstArg); + +ACPI_STATUS +AcpiDsResolveOperands ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDsClearOperands ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsEvaluateNamePath ( + ACPI_WALK_STATE *WalkState); + + +/* + * dswscope - Scope Stack manipulation + */ +ACPI_STATUS +AcpiDsScopeStackPush ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type, + ACPI_WALK_STATE *WalkState); + + +ACPI_STATUS +AcpiDsScopeStackPop ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDsScopeStackClear ( + ACPI_WALK_STATE *WalkState); + + +/* + * dswstate - parser WALK_STATE management routines + */ +ACPI_STATUS +AcpiDsObjStackPush ( + void *Object, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsObjStackPop ( + UINT32 PopCount, + ACPI_WALK_STATE *WalkState); + +ACPI_WALK_STATE * +AcpiDsCreateWalkState ( + ACPI_OWNER_ID OwnerId, + ACPI_PARSE_OBJECT *Origin, + ACPI_OPERAND_OBJECT *MthDesc, + ACPI_THREAD_STATE *Thread); + +ACPI_STATUS +AcpiDsInitAmlWalk ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *MethodNode, + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_EVALUATE_INFO *Info, + UINT8 PassNumber); + +void +AcpiDsObjStackPopAndDelete ( + UINT32 PopCount, + ACPI_WALK_STATE *WalkState); + +void +AcpiDsDeleteWalkState ( + ACPI_WALK_STATE *WalkState); + +ACPI_WALK_STATE * +AcpiDsPopWalkState ( + ACPI_THREAD_STATE *Thread); + +void +AcpiDsPushWalkState ( + ACPI_WALK_STATE *WalkState, + ACPI_THREAD_STATE *Thread); + +ACPI_STATUS +AcpiDsResultStackClear ( + ACPI_WALK_STATE *WalkState); + +ACPI_WALK_STATE * +AcpiDsGetCurrentWalkState ( + ACPI_THREAD_STATE *Thread); + +ACPI_STATUS +AcpiDsResultPop ( + ACPI_OPERAND_OBJECT **Object, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiDsResultPush ( + ACPI_OPERAND_OBJECT *Object, + ACPI_WALK_STATE *WalkState); + +#endif /* _ACDISPAT_H_ */ diff --git a/source/include/acevents.h b/source/include/acevents.h new file mode 100644 index 000000000000..3b874f10759e --- /dev/null +++ b/source/include/acevents.h @@ -0,0 +1,347 @@ +/****************************************************************************** + * + * Name: acevents.h - Event subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACEVENTS_H__ +#define __ACEVENTS_H__ + + +/* + * evevent + */ +ACPI_STATUS +AcpiEvInitializeEvents ( + void); + +ACPI_STATUS +AcpiEvInstallXruptHandlers ( + void); + +UINT32 +AcpiEvFixedEventDetect ( + void); + + +/* + * evmisc + */ +BOOLEAN +AcpiEvIsNotifyObject ( + ACPI_NAMESPACE_NODE *Node); + +UINT32 +AcpiEvGetGpeNumberIndex ( + UINT32 GpeNumber); + +ACPI_STATUS +AcpiEvQueueNotifyRequest ( + ACPI_NAMESPACE_NODE *Node, + UINT32 NotifyValue); + + +/* + * evglock - Global Lock support + */ +ACPI_STATUS +AcpiEvInitGlobalLockHandler ( + void); + +ACPI_HW_DEPENDENT_RETURN_OK ( +ACPI_STATUS +AcpiEvAcquireGlobalLock( + UINT16 Timeout)) + +ACPI_HW_DEPENDENT_RETURN_OK ( +ACPI_STATUS +AcpiEvReleaseGlobalLock( + void)) + +ACPI_STATUS +AcpiEvRemoveGlobalLockHandler ( + void); + + +/* + * evgpe - Low-level GPE support + */ +UINT32 +AcpiEvGpeDetect ( + ACPI_GPE_XRUPT_INFO *GpeXruptList); + +ACPI_STATUS +AcpiEvUpdateGpeEnableMask ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_STATUS +AcpiEvEnableGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_STATUS +AcpiEvAddGpeReference ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_STATUS +AcpiEvRemoveGpeReference ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_GPE_EVENT_INFO * +AcpiEvGetGpeEventInfo ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber); + +ACPI_GPE_EVENT_INFO * +AcpiEvLowGetGpeInfo ( + UINT32 GpeNumber, + ACPI_GPE_BLOCK_INFO *GpeBlock); + +ACPI_STATUS +AcpiEvFinishGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + + +/* + * evgpeblk - Upper-level GPE block support + */ +ACPI_STATUS +AcpiEvCreateGpeBlock ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GENERIC_ADDRESS *GpeBlockAddress, + UINT32 RegisterCount, + UINT8 GpeBlockBaseNumber, + UINT32 InterruptNumber, + ACPI_GPE_BLOCK_INFO **ReturnGpeBlock); + +ACPI_STATUS +AcpiEvInitializeGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + +ACPI_HW_DEPENDENT_RETURN_OK ( +ACPI_STATUS +AcpiEvDeleteGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock)) + +UINT32 +AcpiEvGpeDispatch ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 GpeNumber); + +/* + * evgpeinit - GPE initialization and update + */ +ACPI_STATUS +AcpiEvGpeInitialize ( + void); + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiEvUpdateGpes ( + ACPI_OWNER_ID TableOwnerId)) + +ACPI_STATUS +AcpiEvMatchGpeMethod ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +/* + * evgpeutil - GPE utilities + */ +ACPI_STATUS +AcpiEvWalkGpeList ( + ACPI_GPE_CALLBACK GpeWalkCallback, + void *Context); + +BOOLEAN +AcpiEvValidGpeEvent ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_STATUS +AcpiEvGetGpeDevice ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + +ACPI_GPE_XRUPT_INFO * +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber); + +ACPI_STATUS +AcpiEvDeleteGpeXrupt ( + ACPI_GPE_XRUPT_INFO *GpeXrupt); + +ACPI_STATUS +AcpiEvDeleteGpeHandlers ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + + +/* + * evregion - Address Space handling + */ +ACPI_STATUS +AcpiEvInstallRegionHandlers ( + void); + +ACPI_STATUS +AcpiEvInitializeOpRegions ( + void); + +ACPI_STATUS +AcpiEvAddressSpaceDispatch ( + ACPI_OPERAND_OBJECT *RegionObj, + ACPI_OPERAND_OBJECT *FieldObj, + UINT32 Function, + UINT32 RegionOffset, + UINT32 BitWidth, + UINT64 *Value); + +ACPI_STATUS +AcpiEvAttachRegion ( + ACPI_OPERAND_OBJECT *HandlerObj, + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsIsLocked); + +void +AcpiEvDetachRegion ( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsIsLocked); + +ACPI_STATUS +AcpiEvInstallSpaceHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context); + +ACPI_STATUS +AcpiEvExecuteRegMethods ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId); + +ACPI_STATUS +AcpiEvExecuteRegMethod ( + ACPI_OPERAND_OBJECT *RegionObj, + UINT32 Function); + + +/* + * evregini - Region initialization and setup + */ +ACPI_STATUS +AcpiEvSystemMemoryRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvIoSpaceRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvPciConfigRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvCmosRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvPciBarRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvDefaultRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +ACPI_STATUS +AcpiEvInitializeRegion ( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsLocked); + + +/* + * evsci - SCI (System Control Interrupt) handling/dispatch + */ +UINT32 ACPI_SYSTEM_XFACE +AcpiEvGpeXruptHandler ( + void *Context); + +UINT32 +AcpiEvInstallSciHandler ( + void); + +ACPI_STATUS +AcpiEvRemoveSciHandler ( + void); + +UINT32 +AcpiEvInitializeSCI ( + UINT32 ProgramSCI); + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiEvTerminate ( + void)) + +#endif /* __ACEVENTS_H__ */ diff --git a/source/include/acexcep.h b/source/include/acexcep.h new file mode 100644 index 000000000000..10f5a113da8e --- /dev/null +++ b/source/include/acexcep.h @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * Name: acexcep.h - Exception codes returned by the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACEXCEP_H__ +#define __ACEXCEP_H__ + + +/* + * Exceptions returned by external ACPI interfaces + */ +#define AE_CODE_ENVIRONMENTAL 0x0000 +#define AE_CODE_PROGRAMMER 0x1000 +#define AE_CODE_ACPI_TABLES 0x2000 +#define AE_CODE_AML 0x3000 +#define AE_CODE_CONTROL 0x4000 +#define AE_CODE_MASK 0xF000 + + +#define ACPI_SUCCESS(a) (!(a)) +#define ACPI_FAILURE(a) (a) + + +#define AE_OK (ACPI_STATUS) 0x0000 + +/* + * Environmental exceptions + */ +#define AE_ERROR (ACPI_STATUS) (0x0001 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_ACPI_TABLES (ACPI_STATUS) (0x0002 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_NAMESPACE (ACPI_STATUS) (0x0003 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_MEMORY (ACPI_STATUS) (0x0004 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_FOUND (ACPI_STATUS) (0x0005 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_EXIST (ACPI_STATUS) (0x0006 | AE_CODE_ENVIRONMENTAL) +#define AE_ALREADY_EXISTS (ACPI_STATUS) (0x0007 | AE_CODE_ENVIRONMENTAL) +#define AE_TYPE (ACPI_STATUS) (0x0008 | AE_CODE_ENVIRONMENTAL) +#define AE_NULL_OBJECT (ACPI_STATUS) (0x0009 | AE_CODE_ENVIRONMENTAL) +#define AE_NULL_ENTRY (ACPI_STATUS) (0x000A | AE_CODE_ENVIRONMENTAL) +#define AE_BUFFER_OVERFLOW (ACPI_STATUS) (0x000B | AE_CODE_ENVIRONMENTAL) +#define AE_STACK_OVERFLOW (ACPI_STATUS) (0x000C | AE_CODE_ENVIRONMENTAL) +#define AE_STACK_UNDERFLOW (ACPI_STATUS) (0x000D | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_IMPLEMENTED (ACPI_STATUS) (0x000E | AE_CODE_ENVIRONMENTAL) +#define AE_SUPPORT (ACPI_STATUS) (0x000F | AE_CODE_ENVIRONMENTAL) +#define AE_LIMIT (ACPI_STATUS) (0x0010 | AE_CODE_ENVIRONMENTAL) +#define AE_TIME (ACPI_STATUS) (0x0011 | AE_CODE_ENVIRONMENTAL) +#define AE_ACQUIRE_DEADLOCK (ACPI_STATUS) (0x0012 | AE_CODE_ENVIRONMENTAL) +#define AE_RELEASE_DEADLOCK (ACPI_STATUS) (0x0013 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_ACQUIRED (ACPI_STATUS) (0x0014 | AE_CODE_ENVIRONMENTAL) +#define AE_ALREADY_ACQUIRED (ACPI_STATUS) (0x0015 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_HARDWARE_RESPONSE (ACPI_STATUS) (0x0016 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_GLOBAL_LOCK (ACPI_STATUS) (0x0017 | AE_CODE_ENVIRONMENTAL) +#define AE_ABORT_METHOD (ACPI_STATUS) (0x0018 | AE_CODE_ENVIRONMENTAL) +#define AE_SAME_HANDLER (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_HANDLER (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) +#define AE_OWNER_ID_LIMIT (ACPI_STATUS) (0x001B | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_CONFIGURED (ACPI_STATUS) (0x001C | AE_CODE_ENVIRONMENTAL) + +#define AE_CODE_ENV_MAX 0x001C + + +/* + * Programmer exceptions + */ +#define AE_BAD_PARAMETER (ACPI_STATUS) (0x0001 | AE_CODE_PROGRAMMER) +#define AE_BAD_CHARACTER (ACPI_STATUS) (0x0002 | AE_CODE_PROGRAMMER) +#define AE_BAD_PATHNAME (ACPI_STATUS) (0x0003 | AE_CODE_PROGRAMMER) +#define AE_BAD_DATA (ACPI_STATUS) (0x0004 | AE_CODE_PROGRAMMER) +#define AE_BAD_HEX_CONSTANT (ACPI_STATUS) (0x0005 | AE_CODE_PROGRAMMER) +#define AE_BAD_OCTAL_CONSTANT (ACPI_STATUS) (0x0006 | AE_CODE_PROGRAMMER) +#define AE_BAD_DECIMAL_CONSTANT (ACPI_STATUS) (0x0007 | AE_CODE_PROGRAMMER) +#define AE_MISSING_ARGUMENTS (ACPI_STATUS) (0x0008 | AE_CODE_PROGRAMMER) +#define AE_BAD_ADDRESS (ACPI_STATUS) (0x0009 | AE_CODE_PROGRAMMER) + +#define AE_CODE_PGM_MAX 0x0009 + + +/* + * Acpi table exceptions + */ +#define AE_BAD_SIGNATURE (ACPI_STATUS) (0x0001 | AE_CODE_ACPI_TABLES) +#define AE_BAD_HEADER (ACPI_STATUS) (0x0002 | AE_CODE_ACPI_TABLES) +#define AE_BAD_CHECKSUM (ACPI_STATUS) (0x0003 | AE_CODE_ACPI_TABLES) +#define AE_BAD_VALUE (ACPI_STATUS) (0x0004 | AE_CODE_ACPI_TABLES) +#define AE_INVALID_TABLE_LENGTH (ACPI_STATUS) (0x0005 | AE_CODE_ACPI_TABLES) + +#define AE_CODE_TBL_MAX 0x0005 + + +/* + * AML exceptions. These are caused by problems with + * the actual AML byte stream + */ +#define AE_AML_BAD_OPCODE (ACPI_STATUS) (0x0001 | AE_CODE_AML) +#define AE_AML_NO_OPERAND (ACPI_STATUS) (0x0002 | AE_CODE_AML) +#define AE_AML_OPERAND_TYPE (ACPI_STATUS) (0x0003 | AE_CODE_AML) +#define AE_AML_OPERAND_VALUE (ACPI_STATUS) (0x0004 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_LOCAL (ACPI_STATUS) (0x0005 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_ARG (ACPI_STATUS) (0x0006 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_ELEMENT (ACPI_STATUS) (0x0007 | AE_CODE_AML) +#define AE_AML_NUMERIC_OVERFLOW (ACPI_STATUS) (0x0008 | AE_CODE_AML) +#define AE_AML_REGION_LIMIT (ACPI_STATUS) (0x0009 | AE_CODE_AML) +#define AE_AML_BUFFER_LIMIT (ACPI_STATUS) (0x000A | AE_CODE_AML) +#define AE_AML_PACKAGE_LIMIT (ACPI_STATUS) (0x000B | AE_CODE_AML) +#define AE_AML_DIVIDE_BY_ZERO (ACPI_STATUS) (0x000C | AE_CODE_AML) +#define AE_AML_BAD_NAME (ACPI_STATUS) (0x000D | AE_CODE_AML) +#define AE_AML_NAME_NOT_FOUND (ACPI_STATUS) (0x000E | AE_CODE_AML) +#define AE_AML_INTERNAL (ACPI_STATUS) (0x000F | AE_CODE_AML) +#define AE_AML_INVALID_SPACE_ID (ACPI_STATUS) (0x0010 | AE_CODE_AML) +#define AE_AML_STRING_LIMIT (ACPI_STATUS) (0x0011 | AE_CODE_AML) +#define AE_AML_NO_RETURN_VALUE (ACPI_STATUS) (0x0012 | AE_CODE_AML) +#define AE_AML_METHOD_LIMIT (ACPI_STATUS) (0x0013 | AE_CODE_AML) +#define AE_AML_NOT_OWNER (ACPI_STATUS) (0x0014 | AE_CODE_AML) +#define AE_AML_MUTEX_ORDER (ACPI_STATUS) (0x0015 | AE_CODE_AML) +#define AE_AML_MUTEX_NOT_ACQUIRED (ACPI_STATUS) (0x0016 | AE_CODE_AML) +#define AE_AML_INVALID_RESOURCE_TYPE (ACPI_STATUS) (0x0017 | AE_CODE_AML) +#define AE_AML_INVALID_INDEX (ACPI_STATUS) (0x0018 | AE_CODE_AML) +#define AE_AML_REGISTER_LIMIT (ACPI_STATUS) (0x0019 | AE_CODE_AML) +#define AE_AML_NO_WHILE (ACPI_STATUS) (0x001A | AE_CODE_AML) +#define AE_AML_ALIGNMENT (ACPI_STATUS) (0x001B | AE_CODE_AML) +#define AE_AML_NO_RESOURCE_END_TAG (ACPI_STATUS) (0x001C | AE_CODE_AML) +#define AE_AML_BAD_RESOURCE_VALUE (ACPI_STATUS) (0x001D | AE_CODE_AML) +#define AE_AML_CIRCULAR_REFERENCE (ACPI_STATUS) (0x001E | AE_CODE_AML) +#define AE_AML_BAD_RESOURCE_LENGTH (ACPI_STATUS) (0x001F | AE_CODE_AML) +#define AE_AML_ILLEGAL_ADDRESS (ACPI_STATUS) (0x0020 | AE_CODE_AML) +#define AE_AML_INFINITE_LOOP (ACPI_STATUS) (0x0021 | AE_CODE_AML) + +#define AE_CODE_AML_MAX 0x0021 + + +/* + * Internal exceptions used for control + */ +#define AE_CTRL_RETURN_VALUE (ACPI_STATUS) (0x0001 | AE_CODE_CONTROL) +#define AE_CTRL_PENDING (ACPI_STATUS) (0x0002 | AE_CODE_CONTROL) +#define AE_CTRL_TERMINATE (ACPI_STATUS) (0x0003 | AE_CODE_CONTROL) +#define AE_CTRL_TRUE (ACPI_STATUS) (0x0004 | AE_CODE_CONTROL) +#define AE_CTRL_FALSE (ACPI_STATUS) (0x0005 | AE_CODE_CONTROL) +#define AE_CTRL_DEPTH (ACPI_STATUS) (0x0006 | AE_CODE_CONTROL) +#define AE_CTRL_END (ACPI_STATUS) (0x0007 | AE_CODE_CONTROL) +#define AE_CTRL_TRANSFER (ACPI_STATUS) (0x0008 | AE_CODE_CONTROL) +#define AE_CTRL_BREAK (ACPI_STATUS) (0x0009 | AE_CODE_CONTROL) +#define AE_CTRL_CONTINUE (ACPI_STATUS) (0x000A | AE_CODE_CONTROL) +#define AE_CTRL_SKIP (ACPI_STATUS) (0x000B | AE_CODE_CONTROL) +#define AE_CTRL_PARSE_CONTINUE (ACPI_STATUS) (0x000C | AE_CODE_CONTROL) +#define AE_CTRL_PARSE_PENDING (ACPI_STATUS) (0x000D | AE_CODE_CONTROL) + +#define AE_CODE_CTRL_MAX 0x000D + + +/* Exception strings for AcpiFormatException */ + +#ifdef DEFINE_ACPI_GLOBALS + +/* + * String versions of the exception codes above + * These strings must match the corresponding defines exactly + */ +char const *AcpiGbl_ExceptionNames_Env[] = +{ + "AE_OK", + "AE_ERROR", + "AE_NO_ACPI_TABLES", + "AE_NO_NAMESPACE", + "AE_NO_MEMORY", + "AE_NOT_FOUND", + "AE_NOT_EXIST", + "AE_ALREADY_EXISTS", + "AE_TYPE", + "AE_NULL_OBJECT", + "AE_NULL_ENTRY", + "AE_BUFFER_OVERFLOW", + "AE_STACK_OVERFLOW", + "AE_STACK_UNDERFLOW", + "AE_NOT_IMPLEMENTED", + "AE_SUPPORT", + "AE_LIMIT", + "AE_TIME", + "AE_ACQUIRE_DEADLOCK", + "AE_RELEASE_DEADLOCK", + "AE_NOT_ACQUIRED", + "AE_ALREADY_ACQUIRED", + "AE_NO_HARDWARE_RESPONSE", + "AE_NO_GLOBAL_LOCK", + "AE_ABORT_METHOD", + "AE_SAME_HANDLER", + "AE_NO_HANDLER", + "AE_OWNER_ID_LIMIT", + "AE_NOT_CONFIGURED" +}; + +char const *AcpiGbl_ExceptionNames_Pgm[] = +{ + NULL, + "AE_BAD_PARAMETER", + "AE_BAD_CHARACTER", + "AE_BAD_PATHNAME", + "AE_BAD_DATA", + "AE_BAD_HEX_CONSTANT", + "AE_BAD_OCTAL_CONSTANT", + "AE_BAD_DECIMAL_CONSTANT", + "AE_MISSING_ARGUMENTS", + "AE_BAD_ADDRESS" +}; + +char const *AcpiGbl_ExceptionNames_Tbl[] = +{ + NULL, + "AE_BAD_SIGNATURE", + "AE_BAD_HEADER", + "AE_BAD_CHECKSUM", + "AE_BAD_VALUE", + "AE_INVALID_TABLE_LENGTH" +}; + +char const *AcpiGbl_ExceptionNames_Aml[] = +{ + NULL, + "AE_AML_BAD_OPCODE", + "AE_AML_NO_OPERAND", + "AE_AML_OPERAND_TYPE", + "AE_AML_OPERAND_VALUE", + "AE_AML_UNINITIALIZED_LOCAL", + "AE_AML_UNINITIALIZED_ARG", + "AE_AML_UNINITIALIZED_ELEMENT", + "AE_AML_NUMERIC_OVERFLOW", + "AE_AML_REGION_LIMIT", + "AE_AML_BUFFER_LIMIT", + "AE_AML_PACKAGE_LIMIT", + "AE_AML_DIVIDE_BY_ZERO", + "AE_AML_BAD_NAME", + "AE_AML_NAME_NOT_FOUND", + "AE_AML_INTERNAL", + "AE_AML_INVALID_SPACE_ID", + "AE_AML_STRING_LIMIT", + "AE_AML_NO_RETURN_VALUE", + "AE_AML_METHOD_LIMIT", + "AE_AML_NOT_OWNER", + "AE_AML_MUTEX_ORDER", + "AE_AML_MUTEX_NOT_ACQUIRED", + "AE_AML_INVALID_RESOURCE_TYPE", + "AE_AML_INVALID_INDEX", + "AE_AML_REGISTER_LIMIT", + "AE_AML_NO_WHILE", + "AE_AML_ALIGNMENT", + "AE_AML_NO_RESOURCE_END_TAG", + "AE_AML_BAD_RESOURCE_VALUE", + "AE_AML_CIRCULAR_REFERENCE", + "AE_AML_BAD_RESOURCE_LENGTH", + "AE_AML_ILLEGAL_ADDRESS", + "AE_AML_INFINITE_LOOP" +}; + +char const *AcpiGbl_ExceptionNames_Ctrl[] = +{ + NULL, + "AE_CTRL_RETURN_VALUE", + "AE_CTRL_PENDING", + "AE_CTRL_TERMINATE", + "AE_CTRL_TRUE", + "AE_CTRL_FALSE", + "AE_CTRL_DEPTH", + "AE_CTRL_END", + "AE_CTRL_TRANSFER", + "AE_CTRL_BREAK", + "AE_CTRL_CONTINUE", + "AE_CTRL_SKIP", + "AE_CTRL_PARSE_CONTINUE", + "AE_CTRL_PARSE_PENDING" +}; + +#endif /* ACPI GLOBALS */ + +#endif /* __ACEXCEP_H__ */ diff --git a/source/include/acglobal.h b/source/include/acglobal.h new file mode 100644 index 000000000000..edf33d68ed7d --- /dev/null +++ b/source/include/acglobal.h @@ -0,0 +1,483 @@ +/****************************************************************************** + * + * Name: acglobal.h - Declarations for global variables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACGLOBAL_H__ +#define __ACGLOBAL_H__ + + +/* + * Ensure that the globals are actually defined and initialized only once. + * + * The use of these macros allows a single list of globals (here) in order + * to simplify maintenance of the code. + */ +#ifdef DEFINE_ACPI_GLOBALS +#define ACPI_EXTERN +#define ACPI_INIT_GLOBAL(a,b) a=b +#else +#define ACPI_EXTERN extern +#define ACPI_INIT_GLOBAL(a,b) a +#endif + + +#ifdef DEFINE_ACPI_GLOBALS + +/* Public globals, available from outside ACPICA subsystem */ + +/***************************************************************************** + * + * Runtime configuration (static defaults that can be overriden at runtime) + * + ****************************************************************************/ + +/* + * Enable "slack" in the AML interpreter? Default is FALSE, and the + * interpreter strictly follows the ACPI specification. Setting to TRUE + * allows the interpreter to ignore certain errors and/or bad AML constructs. + * + * Currently, these features are enabled by this flag: + * + * 1) Allow "implicit return" of last value in a control method + * 2) Allow access beyond the end of an operation region + * 3) Allow access to uninitialized locals/args (auto-init to integer 0) + * 4) Allow ANY object type to be a source operand for the Store() operator + * 5) Allow unresolved references (invalid target name) in package objects + * 6) Enable warning messages for behavior that is not ACPI spec compliant + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_EnableInterpreterSlack, FALSE); + +/* + * Automatically serialize ALL control methods? Default is FALSE, meaning + * to use the Serialized/NotSerialized method flags on a per method basis. + * Only change this if the ASL code is poorly written and cannot handle + * reentrancy even though methods are marked "NotSerialized". + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_AllMethodsSerialized, FALSE); + +/* + * Create the predefined _OSI method in the namespace? Default is TRUE + * because ACPI CA is fully compatible with other ACPI implementations. + * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_CreateOsiMethod, TRUE); + +/* + * Optionally use default values for the ACPI register widths. Set this to + * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_UseDefaultRegisterWidths, TRUE); + +/* + * Optionally enable output from the AML Debug Object. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_EnableAmlDebugObject, FALSE); + +/* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_CopyDsdtLocally, FALSE); + +/* + * Optionally truncate I/O addresses to 16 bits. Provides compatibility + * with other ACPI implementations. NOTE: During ACPICA initialization, + * this value is set to TRUE if any Windows OSI strings have been + * requested by the BIOS. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_TruncateIoAddresses, FALSE); + +/* + * Disable runtime checking and repair of values returned by control methods. + * Use only if the repair is causing a problem on a particular machine. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_DisableAutoRepair, FALSE); + + +/* AcpiGbl_FADT is a local copy of the FADT, converted to a common format. */ + +ACPI_TABLE_FADT AcpiGbl_FADT; +UINT32 AcpiCurrentGpeCount; +UINT32 AcpiGbl_TraceFlags; +ACPI_NAME AcpiGbl_TraceMethodName; +BOOLEAN AcpiGbl_SystemAwakeAndRunning; + +/* + * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning + * that the ACPI hardware is no longer required. A flag in the FADT indicates + * a reduced HW machine, and that flag is duplicated here for convenience. + */ +BOOLEAN AcpiGbl_ReducedHardware; + +#endif /* DEFINE_ACPI_GLOBALS */ + +/* Do not disassemble buffers to resource descriptors */ + +ACPI_EXTERN UINT8 ACPI_INIT_GLOBAL (AcpiGbl_NoResourceDisassembly, FALSE); + +/***************************************************************************** + * + * ACPI Table globals + * + ****************************************************************************/ + +/* + * AcpiGbl_RootTableList is the master list of ACPI tables that were + * found in the RSDT/XSDT. + */ +ACPI_EXTERN ACPI_TABLE_LIST AcpiGbl_RootTableList; + +#if (!ACPI_REDUCED_HARDWARE) +ACPI_EXTERN ACPI_TABLE_FACS *AcpiGbl_FACS; + +#endif /* !ACPI_REDUCED_HARDWARE */ + +/* These addresses are calculated from the FADT Event Block addresses */ + +ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aStatus; +ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aEnable; + +ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bStatus; +ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bEnable; + +/* DSDT information. Used to check for DSDT corruption */ + +ACPI_EXTERN ACPI_TABLE_HEADER *AcpiGbl_DSDT; +ACPI_EXTERN ACPI_TABLE_HEADER AcpiGbl_OriginalDsdtHeader; + +/* + * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is + * determined by the revision of the DSDT: If the DSDT revision is less than + * 2, use only the lower 32 bits of the internal 64-bit Integer. + */ +ACPI_EXTERN UINT8 AcpiGbl_IntegerBitWidth; +ACPI_EXTERN UINT8 AcpiGbl_IntegerByteWidth; +ACPI_EXTERN UINT8 AcpiGbl_IntegerNybbleWidth; + + +/***************************************************************************** + * + * Mutual exclusion within ACPICA subsystem + * + ****************************************************************************/ + +/* + * Predefined mutex objects. This array contains the + * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. + * (The table maps local handles to the real OS handles) + */ +ACPI_EXTERN ACPI_MUTEX_INFO AcpiGbl_MutexInfo[ACPI_NUM_MUTEX]; + +/* + * Global lock mutex is an actual AML mutex object + * Global lock semaphore works in conjunction with the actual global lock + * Global lock spinlock is used for "pending" handshake + */ +ACPI_EXTERN ACPI_OPERAND_OBJECT *AcpiGbl_GlobalLockMutex; +ACPI_EXTERN ACPI_SEMAPHORE AcpiGbl_GlobalLockSemaphore; +ACPI_EXTERN ACPI_SPINLOCK AcpiGbl_GlobalLockPendingLock; +ACPI_EXTERN UINT16 AcpiGbl_GlobalLockHandle; +ACPI_EXTERN BOOLEAN AcpiGbl_GlobalLockAcquired; +ACPI_EXTERN BOOLEAN AcpiGbl_GlobalLockPresent; +ACPI_EXTERN BOOLEAN AcpiGbl_GlobalLockPending; + +/* + * Spinlocks are used for interfaces that can be possibly called at + * interrupt level + */ +ACPI_EXTERN ACPI_SPINLOCK AcpiGbl_GpeLock; /* For GPE data structs and registers */ +ACPI_EXTERN ACPI_SPINLOCK AcpiGbl_HardwareLock; /* For ACPI H/W except GPE registers */ + +/* Mutex for _OSI support */ + +ACPI_EXTERN ACPI_MUTEX AcpiGbl_OsiMutex; + +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_EXTERN ACPI_RW_LOCK AcpiGbl_NamespaceRwLock; + + +/***************************************************************************** + * + * Miscellaneous globals + * + ****************************************************************************/ + +/* Object caches */ + +ACPI_EXTERN ACPI_CACHE_T *AcpiGbl_NamespaceCache; +ACPI_EXTERN ACPI_CACHE_T *AcpiGbl_StateCache; +ACPI_EXTERN ACPI_CACHE_T *AcpiGbl_PsNodeCache; +ACPI_EXTERN ACPI_CACHE_T *AcpiGbl_PsNodeExtCache; +ACPI_EXTERN ACPI_CACHE_T *AcpiGbl_OperandCache; + +/* Global handlers */ + +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER AcpiGbl_DeviceNotify; +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER AcpiGbl_SystemNotify; +ACPI_EXTERN ACPI_EXCEPTION_HANDLER AcpiGbl_ExceptionHandler; +ACPI_EXTERN ACPI_INIT_HANDLER AcpiGbl_InitHandler; +ACPI_EXTERN ACPI_TABLE_HANDLER AcpiGbl_TableHandler; +ACPI_EXTERN void *AcpiGbl_TableHandlerContext; +ACPI_EXTERN ACPI_WALK_STATE *AcpiGbl_BreakpointWalk; +ACPI_EXTERN ACPI_INTERFACE_HANDLER AcpiGbl_InterfaceHandler; + +/* Owner ID support */ + +ACPI_EXTERN UINT32 AcpiGbl_OwnerIdMask[ACPI_NUM_OWNERID_MASKS]; +ACPI_EXTERN UINT8 AcpiGbl_LastOwnerIdIndex; +ACPI_EXTERN UINT8 AcpiGbl_NextOwnerIdOffset; + +/* Initialization sequencing */ + +ACPI_EXTERN BOOLEAN AcpiGbl_RegMethodsExecuted; + +/* Misc */ + +ACPI_EXTERN UINT32 AcpiGbl_OriginalMode; +ACPI_EXTERN UINT32 AcpiGbl_RsdpOriginalLocation; +ACPI_EXTERN UINT32 AcpiGbl_NsLookupCount; +ACPI_EXTERN UINT32 AcpiGbl_PsFindCount; +ACPI_EXTERN UINT16 AcpiGbl_Pm1EnableRegisterSave; +ACPI_EXTERN UINT8 AcpiGbl_DebuggerConfiguration; +ACPI_EXTERN BOOLEAN AcpiGbl_StepToNextCall; +ACPI_EXTERN BOOLEAN AcpiGbl_AcpiHardwarePresent; +ACPI_EXTERN BOOLEAN AcpiGbl_EventsInitialized; +ACPI_EXTERN UINT8 AcpiGbl_OsiData; +ACPI_EXTERN ACPI_INTERFACE_INFO *AcpiGbl_SupportedInterfaces; +ACPI_EXTERN ACPI_ADDRESS_RANGE *AcpiGbl_AddressRangeList[ACPI_ADDRESS_RANGE_MAX]; + + +#ifndef DEFINE_ACPI_GLOBALS + +/* Exception codes */ + +extern char const *AcpiGbl_ExceptionNames_Env[]; +extern char const *AcpiGbl_ExceptionNames_Pgm[]; +extern char const *AcpiGbl_ExceptionNames_Tbl[]; +extern char const *AcpiGbl_ExceptionNames_Aml[]; +extern char const *AcpiGbl_ExceptionNames_Ctrl[]; + +/* Other miscellaneous */ + +extern BOOLEAN AcpiGbl_Shutdown; +extern UINT32 AcpiGbl_StartupFlags; +extern const char *AcpiGbl_SleepStateNames[ACPI_S_STATE_COUNT]; +extern const char *AcpiGbl_LowestDstateNames[ACPI_NUM_SxW_METHODS]; +extern const char *AcpiGbl_HighestDstateNames[ACPI_NUM_SxD_METHODS]; +extern const ACPI_OPCODE_INFO AcpiGbl_AmlOpInfo[AML_NUM_OPCODES]; +extern const char *AcpiGbl_RegionTypes[ACPI_NUM_PREDEFINED_REGIONS]; +#endif + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +/* Lists for tracking memory allocations */ + +ACPI_EXTERN ACPI_MEMORY_LIST *AcpiGbl_GlobalList; +ACPI_EXTERN ACPI_MEMORY_LIST *AcpiGbl_NsNodeList; +ACPI_EXTERN BOOLEAN AcpiGbl_DisplayFinalMemStats; +ACPI_EXTERN BOOLEAN AcpiGbl_DisableMemTracking; +#endif + + +/***************************************************************************** + * + * Namespace globals + * + ****************************************************************************/ + +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) +#define NUM_PREDEFINED_NAMES 10 +#else +#define NUM_PREDEFINED_NAMES 9 +#endif + +ACPI_EXTERN ACPI_NAMESPACE_NODE AcpiGbl_RootNodeStruct; +ACPI_EXTERN ACPI_NAMESPACE_NODE *AcpiGbl_RootNode; +ACPI_EXTERN ACPI_NAMESPACE_NODE *AcpiGbl_FadtGpeDevice; +ACPI_EXTERN ACPI_OPERAND_OBJECT *AcpiGbl_ModuleCodeList; + + +extern const UINT8 AcpiGbl_NsProperties [ACPI_NUM_NS_TYPES]; +extern const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames [NUM_PREDEFINED_NAMES]; + +#ifdef ACPI_DEBUG_OUTPUT +ACPI_EXTERN UINT32 AcpiGbl_CurrentNodeCount; +ACPI_EXTERN UINT32 AcpiGbl_CurrentNodeSize; +ACPI_EXTERN UINT32 AcpiGbl_MaxConcurrentNodeCount; +ACPI_EXTERN ACPI_SIZE *AcpiGbl_EntryStackPointer; +ACPI_EXTERN ACPI_SIZE *AcpiGbl_LowestStackPointer; +ACPI_EXTERN UINT32 AcpiGbl_DeepestNesting; +#endif + + +/***************************************************************************** + * + * Interpreter globals + * + ****************************************************************************/ + + +ACPI_EXTERN ACPI_THREAD_STATE *AcpiGbl_CurrentWalkList; + +/* Control method single step flag */ + +ACPI_EXTERN UINT8 AcpiGbl_CmSingleStep; + + +/***************************************************************************** + * + * Hardware globals + * + ****************************************************************************/ + +extern ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG]; +ACPI_EXTERN UINT8 AcpiGbl_SleepTypeA; +ACPI_EXTERN UINT8 AcpiGbl_SleepTypeB; + + +/***************************************************************************** + * + * Event and GPE globals + * + ****************************************************************************/ + +#if (!ACPI_REDUCED_HARDWARE) + +ACPI_EXTERN UINT8 AcpiGbl_AllGpesInitialized; +ACPI_EXTERN ACPI_GPE_XRUPT_INFO *AcpiGbl_GpeXruptListHead; +ACPI_EXTERN ACPI_GPE_BLOCK_INFO *AcpiGbl_GpeFadtBlocks[ACPI_MAX_GPE_BLOCKS]; +ACPI_EXTERN ACPI_GBL_EVENT_HANDLER AcpiGbl_GlobalEventHandler; +ACPI_EXTERN void *AcpiGbl_GlobalEventHandlerContext; +ACPI_EXTERN ACPI_FIXED_EVENT_HANDLER AcpiGbl_FixedEventHandlers[ACPI_NUM_FIXED_EVENTS]; +extern ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS]; + +#endif /* !ACPI_REDUCED_HARDWARE */ + +/***************************************************************************** + * + * Debug support + * + ****************************************************************************/ + +/* Procedure nesting level for debug output */ + +extern UINT32 AcpiGbl_NestingLevel; + +/* Event counters */ + +ACPI_EXTERN UINT32 AcpiMethodCount; +ACPI_EXTERN UINT32 AcpiGpeCount; +ACPI_EXTERN UINT32 AcpiSciCount; +ACPI_EXTERN UINT32 AcpiFixedEventCount[ACPI_NUM_FIXED_EVENTS]; + +/* Support for dynamic control method tracing mechanism */ + +ACPI_EXTERN UINT32 AcpiGbl_OriginalDbgLevel; +ACPI_EXTERN UINT32 AcpiGbl_OriginalDbgLayer; +ACPI_EXTERN UINT32 AcpiGbl_TraceDbgLevel; +ACPI_EXTERN UINT32 AcpiGbl_TraceDbgLayer; + + +/***************************************************************************** + * + * Debugger globals + * + ****************************************************************************/ + +ACPI_EXTERN UINT8 AcpiGbl_DbOutputFlags; + +#ifdef ACPI_DISASSEMBLER + +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_disasm; +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_verbose; +ACPI_EXTERN ACPI_EXTERNAL_LIST *AcpiGbl_ExternalList; +ACPI_EXTERN ACPI_EXTERNAL_FILE *AcpiGbl_ExternalFileList; +#endif + + +#ifdef ACPI_DEBUGGER + +extern BOOLEAN AcpiGbl_MethodExecuting; +extern BOOLEAN AcpiGbl_AbortMethod; +extern BOOLEAN AcpiGbl_DbTerminateThreads; + +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_tables; +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_stats; +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_ini_methods; +ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_NoRegionSupport; + +ACPI_EXTERN char *AcpiGbl_DbArgs[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN ACPI_OBJECT_TYPE AcpiGbl_DbArgTypes[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN char AcpiGbl_DbLineBuf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char AcpiGbl_DbParsedBuf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char AcpiGbl_DbScopeBuf[80]; +ACPI_EXTERN char AcpiGbl_DbDebugFilename[80]; +ACPI_EXTERN BOOLEAN AcpiGbl_DbOutputToFile; +ACPI_EXTERN char *AcpiGbl_DbBuffer; +ACPI_EXTERN char *AcpiGbl_DbFilename; +ACPI_EXTERN UINT32 AcpiGbl_DbDebugLevel; +ACPI_EXTERN UINT32 AcpiGbl_DbConsoleDebugLevel; +ACPI_EXTERN ACPI_NAMESPACE_NODE *AcpiGbl_DbScopeNode; + +/* + * Statistic globals + */ +ACPI_EXTERN UINT16 AcpiGbl_ObjTypeCount[ACPI_TYPE_NS_NODE_MAX+1]; +ACPI_EXTERN UINT16 AcpiGbl_NodeTypeCount[ACPI_TYPE_NS_NODE_MAX+1]; +ACPI_EXTERN UINT16 AcpiGbl_ObjTypeCountMisc; +ACPI_EXTERN UINT16 AcpiGbl_NodeTypeCountMisc; +ACPI_EXTERN UINT32 AcpiGbl_NumNodes; +ACPI_EXTERN UINT32 AcpiGbl_NumObjects; + + +ACPI_EXTERN UINT32 AcpiGbl_SizeOfParseTree; +ACPI_EXTERN UINT32 AcpiGbl_SizeOfMethodTrees; +ACPI_EXTERN UINT32 AcpiGbl_SizeOfNodeEntries; +ACPI_EXTERN UINT32 AcpiGbl_SizeOfAcpiObjects; + +#endif /* ACPI_DEBUGGER */ + +#endif /* __ACGLOBAL_H__ */ diff --git a/source/include/achware.h b/source/include/achware.h new file mode 100644 index 000000000000..004795dbfa12 --- /dev/null +++ b/source/include/achware.h @@ -0,0 +1,228 @@ +/****************************************************************************** + * + * Name: achware.h -- hardware specific interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACHWARE_H__ +#define __ACHWARE_H__ + + +/* Values for the _SST predefined method */ + +#define ACPI_SST_INDICATOR_OFF 0 +#define ACPI_SST_WORKING 1 +#define ACPI_SST_WAKING 2 +#define ACPI_SST_SLEEPING 3 +#define ACPI_SST_SLEEP_CONTEXT 4 + + +/* + * hwacpi - high level functions + */ +ACPI_STATUS +AcpiHwSetMode ( + UINT32 Mode); + +UINT32 +AcpiHwGetMode ( + void); + + +/* + * hwregs - ACPI Register I/O + */ +ACPI_STATUS +AcpiHwValidateRegister ( + ACPI_GENERIC_ADDRESS *Reg, + UINT8 MaxBitWidth, + UINT64 *Address); + +ACPI_STATUS +AcpiHwRead ( + UINT32 *Value, + ACPI_GENERIC_ADDRESS *Reg); + +ACPI_STATUS +AcpiHwWrite ( + UINT32 Value, + ACPI_GENERIC_ADDRESS *Reg); + +ACPI_BIT_REGISTER_INFO * +AcpiHwGetBitRegisterInfo ( + UINT32 RegisterId); + +ACPI_STATUS +AcpiHwWritePm1Control ( + UINT32 Pm1aControl, + UINT32 Pm1bControl); + +ACPI_STATUS +AcpiHwRegisterRead ( + UINT32 RegisterId, + UINT32 *ReturnValue); + +ACPI_STATUS +AcpiHwRegisterWrite ( + UINT32 RegisterId, + UINT32 Value); + +ACPI_STATUS +AcpiHwClearAcpiStatus ( + void); + + +/* + * hwsleep - sleep/wake support (Legacy sleep registers) + */ +ACPI_STATUS +AcpiHwLegacySleep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwLegacyWakePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwLegacyWake ( + UINT8 SleepState); + + +/* + * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers) + */ +void +AcpiHwExecuteSleepMethod ( + char *MethodName, + UINT32 IntegerArgument); + +ACPI_STATUS +AcpiHwExtendedSleep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwExtendedWakePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwExtendedWake ( + UINT8 SleepState); + + +/* + * hwvalid - Port I/O with validation + */ +ACPI_STATUS +AcpiHwReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width); + +ACPI_STATUS +AcpiHwWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width); + + +/* + * hwgpe - GPE support + */ +UINT32 +AcpiHwGetGpeRegisterBit ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo); + +ACPI_STATUS +AcpiHwLowSetGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 Action); + +ACPI_STATUS +AcpiHwDisableGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + +ACPI_STATUS +AcpiHwClearGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_STATUS +AcpiHwClearGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + +ACPI_STATUS +AcpiHwGetGpeStatus ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + ACPI_EVENT_STATUS *EventStatus); + +ACPI_STATUS +AcpiHwDisableAllGpes ( + void); + +ACPI_STATUS +AcpiHwEnableAllRuntimeGpes ( + void); + +ACPI_STATUS +AcpiHwEnableAllWakeupGpes ( + void); + +ACPI_STATUS +AcpiHwEnableRuntimeGpeBlock ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + + +/* + * hwpci - PCI configuration support + */ +ACPI_STATUS +AcpiHwDerivePciId ( + ACPI_PCI_ID *PciId, + ACPI_HANDLE RootPciDevice, + ACPI_HANDLE PciRegion); + + +#endif /* __ACHWARE_H__ */ diff --git a/source/include/acinterp.h b/source/include/acinterp.h new file mode 100644 index 000000000000..45e9814f7930 --- /dev/null +++ b/source/include/acinterp.h @@ -0,0 +1,726 @@ +/****************************************************************************** + * + * Name: acinterp.h - Interpreter subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACINTERP_H__ +#define __ACINTERP_H__ + + +#define ACPI_WALK_OPERANDS (&(WalkState->Operands [WalkState->NumOperands -1])) + +/* Macros for tables used for debug output */ + +#define ACPI_EXD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_OPERAND_OBJECT,f) +#define ACPI_EXD_NSOFFSET(f) (UINT8) ACPI_OFFSET (ACPI_NAMESPACE_NODE,f) +#define ACPI_EXD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_EXDUMP_INFO)) + +/* + * If possible, pack the following structures to byte alignment, since we + * don't care about performance for debug output. Two cases where we cannot + * pack the structures: + * + * 1) Hardware does not support misaligned memory transfers + * 2) Compiler does not support pointers within packed structures + */ +#if (!defined(ACPI_MISALIGNMENT_NOT_SUPPORTED) && !defined(ACPI_PACKED_POINTERS_NOT_SUPPORTED)) +#pragma pack(1) +#endif + +typedef const struct acpi_exdump_info +{ + UINT8 Opcode; + UINT8 Offset; + char *Name; + +} ACPI_EXDUMP_INFO; + +/* Values for the Opcode field above */ + +#define ACPI_EXD_INIT 0 +#define ACPI_EXD_TYPE 1 +#define ACPI_EXD_UINT8 2 +#define ACPI_EXD_UINT16 3 +#define ACPI_EXD_UINT32 4 +#define ACPI_EXD_UINT64 5 +#define ACPI_EXD_LITERAL 6 +#define ACPI_EXD_POINTER 7 +#define ACPI_EXD_ADDRESS 8 +#define ACPI_EXD_STRING 9 +#define ACPI_EXD_BUFFER 10 +#define ACPI_EXD_PACKAGE 11 +#define ACPI_EXD_FIELD 12 +#define ACPI_EXD_REFERENCE 13 + +/* restore default alignment */ + +#pragma pack() + + +/* + * exconvrt - object conversion + */ +ACPI_STATUS +AcpiExConvertToInteger ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + UINT32 Flags); + +ACPI_STATUS +AcpiExConvertToBuffer ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc); + +ACPI_STATUS +AcpiExConvertToString ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + UINT32 Type); + +/* Types for ->String conversion */ + +#define ACPI_EXPLICIT_BYTE_COPY 0x00000000 +#define ACPI_EXPLICIT_CONVERT_HEX 0x00000001 +#define ACPI_IMPLICIT_CONVERT_HEX 0x00000002 +#define ACPI_EXPLICIT_CONVERT_DECIMAL 0x00000003 + +ACPI_STATUS +AcpiExConvertToTargetType ( + ACPI_OBJECT_TYPE DestinationType, + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + ACPI_WALK_STATE *WalkState); + + +/* + * exdebug - AML debug object + */ +void +AcpiExDoDebugObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + UINT32 Level, + UINT32 Index); + + +/* + * exfield - ACPI AML (p-code) execution - field manipulation + */ +ACPI_STATUS +AcpiExCommonBufferSetup ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 BufferLength, + UINT32 *DatumCount); + +ACPI_STATUS +AcpiExWriteWithUpdateRule ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT64 Mask, + UINT64 FieldValue, + UINT32 FieldDatumByteOffset); + +void +AcpiExGetBufferDatum( + UINT64 *Datum, + void *Buffer, + UINT32 BufferLength, + UINT32 ByteGranularity, + UINT32 BufferOffset); + +void +AcpiExSetBufferDatum ( + UINT64 MergedDatum, + void *Buffer, + UINT32 BufferLength, + UINT32 ByteGranularity, + UINT32 BufferOffset); + +ACPI_STATUS +AcpiExReadDataFromField ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **RetBufferDesc); + +ACPI_STATUS +AcpiExWriteDataToField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc); + + +/* + * exfldio - low level field I/O + */ +ACPI_STATUS +AcpiExExtractFromField ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer, + UINT32 BufferLength); + +ACPI_STATUS +AcpiExInsertIntoField ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer, + UINT32 BufferLength); + +ACPI_STATUS +AcpiExAccessRegion ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset, + UINT64 *Value, + UINT32 ReadWrite); + + +/* + * exmisc - misc support routines + */ +ACPI_STATUS +AcpiExGetObjectReference ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExConcatTemplate ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *ObjDesc2, + ACPI_OPERAND_OBJECT **ActualReturnDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExDoConcatenate ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *ObjDesc2, + ACPI_OPERAND_OBJECT **ActualReturnDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExDoLogicalNumericOp ( + UINT16 Opcode, + UINT64 Integer0, + UINT64 Integer1, + BOOLEAN *LogicalResult); + +ACPI_STATUS +AcpiExDoLogicalOp ( + UINT16 Opcode, + ACPI_OPERAND_OBJECT *Operand0, + ACPI_OPERAND_OBJECT *Operand1, + BOOLEAN *LogicalResult); + +UINT64 +AcpiExDoMathOp ( + UINT16 Opcode, + UINT64 Operand0, + UINT64 Operand1); + +ACPI_STATUS +AcpiExCreateMutex ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreateProcessor ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreatePowerResource ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreateRegion ( + UINT8 *AmlStart, + UINT32 AmlLength, + UINT8 RegionSpace, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreateEvent ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreateAlias ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExCreateMethod ( + UINT8 *AmlStart, + UINT32 AmlLength, + ACPI_WALK_STATE *WalkState); + + +/* + * exconfig - dynamic table load/unload + */ +ACPI_STATUS +AcpiExLoadOp ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT *Target, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExLoadTableOp ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT **ReturnDesc); + +ACPI_STATUS +AcpiExUnloadTable ( + ACPI_OPERAND_OBJECT *DdbHandle); + + +/* + * exmutex - mutex support + */ +ACPI_STATUS +AcpiExAcquireMutex ( + ACPI_OPERAND_OBJECT *TimeDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExAcquireMutexObject ( + UINT16 Timeout, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_THREAD_ID ThreadId); + +ACPI_STATUS +AcpiExReleaseMutex ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExReleaseMutexObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +void +AcpiExReleaseAllMutexes ( + ACPI_THREAD_STATE *Thread); + +void +AcpiExUnlinkMutex ( + ACPI_OPERAND_OBJECT *ObjDesc); + + +/* + * exprep - ACPI AML execution - prep utilities + */ +ACPI_STATUS +AcpiExPrepCommonFieldObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 FieldFlags, + UINT8 FieldAttribute, + UINT32 FieldBitPosition, + UINT32 FieldBitLength); + +ACPI_STATUS +AcpiExPrepFieldValue ( + ACPI_CREATE_FIELD_INFO *Info); + + +/* + * exsystem - Interface to OS services + */ +ACPI_STATUS +AcpiExSystemDoNotifyOp ( + ACPI_OPERAND_OBJECT *Value, + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiExSystemDoSleep( + UINT64 Time); + +ACPI_STATUS +AcpiExSystemDoStall ( + UINT32 Time); + +ACPI_STATUS +AcpiExSystemSignalEvent( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiExSystemWaitEvent( + ACPI_OPERAND_OBJECT *Time, + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiExSystemResetEvent( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiExSystemWaitSemaphore ( + ACPI_SEMAPHORE Semaphore, + UINT16 Timeout); + +ACPI_STATUS +AcpiExSystemWaitMutex ( + ACPI_MUTEX Mutex, + UINT16 Timeout); + +/* + * exoparg1 - ACPI AML execution, 1 operand + */ +ACPI_STATUS +AcpiExOpcode_0A_0T_1R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_1A_0T_0R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_1A_0T_1R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_1A_1T_1R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_1A_1T_0R ( + ACPI_WALK_STATE *WalkState); + +/* + * exoparg2 - ACPI AML execution, 2 operands + */ +ACPI_STATUS +AcpiExOpcode_2A_0T_0R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_2A_0T_1R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_2A_1T_1R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_2A_2T_1R ( + ACPI_WALK_STATE *WalkState); + + +/* + * exoparg3 - ACPI AML execution, 3 operands + */ +ACPI_STATUS +AcpiExOpcode_3A_0T_0R ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExOpcode_3A_1T_1R ( + ACPI_WALK_STATE *WalkState); + + +/* + * exoparg6 - ACPI AML execution, 6 operands + */ +ACPI_STATUS +AcpiExOpcode_6A_0T_1R ( + ACPI_WALK_STATE *WalkState); + + +/* + * exresolv - Object resolution and get value functions + */ +ACPI_STATUS +AcpiExResolveToValue ( + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExResolveMultiple ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *Operand, + ACPI_OBJECT_TYPE *ReturnType, + ACPI_OPERAND_OBJECT **ReturnDesc); + + +/* + * exresnte - resolve namespace node + */ +ACPI_STATUS +AcpiExResolveNodeToValue ( + ACPI_NAMESPACE_NODE **StackPtr, + ACPI_WALK_STATE *WalkState); + + +/* + * exresop - resolve operand to value + */ +ACPI_STATUS +AcpiExResolveOperands ( + UINT16 Opcode, + ACPI_OPERAND_OBJECT **StackPtr, + ACPI_WALK_STATE *WalkState); + + +/* + * exdump - Interpreter debug output routines + */ +void +AcpiExDumpOperand ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Depth); + +void +AcpiExDumpOperands ( + ACPI_OPERAND_OBJECT **Operands, + const char *OpcodeName, + UINT32 NumOpcodes); + +void +AcpiExDumpObjectDescriptor ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Flags); + +void +AcpiExDumpNamespaceNode ( + ACPI_NAMESPACE_NODE *Node, + UINT32 Flags); + + +/* + * exnames - AML namestring support + */ +ACPI_STATUS +AcpiExGetNameString ( + ACPI_OBJECT_TYPE DataType, + UINT8 *InAmlAddress, + char **OutNameString, + UINT32 *OutNameLength); + + +/* + * exstore - Object store support + */ +ACPI_STATUS +AcpiExStore ( + ACPI_OPERAND_OBJECT *ValDesc, + ACPI_OPERAND_OBJECT *DestDesc, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExStoreObjectToNode ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node, + ACPI_WALK_STATE *WalkState, + UINT8 ImplicitConversion); + +#define ACPI_IMPLICIT_CONVERSION TRUE +#define ACPI_NO_IMPLICIT_CONVERSION FALSE + + +/* + * exstoren - resolve/store object + */ +ACPI_STATUS +AcpiExResolveObject ( + ACPI_OPERAND_OBJECT **SourceDescPtr, + ACPI_OBJECT_TYPE TargetType, + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiExStoreObjectToObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc, + ACPI_OPERAND_OBJECT **NewDesc, + ACPI_WALK_STATE *WalkState); + + +/* + * exstorob - store object - buffer/string + */ +ACPI_STATUS +AcpiExStoreBufferToBuffer ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc); + +ACPI_STATUS +AcpiExStoreStringToString ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc); + + +/* + * excopy - object copy + */ +ACPI_STATUS +AcpiExCopyIntegerToIndexField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc); + +ACPI_STATUS +AcpiExCopyIntegerToBankField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc); + +ACPI_STATUS +AcpiExCopyDataToNamedField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node); + +ACPI_STATUS +AcpiExCopyIntegerToBufferField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *TargetDesc); + + +/* + * exutils - interpreter/scanner utilities + */ +void +AcpiExEnterInterpreter ( + void); + +void +AcpiExExitInterpreter ( + void); + +void +AcpiExReacquireInterpreter ( + void); + +void +AcpiExRelinquishInterpreter ( + void); + +void +AcpiExTruncateFor32bitTable ( + ACPI_OPERAND_OBJECT *ObjDesc); + +void +AcpiExAcquireGlobalLock ( + UINT32 Rule); + +void +AcpiExReleaseGlobalLock ( + UINT32 Rule); + +void +AcpiExEisaIdToString ( + char *Dest, + UINT64 CompressedId); + +void +AcpiExIntegerToString ( + char *Dest, + UINT64 Value); + +BOOLEAN +AcpiIsValidSpaceId ( + UINT8 SpaceId); + + +/* + * exregion - default OpRegion handlers + */ +ACPI_STATUS +AcpiExSystemMemorySpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExSystemIoSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExPciConfigSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExCmosSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExPciBarSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExEmbeddedControllerSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +ACPI_STATUS +AcpiExSmBusSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + + +ACPI_STATUS +AcpiExDataTableSpaceHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +#endif /* __INTERP_H__ */ diff --git a/source/include/aclocal.h b/source/include/aclocal.h new file mode 100644 index 000000000000..d29a72157639 --- /dev/null +++ b/source/include/aclocal.h @@ -0,0 +1,1302 @@ +/****************************************************************************** + * + * Name: aclocal.h - Internal data types used across the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACLOCAL_H__ +#define __ACLOCAL_H__ + + +/* acpisrc:StructDefs -- for acpisrc conversion */ + +#define ACPI_SERIALIZED 0xFF + +typedef UINT32 ACPI_MUTEX_HANDLE; +#define ACPI_GLOBAL_LOCK (ACPI_SEMAPHORE) (-1) + +/* Total number of aml opcodes defined */ + +#define AML_NUM_OPCODES 0x81 + + +/* Forward declarations */ + +struct acpi_walk_state; +struct acpi_obj_mutex; +union acpi_parse_object; + + +/***************************************************************************** + * + * Mutex typedefs and structs + * + ****************************************************************************/ + + +/* + * Predefined handles for the mutex objects used within the subsystem + * All mutex objects are automatically created by AcpiUtMutexInitialize. + * + * The acquire/release ordering protocol is implied via this list. Mutexes + * with a lower value must be acquired before mutexes with a higher value. + * + * NOTE: any changes here must be reflected in the AcpiGbl_MutexNames + * table below also! + */ +#define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */ +#define ACPI_MTX_NAMESPACE 1 /* ACPI Namespace */ +#define ACPI_MTX_TABLES 2 /* Data for ACPI tables */ +#define ACPI_MTX_EVENTS 3 /* Data for ACPI events */ +#define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */ +#define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ +#define ACPI_MTX_DEBUG_CMD_COMPLETE 6 /* AML debugger */ +#define ACPI_MTX_DEBUG_CMD_READY 7 /* AML debugger */ + +#define ACPI_MAX_MUTEX 7 +#define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 + + +/* Lock structure for reader/writer interfaces */ + +typedef struct acpi_rw_lock +{ + ACPI_MUTEX WriterMutex; + ACPI_MUTEX ReaderMutex; + UINT32 NumReaders; + +} ACPI_RW_LOCK; + + +/* + * Predefined handles for spinlocks used within the subsystem. + * These spinlocks are created by AcpiUtMutexInitialize + */ +#define ACPI_LOCK_GPES 0 +#define ACPI_LOCK_HARDWARE 1 + +#define ACPI_MAX_LOCK 1 +#define ACPI_NUM_LOCK ACPI_MAX_LOCK+1 + + +/* This Thread ID means that the mutex is not in use (unlocked) */ + +#define ACPI_MUTEX_NOT_ACQUIRED (ACPI_THREAD_ID) -1 + +/* Table for the global mutexes */ + +typedef struct acpi_mutex_info +{ + ACPI_MUTEX Mutex; + UINT32 UseCount; + ACPI_THREAD_ID ThreadId; + +} ACPI_MUTEX_INFO; + + +/* Lock flag parameter for various interfaces */ + +#define ACPI_MTX_DO_NOT_LOCK 0 +#define ACPI_MTX_LOCK 1 + + +/* Field access granularities */ + +#define ACPI_FIELD_BYTE_GRANULARITY 1 +#define ACPI_FIELD_WORD_GRANULARITY 2 +#define ACPI_FIELD_DWORD_GRANULARITY 4 +#define ACPI_FIELD_QWORD_GRANULARITY 8 + + +#define ACPI_ENTRY_NOT_FOUND NULL + + +/***************************************************************************** + * + * Namespace typedefs and structs + * + ****************************************************************************/ + +/* Operational modes of the AML interpreter/scanner */ + +typedef enum +{ + ACPI_IMODE_LOAD_PASS1 = 0x01, + ACPI_IMODE_LOAD_PASS2 = 0x02, + ACPI_IMODE_EXECUTE = 0x03 + +} ACPI_INTERPRETER_MODE; + + +/* + * The Namespace Node describes a named object that appears in the AML. + * DescriptorType is used to differentiate between internal descriptors. + * + * The node is optimized for both 32-bit and 64-bit platforms: + * 20 bytes for the 32-bit case, 32 bytes for the 64-bit case. + * + * Note: The DescriptorType and Type fields must appear in the identical + * position in both the ACPI_NAMESPACE_NODE and ACPI_OPERAND_OBJECT + * structures. + */ +typedef struct acpi_namespace_node +{ + union acpi_operand_object *Object; /* Interpreter object */ + UINT8 DescriptorType; /* Differentiate object descriptor types */ + UINT8 Type; /* ACPI Type associated with this name */ + UINT8 Flags; /* Miscellaneous flags */ + ACPI_OWNER_ID OwnerId; /* Node creator */ + ACPI_NAME_UNION Name; /* ACPI Name, always 4 chars per ACPI spec */ + struct acpi_namespace_node *Parent; /* Parent node */ + struct acpi_namespace_node *Child; /* First child */ + struct acpi_namespace_node *Peer; /* First peer */ + + /* + * The following fields are used by the ASL compiler and disassembler only + */ +#ifdef ACPI_LARGE_NAMESPACE_NODE + union acpi_parse_object *Op; + UINT32 Value; + UINT32 Length; +#endif + +} ACPI_NAMESPACE_NODE; + + +/* Namespace Node flags */ + +#define ANOBJ_RESERVED 0x01 /* Available for use */ +#define ANOBJ_TEMPORARY 0x02 /* Node is create by a method and is temporary */ +#define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */ +#define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */ +#define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */ +#define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ +#define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (InstallMethod) */ + +#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ +#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ +#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */ + + +/* Internal ACPI table management - master table list */ + +typedef struct acpi_table_list +{ + ACPI_TABLE_DESC *Tables; /* Table descriptor array */ + UINT32 CurrentTableCount; /* Tables currently in the array */ + UINT32 MaxTableCount; /* Max tables array will hold */ + UINT8 Flags; + +} ACPI_TABLE_LIST; + +/* Flags for above */ + +#define ACPI_ROOT_ORIGIN_UNKNOWN (0) /* ~ORIGIN_ALLOCATED */ +#define ACPI_ROOT_ORIGIN_ALLOCATED (1) +#define ACPI_ROOT_ALLOW_RESIZE (2) + + +/* Predefined (fixed) table indexes */ + +#define ACPI_TABLE_INDEX_DSDT (0) +#define ACPI_TABLE_INDEX_FACS (1) + + +typedef struct acpi_find_context +{ + char *SearchFor; + ACPI_HANDLE *List; + UINT32 *Count; + +} ACPI_FIND_CONTEXT; + + +typedef struct acpi_ns_search_data +{ + ACPI_NAMESPACE_NODE *Node; + +} ACPI_NS_SEARCH_DATA; + + +/* Object types used during package copies */ + +#define ACPI_COPY_TYPE_SIMPLE 0 +#define ACPI_COPY_TYPE_PACKAGE 1 + + +/* Info structure used to convert external<->internal namestrings */ + +typedef struct acpi_namestring_info +{ + const char *ExternalName; + const char *NextExternalChar; + char *InternalName; + UINT32 Length; + UINT32 NumSegments; + UINT32 NumCarats; + BOOLEAN FullyQualified; + +} ACPI_NAMESTRING_INFO; + + +/* Field creation info */ + +typedef struct acpi_create_field_info +{ + ACPI_NAMESPACE_NODE *RegionNode; + ACPI_NAMESPACE_NODE *FieldNode; + ACPI_NAMESPACE_NODE *RegisterNode; + ACPI_NAMESPACE_NODE *DataRegisterNode; + ACPI_NAMESPACE_NODE *ConnectionNode; + UINT8 *ResourceBuffer; + UINT32 BankValue; + UINT32 FieldBitPosition; + UINT32 FieldBitLength; + UINT16 ResourceLength; + UINT8 FieldFlags; + UINT8 Attribute; + UINT8 FieldType; + UINT8 AccessLength; + +} ACPI_CREATE_FIELD_INFO; + + +typedef +ACPI_STATUS (*ACPI_INTERNAL_METHOD) ( + struct acpi_walk_state *WalkState); + + +/* + * Bitmapped ACPI types. Used internally only + */ +#define ACPI_BTYPE_ANY 0x00000000 +#define ACPI_BTYPE_INTEGER 0x00000001 +#define ACPI_BTYPE_STRING 0x00000002 +#define ACPI_BTYPE_BUFFER 0x00000004 +#define ACPI_BTYPE_PACKAGE 0x00000008 +#define ACPI_BTYPE_FIELD_UNIT 0x00000010 +#define ACPI_BTYPE_DEVICE 0x00000020 +#define ACPI_BTYPE_EVENT 0x00000040 +#define ACPI_BTYPE_METHOD 0x00000080 +#define ACPI_BTYPE_MUTEX 0x00000100 +#define ACPI_BTYPE_REGION 0x00000200 +#define ACPI_BTYPE_POWER 0x00000400 +#define ACPI_BTYPE_PROCESSOR 0x00000800 +#define ACPI_BTYPE_THERMAL 0x00001000 +#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 +#define ACPI_BTYPE_DDB_HANDLE 0x00004000 +#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 +#define ACPI_BTYPE_REFERENCE 0x00010000 +#define ACPI_BTYPE_RESOURCE 0x00020000 + +#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) + +#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) +#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) +#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ +#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF + + +/* + * Information structure for ACPI predefined names. + * Each entry in the table contains the following items: + * + * Name - The ACPI reserved name + * ParamCount - Number of arguments to the method + * ExpectedReturnBtypes - Allowed type(s) for the return value + */ +typedef struct acpi_name_info +{ + char Name[ACPI_NAME_SIZE]; + UINT8 ParamCount; + UINT8 ExpectedBtypes; + +} ACPI_NAME_INFO; + +/* + * Secondary information structures for ACPI predefined objects that return + * package objects. This structure appears as the next entry in the table + * after the NAME_INFO structure above. + * + * The reason for this is to minimize the size of the predefined name table. + */ + +/* + * Used for ACPI_PTYPE1_FIXED, ACPI_PTYPE1_VAR, ACPI_PTYPE2, + * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT, + * ACPI_PTYPE2_FIX_VAR + */ +typedef struct acpi_package_info +{ + UINT8 Type; + UINT8 ObjectType1; + UINT8 Count1; + UINT8 ObjectType2; + UINT8 Count2; + UINT8 Reserved; + +} ACPI_PACKAGE_INFO; + +/* Used for ACPI_PTYPE2_FIXED */ + +typedef struct acpi_package_info2 +{ + UINT8 Type; + UINT8 Count; + UINT8 ObjectType[4]; + +} ACPI_PACKAGE_INFO2; + +/* Used for ACPI_PTYPE1_OPTION */ + +typedef struct acpi_package_info3 +{ + UINT8 Type; + UINT8 Count; + UINT8 ObjectType[2]; + UINT8 TailObjectType; + UINT8 Reserved; + +} ACPI_PACKAGE_INFO3; + +typedef union acpi_predefined_info +{ + ACPI_NAME_INFO Info; + ACPI_PACKAGE_INFO RetInfo; + ACPI_PACKAGE_INFO2 RetInfo2; + ACPI_PACKAGE_INFO3 RetInfo3; + +} ACPI_PREDEFINED_INFO; + + +/* Data block used during object validation */ + +typedef struct acpi_predefined_data +{ + char *Pathname; + const ACPI_PREDEFINED_INFO *Predefined; + union acpi_operand_object *ParentPackage; + ACPI_NAMESPACE_NODE *Node; + UINT32 Flags; + UINT8 NodeFlags; + +} ACPI_PREDEFINED_DATA; + +/* Defines for Flags field above */ + +#define ACPI_OBJECT_REPAIRED 1 + + +/* + * Bitmapped return value types + * Note: the actual data types must be contiguous, a loop in nspredef.c + * depends on this. + */ +#define ACPI_RTYPE_ANY 0x00 +#define ACPI_RTYPE_NONE 0x01 +#define ACPI_RTYPE_INTEGER 0x02 +#define ACPI_RTYPE_STRING 0x04 +#define ACPI_RTYPE_BUFFER 0x08 +#define ACPI_RTYPE_PACKAGE 0x10 +#define ACPI_RTYPE_REFERENCE 0x20 +#define ACPI_RTYPE_ALL 0x3F + +#define ACPI_NUM_RTYPES 5 /* Number of actual object types */ + + +/***************************************************************************** + * + * Event typedefs and structs + * + ****************************************************************************/ + +/* Dispatch info for each GPE -- either a method or handler, cannot be both */ + +typedef struct acpi_gpe_handler_info +{ + ACPI_GPE_HANDLER Address; /* Address of handler, if any */ + void *Context; /* Context to be passed to handler */ + ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level (saved) */ + UINT8 OriginalFlags; /* Original (pre-handler) GPE info */ + BOOLEAN OriginallyEnabled; /* True if GPE was originally enabled */ + +} ACPI_GPE_HANDLER_INFO; + +/* + * GPE dispatch info. At any time, the GPE can have at most one type + * of dispatch - Method, Handler, or Implicit Notify. + */ +typedef union acpi_gpe_dispatch_info +{ + ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level */ + struct acpi_gpe_handler_info *Handler; /* Installed GPE handler */ + ACPI_NAMESPACE_NODE *DeviceNode; /* Parent _PRW device for implicit notify */ + +} ACPI_GPE_DISPATCH_INFO; + +/* + * Information about a GPE, one per each GPE in an array. + * NOTE: Important to keep this struct as small as possible. + */ +typedef struct acpi_gpe_event_info +{ + union acpi_gpe_dispatch_info Dispatch; /* Either Method or Handler */ + struct acpi_gpe_register_info *RegisterInfo; /* Backpointer to register info */ + UINT8 Flags; /* Misc info about this GPE */ + UINT8 GpeNumber; /* This GPE */ + UINT8 RuntimeCount; /* References to a run GPE */ + +} ACPI_GPE_EVENT_INFO; + +/* Information about a GPE register pair, one per each status/enable pair in an array */ + +typedef struct acpi_gpe_register_info +{ + ACPI_GENERIC_ADDRESS StatusAddress; /* Address of status reg */ + ACPI_GENERIC_ADDRESS EnableAddress; /* Address of enable reg */ + UINT8 EnableForWake; /* GPEs to keep enabled when sleeping */ + UINT8 EnableForRun; /* GPEs to keep enabled when running */ + UINT8 BaseGpeNumber; /* Base GPE number for this register */ + +} ACPI_GPE_REGISTER_INFO; + +/* + * Information about a GPE register block, one per each installed block -- + * GPE0, GPE1, and one per each installed GPE Block Device. + */ +typedef struct acpi_gpe_block_info +{ + ACPI_NAMESPACE_NODE *Node; + struct acpi_gpe_block_info *Previous; + struct acpi_gpe_block_info *Next; + struct acpi_gpe_xrupt_info *XruptBlock; /* Backpointer to interrupt block */ + ACPI_GPE_REGISTER_INFO *RegisterInfo; /* One per GPE register pair */ + ACPI_GPE_EVENT_INFO *EventInfo; /* One for each GPE */ + ACPI_GENERIC_ADDRESS BlockAddress; /* Base address of the block */ + UINT32 RegisterCount; /* Number of register pairs in block */ + UINT16 GpeCount; /* Number of individual GPEs in block */ + UINT8 BlockBaseNumber;/* Base GPE number for this block */ + BOOLEAN Initialized; /* TRUE if this block is initialized */ + +} ACPI_GPE_BLOCK_INFO; + +/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ + +typedef struct acpi_gpe_xrupt_info +{ + struct acpi_gpe_xrupt_info *Previous; + struct acpi_gpe_xrupt_info *Next; + ACPI_GPE_BLOCK_INFO *GpeBlockListHead; /* List of GPE blocks for this xrupt */ + UINT32 InterruptNumber; /* System interrupt number */ + +} ACPI_GPE_XRUPT_INFO; + +typedef struct acpi_gpe_walk_info +{ + ACPI_NAMESPACE_NODE *GpeDevice; + ACPI_GPE_BLOCK_INFO *GpeBlock; + UINT16 Count; + ACPI_OWNER_ID OwnerId; + BOOLEAN ExecuteByOwnerId; + +} ACPI_GPE_WALK_INFO; + +typedef struct acpi_gpe_device_info +{ + UINT32 Index; + UINT32 NextBlockBaseIndex; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *GpeDevice; + +} ACPI_GPE_DEVICE_INFO; + +typedef ACPI_STATUS (*ACPI_GPE_CALLBACK) ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + + +/* Information about each particular fixed event */ + +typedef struct acpi_fixed_event_handler +{ + ACPI_EVENT_HANDLER Handler; /* Address of handler. */ + void *Context; /* Context to be passed to handler */ + +} ACPI_FIXED_EVENT_HANDLER; + +typedef struct acpi_fixed_event_info +{ + UINT8 StatusRegisterId; + UINT8 EnableRegisterId; + UINT16 StatusBitMask; + UINT16 EnableBitMask; + +} ACPI_FIXED_EVENT_INFO; + +/* Information used during field processing */ + +typedef struct acpi_field_info +{ + UINT8 SkipField; + UINT8 FieldFlag; + UINT32 PkgLength; + +} ACPI_FIELD_INFO; + + +/***************************************************************************** + * + * Generic "state" object for stacks + * + ****************************************************************************/ + +#define ACPI_CONTROL_NORMAL 0xC0 +#define ACPI_CONTROL_CONDITIONAL_EXECUTING 0xC1 +#define ACPI_CONTROL_PREDICATE_EXECUTING 0xC2 +#define ACPI_CONTROL_PREDICATE_FALSE 0xC3 +#define ACPI_CONTROL_PREDICATE_TRUE 0xC4 + + +#define ACPI_STATE_COMMON \ + void *Next; \ + UINT8 DescriptorType; /* To differentiate various internal objs */\ + UINT8 Flags; \ + UINT16 Value; \ + UINT16 State; + + /* There are 2 bytes available here until the next natural alignment boundary */ + +typedef struct acpi_common_state +{ + ACPI_STATE_COMMON +} ACPI_COMMON_STATE; + + +/* + * Update state - used to traverse complex objects such as packages + */ +typedef struct acpi_update_state +{ + ACPI_STATE_COMMON + union acpi_operand_object *Object; + +} ACPI_UPDATE_STATE; + + +/* + * Pkg state - used to traverse nested package structures + */ +typedef struct acpi_pkg_state +{ + ACPI_STATE_COMMON + UINT16 Index; + union acpi_operand_object *SourceObject; + union acpi_operand_object *DestObject; + struct acpi_walk_state *WalkState; + void *ThisTargetObj; + UINT32 NumPackages; + +} ACPI_PKG_STATE; + + +/* + * Control state - one per if/else and while constructs. + * Allows nesting of these constructs + */ +typedef struct acpi_control_state +{ + ACPI_STATE_COMMON + UINT16 Opcode; + union acpi_parse_object *PredicateOp; + UINT8 *AmlPredicateStart; /* Start of if/while predicate */ + UINT8 *PackageEnd; /* End of if/while block */ + UINT32 LoopCount; /* While() loop counter */ + +} ACPI_CONTROL_STATE; + + +/* + * Scope state - current scope during namespace lookups + */ +typedef struct acpi_scope_state +{ + ACPI_STATE_COMMON + ACPI_NAMESPACE_NODE *Node; + +} ACPI_SCOPE_STATE; + + +typedef struct acpi_pscope_state +{ + ACPI_STATE_COMMON + UINT32 ArgCount; /* Number of fixed arguments */ + union acpi_parse_object *Op; /* Current op being parsed */ + UINT8 *ArgEnd; /* Current argument end */ + UINT8 *PkgEnd; /* Current package end */ + UINT32 ArgList; /* Next argument to parse */ + +} ACPI_PSCOPE_STATE; + + +/* + * Thread state - one per thread across multiple walk states. Multiple walk + * states are created when there are nested control methods executing. + */ +typedef struct acpi_thread_state +{ + ACPI_STATE_COMMON + UINT8 CurrentSyncLevel; /* Mutex Sync (nested acquire) level */ + struct acpi_walk_state *WalkStateList; /* Head of list of WalkStates for this thread */ + union acpi_operand_object *AcquiredMutexList; /* List of all currently acquired mutexes */ + ACPI_THREAD_ID ThreadId; /* Running thread ID */ + +} ACPI_THREAD_STATE; + + +/* + * Result values - used to accumulate the results of nested + * AML arguments + */ +typedef struct acpi_result_values +{ + ACPI_STATE_COMMON + union acpi_operand_object *ObjDesc [ACPI_RESULTS_FRAME_OBJ_NUM]; + +} ACPI_RESULT_VALUES; + + +typedef +ACPI_STATUS (*ACPI_PARSE_DOWNWARDS) ( + struct acpi_walk_state *WalkState, + union acpi_parse_object **OutOp); + +typedef +ACPI_STATUS (*ACPI_PARSE_UPWARDS) ( + struct acpi_walk_state *WalkState); + + +/* + * Notify info - used to pass info to the deferred notify + * handler/dispatcher. + */ +typedef struct acpi_notify_info +{ + ACPI_STATE_COMMON + ACPI_NAMESPACE_NODE *Node; + union acpi_operand_object *HandlerObj; + +} ACPI_NOTIFY_INFO; + + +/* Generic state is union of structs above */ + +typedef union acpi_generic_state +{ + ACPI_COMMON_STATE Common; + ACPI_CONTROL_STATE Control; + ACPI_UPDATE_STATE Update; + ACPI_SCOPE_STATE Scope; + ACPI_PSCOPE_STATE ParseScope; + ACPI_PKG_STATE Pkg; + ACPI_THREAD_STATE Thread; + ACPI_RESULT_VALUES Results; + ACPI_NOTIFY_INFO Notify; + +} ACPI_GENERIC_STATE; + + +/***************************************************************************** + * + * Interpreter typedefs and structs + * + ****************************************************************************/ + +typedef +ACPI_STATUS (*ACPI_EXECUTE_OP) ( + struct acpi_walk_state *WalkState); + +/* Address Range info block */ + +typedef struct acpi_address_range +{ + struct acpi_address_range *Next; + ACPI_NAMESPACE_NODE *RegionNode; + ACPI_PHYSICAL_ADDRESS StartAddress; + ACPI_PHYSICAL_ADDRESS EndAddress; + +} ACPI_ADDRESS_RANGE; + + +/***************************************************************************** + * + * Parser typedefs and structs + * + ****************************************************************************/ + +/* + * AML opcode, name, and argument layout + */ +typedef struct acpi_opcode_info +{ +#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT) + char *Name; /* Opcode name (disassembler/debug only) */ +#endif + UINT32 ParseArgs; /* Grammar/Parse time arguments */ + UINT32 RuntimeArgs; /* Interpret time arguments */ + UINT16 Flags; /* Misc flags */ + UINT8 ObjectType; /* Corresponding internal object type */ + UINT8 Class; /* Opcode class */ + UINT8 Type; /* Opcode type */ + +} ACPI_OPCODE_INFO; + +/* Structure for Resource Tag information */ + +typedef struct acpi_tag_info +{ + UINT32 BitOffset; + UINT32 BitLength; + +} ACPI_TAG_INFO; + +/* Value associated with the parse object */ + +typedef union acpi_parse_value +{ + UINT64 Integer; /* Integer constant (Up to 64 bits) */ + UINT32 Size; /* bytelist or field size */ + char *String; /* NULL terminated string */ + UINT8 *Buffer; /* buffer or string */ + char *Name; /* NULL terminated string */ + union acpi_parse_object *Arg; /* arguments and contained ops */ + ACPI_TAG_INFO Tag; /* Resource descriptor tag info */ + +} ACPI_PARSE_VALUE; + + +#ifdef ACPI_DISASSEMBLER +#define ACPI_DISASM_ONLY_MEMBERS(a) a; +#else +#define ACPI_DISASM_ONLY_MEMBERS(a) +#endif + +#define ACPI_PARSE_COMMON \ + union acpi_parse_object *Parent; /* Parent op */\ + UINT8 DescriptorType; /* To differentiate various internal objs */\ + UINT8 Flags; /* Type of Op */\ + UINT16 AmlOpcode; /* AML opcode */\ + UINT32 AmlOffset; /* Offset of declaration in AML */\ + union acpi_parse_object *Next; /* Next op */\ + ACPI_NAMESPACE_NODE *Node; /* For use by interpreter */\ + ACPI_PARSE_VALUE Value; /* Value or args associated with the opcode */\ + UINT8 ArgListLength; /* Number of elements in the arg list */\ + ACPI_DISASM_ONLY_MEMBERS (\ + UINT8 DisasmFlags; /* Used during AML disassembly */\ + UINT8 DisasmOpcode; /* Subtype used for disassembly */\ + char AmlOpName[16]) /* Op name (debug only) */ + + +#define ACPI_DASM_BUFFER 0x00 +#define ACPI_DASM_RESOURCE 0x01 +#define ACPI_DASM_STRING 0x02 +#define ACPI_DASM_UNICODE 0x03 +#define ACPI_DASM_EISAID 0x04 +#define ACPI_DASM_MATCHOP 0x05 +#define ACPI_DASM_LNOT_PREFIX 0x06 +#define ACPI_DASM_LNOT_SUFFIX 0x07 +#define ACPI_DASM_IGNORE 0x08 + +/* + * Generic operation (for example: If, While, Store) + */ +typedef struct acpi_parse_obj_common +{ + ACPI_PARSE_COMMON +} ACPI_PARSE_OBJ_COMMON; + + +/* + * Extended Op for named ops (Scope, Method, etc.), deferred ops (Methods and OpRegions), + * and bytelists. + */ +typedef struct acpi_parse_obj_named +{ + ACPI_PARSE_COMMON + UINT8 *Path; + UINT8 *Data; /* AML body or bytelist data */ + UINT32 Length; /* AML length */ + UINT32 Name; /* 4-byte name or zero if no name */ + +} ACPI_PARSE_OBJ_NAMED; + + +/* This version is used by the iASL compiler only */ + +#define ACPI_MAX_PARSEOP_NAME 20 + +typedef struct acpi_parse_obj_asl +{ + ACPI_PARSE_COMMON + union acpi_parse_object *Child; + union acpi_parse_object *ParentMethod; + char *Filename; + char *ExternalName; + char *Namepath; + char NameSeg[4]; + UINT32 ExtraValue; + UINT32 Column; + UINT32 LineNumber; + UINT32 LogicalLineNumber; + UINT32 LogicalByteOffset; + UINT32 EndLine; + UINT32 EndLogicalLine; + UINT32 AcpiBtype; + UINT32 AmlLength; + UINT32 AmlSubtreeLength; + UINT32 FinalAmlLength; + UINT32 FinalAmlOffset; + UINT32 CompileFlags; + UINT16 ParseOpcode; + UINT8 AmlOpcodeLength; + UINT8 AmlPkgLenBytes; + UINT8 Extra; + char ParseOpName[ACPI_MAX_PARSEOP_NAME]; + +} ACPI_PARSE_OBJ_ASL; + +typedef union acpi_parse_object +{ + ACPI_PARSE_OBJ_COMMON Common; + ACPI_PARSE_OBJ_NAMED Named; + ACPI_PARSE_OBJ_ASL Asl; + +} ACPI_PARSE_OBJECT; + + +/* + * Parse state - one state per parser invocation and each control + * method. + */ +typedef struct acpi_parse_state +{ + UINT8 *AmlStart; /* First AML byte */ + UINT8 *Aml; /* Next AML byte */ + UINT8 *AmlEnd; /* (last + 1) AML byte */ + UINT8 *PkgStart; /* Current package begin */ + UINT8 *PkgEnd; /* Current package end */ + union acpi_parse_object *StartOp; /* Root of parse tree */ + struct acpi_namespace_node *StartNode; + union acpi_generic_state *Scope; /* Current scope */ + union acpi_parse_object *StartScope; + UINT32 AmlSize; + +} ACPI_PARSE_STATE; + + +/* Parse object flags */ + +#define ACPI_PARSEOP_GENERIC 0x01 +#define ACPI_PARSEOP_NAMED 0x02 +#define ACPI_PARSEOP_DEFERRED 0x04 +#define ACPI_PARSEOP_BYTELIST 0x08 +#define ACPI_PARSEOP_IN_STACK 0x10 +#define ACPI_PARSEOP_TARGET 0x20 +#define ACPI_PARSEOP_IN_CACHE 0x80 + +/* Parse object DisasmFlags */ + +#define ACPI_PARSEOP_IGNORE 0x01 +#define ACPI_PARSEOP_PARAMLIST 0x02 +#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 +#define ACPI_PARSEOP_SPECIAL 0x10 + + +/***************************************************************************** + * + * Hardware (ACPI registers) and PNP + * + ****************************************************************************/ + +typedef struct acpi_bit_register_info +{ + UINT8 ParentRegister; + UINT8 BitPosition; + UINT16 AccessBitMask; + +} ACPI_BIT_REGISTER_INFO; + + +/* + * Some ACPI registers have bits that must be ignored -- meaning that they + * must be preserved. + */ +#define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */ + +/* Write-only bits must be zeroed by software */ + +#define ACPI_PM1_CONTROL_WRITEONLY_BITS 0x2004 /* Bits 13, 2 */ + +/* For control registers, both ignored and reserved bits must be preserved */ + +/* + * For PM1 control, the SCI enable bit (bit 0, SCI_EN) is defined by the + * ACPI specification to be a "preserved" bit - "OSPM always preserves this + * bit position", section 4.7.3.2.1. However, on some machines the OS must + * write a one to this bit after resume for the machine to work properly. + * To enable this, we no longer attempt to preserve this bit. No machines + * are known to fail if the bit is not preserved. (May 2009) + */ +#define ACPI_PM1_CONTROL_IGNORED_BITS 0x0200 /* Bit 9 */ +#define ACPI_PM1_CONTROL_RESERVED_BITS 0xC1F8 /* Bits 14-15, 3-8 */ +#define ACPI_PM1_CONTROL_PRESERVED_BITS \ + (ACPI_PM1_CONTROL_IGNORED_BITS | ACPI_PM1_CONTROL_RESERVED_BITS) + +#define ACPI_PM2_CONTROL_PRESERVED_BITS 0xFFFFFFFE /* All except bit 0 */ + +/* + * Register IDs + * These are the full ACPI registers + */ +#define ACPI_REGISTER_PM1_STATUS 0x01 +#define ACPI_REGISTER_PM1_ENABLE 0x02 +#define ACPI_REGISTER_PM1_CONTROL 0x03 +#define ACPI_REGISTER_PM2_CONTROL 0x04 +#define ACPI_REGISTER_PM_TIMER 0x05 +#define ACPI_REGISTER_PROCESSOR_BLOCK 0x06 +#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x07 + + +/* Masks used to access the BitRegisters */ + +#define ACPI_BITMASK_TIMER_STATUS 0x0001 +#define ACPI_BITMASK_BUS_MASTER_STATUS 0x0010 +#define ACPI_BITMASK_GLOBAL_LOCK_STATUS 0x0020 +#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200 +#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ +#define ACPI_BITMASK_WAKE_STATUS 0x8000 + +#define ACPI_BITMASK_ALL_FIXED_STATUS (\ + ACPI_BITMASK_TIMER_STATUS | \ + ACPI_BITMASK_BUS_MASTER_STATUS | \ + ACPI_BITMASK_GLOBAL_LOCK_STATUS | \ + ACPI_BITMASK_POWER_BUTTON_STATUS | \ + ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ + ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_PCIEXP_WAKE_STATUS | \ + ACPI_BITMASK_WAKE_STATUS) + +#define ACPI_BITMASK_TIMER_ENABLE 0x0001 +#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020 +#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200 +#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */ + +#define ACPI_BITMASK_SCI_ENABLE 0x0001 +#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 +#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004 +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 +#define ACPI_BITMASK_SLEEP_ENABLE 0x2000 + +#define ACPI_BITMASK_ARB_DISABLE 0x0001 + + +/* Raw bit position of each BitRegister */ + +#define ACPI_BITPOSITION_TIMER_STATUS 0x00 +#define ACPI_BITPOSITION_BUS_MASTER_STATUS 0x04 +#define ACPI_BITPOSITION_GLOBAL_LOCK_STATUS 0x05 +#define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08 +#define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09 +#define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */ +#define ACPI_BITPOSITION_WAKE_STATUS 0x0F + +#define ACPI_BITPOSITION_TIMER_ENABLE 0x00 +#define ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE 0x05 +#define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08 +#define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09 +#define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */ + +#define ACPI_BITPOSITION_SCI_ENABLE 0x00 +#define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01 +#define ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE 0x02 +#define ACPI_BITPOSITION_SLEEP_TYPE 0x0A +#define ACPI_BITPOSITION_SLEEP_ENABLE 0x0D + +#define ACPI_BITPOSITION_ARB_DISABLE 0x00 + + +/* Structs and definitions for _OSI support and I/O port validation */ + +#define ACPI_OSI_WIN_2000 0x01 +#define ACPI_OSI_WIN_XP 0x02 +#define ACPI_OSI_WIN_XP_SP1 0x03 +#define ACPI_OSI_WINSRV_2003 0x04 +#define ACPI_OSI_WIN_XP_SP2 0x05 +#define ACPI_OSI_WINSRV_2003_SP1 0x06 +#define ACPI_OSI_WIN_VISTA 0x07 +#define ACPI_OSI_WINSRV_2008 0x08 +#define ACPI_OSI_WIN_VISTA_SP1 0x09 +#define ACPI_OSI_WIN_VISTA_SP2 0x0A +#define ACPI_OSI_WIN_7 0x0B + +#define ACPI_ALWAYS_ILLEGAL 0x00 + +typedef struct acpi_interface_info +{ + char *Name; + struct acpi_interface_info *Next; + UINT8 Flags; + UINT8 Value; + +} ACPI_INTERFACE_INFO; + +#define ACPI_OSI_INVALID 0x01 +#define ACPI_OSI_DYNAMIC 0x02 + +typedef struct acpi_port_info +{ + char *Name; + UINT16 Start; + UINT16 End; + UINT8 OsiDependency; + +} ACPI_PORT_INFO; + + +/***************************************************************************** + * + * Resource descriptors + * + ****************************************************************************/ + +/* ResourceType values */ + +#define ACPI_ADDRESS_TYPE_MEMORY_RANGE 0 +#define ACPI_ADDRESS_TYPE_IO_RANGE 1 +#define ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE 2 + +/* Resource descriptor types and masks */ + +#define ACPI_RESOURCE_NAME_LARGE 0x80 +#define ACPI_RESOURCE_NAME_SMALL 0x00 + +#define ACPI_RESOURCE_NAME_SMALL_MASK 0x78 /* Bits 6:3 contain the type */ +#define ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK 0x07 /* Bits 2:0 contain the length */ +#define ACPI_RESOURCE_NAME_LARGE_MASK 0x7F /* Bits 6:0 contain the type */ + + +/* + * Small resource descriptor "names" as defined by the ACPI specification. + * Note: Bits 2:0 are used for the descriptor length + */ +#define ACPI_RESOURCE_NAME_IRQ 0x20 +#define ACPI_RESOURCE_NAME_DMA 0x28 +#define ACPI_RESOURCE_NAME_START_DEPENDENT 0x30 +#define ACPI_RESOURCE_NAME_END_DEPENDENT 0x38 +#define ACPI_RESOURCE_NAME_IO 0x40 +#define ACPI_RESOURCE_NAME_FIXED_IO 0x48 +#define ACPI_RESOURCE_NAME_FIXED_DMA 0x50 +#define ACPI_RESOURCE_NAME_RESERVED_S2 0x58 +#define ACPI_RESOURCE_NAME_RESERVED_S3 0x60 +#define ACPI_RESOURCE_NAME_RESERVED_S4 0x68 +#define ACPI_RESOURCE_NAME_VENDOR_SMALL 0x70 +#define ACPI_RESOURCE_NAME_END_TAG 0x78 + +/* + * Large resource descriptor "names" as defined by the ACPI specification. + * Note: includes the Large Descriptor bit in bit[7] + */ +#define ACPI_RESOURCE_NAME_MEMORY24 0x81 +#define ACPI_RESOURCE_NAME_GENERIC_REGISTER 0x82 +#define ACPI_RESOURCE_NAME_RESERVED_L1 0x83 +#define ACPI_RESOURCE_NAME_VENDOR_LARGE 0x84 +#define ACPI_RESOURCE_NAME_MEMORY32 0x85 +#define ACPI_RESOURCE_NAME_FIXED_MEMORY32 0x86 +#define ACPI_RESOURCE_NAME_ADDRESS32 0x87 +#define ACPI_RESOURCE_NAME_ADDRESS16 0x88 +#define ACPI_RESOURCE_NAME_EXTENDED_IRQ 0x89 +#define ACPI_RESOURCE_NAME_ADDRESS64 0x8A +#define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 0x8B +#define ACPI_RESOURCE_NAME_GPIO 0x8C +#define ACPI_RESOURCE_NAME_SERIAL_BUS 0x8E +#define ACPI_RESOURCE_NAME_LARGE_MAX 0x8E + + +/***************************************************************************** + * + * Miscellaneous + * + ****************************************************************************/ + +#define ACPI_ASCII_ZERO 0x30 + + +/***************************************************************************** + * + * Disassembler + * + ****************************************************************************/ + +typedef struct acpi_external_list +{ + char *Path; + char *InternalPath; + struct acpi_external_list *Next; + UINT32 Value; + UINT16 Length; + UINT8 Type; + UINT8 Flags; + +} ACPI_EXTERNAL_LIST; + +/* Values for Flags field above */ + +#define ACPI_IPATH_ALLOCATED 0x01 + + +typedef struct acpi_external_file +{ + char *Path; + struct acpi_external_file *Next; + +} ACPI_EXTERNAL_FILE; + + +/***************************************************************************** + * + * Debugger + * + ****************************************************************************/ + +typedef struct acpi_db_method_info +{ + ACPI_HANDLE MainThreadGate; + ACPI_HANDLE ThreadCompleteGate; + ACPI_HANDLE InfoGate; + ACPI_THREAD_ID *Threads; + UINT32 NumThreads; + UINT32 NumCreated; + UINT32 NumCompleted; + + char *Name; + UINT32 Flags; + UINT32 NumLoops; + char Pathname[128]; + char **Args; + ACPI_OBJECT_TYPE *Types; + + /* + * Arguments to be passed to method for the command + * Threads - + * the Number of threads, ID of current thread and + * Index of current thread inside all them created. + */ + char InitArgs; + ACPI_OBJECT_TYPE ArgTypes[4]; + char *Arguments[4]; + char NumThreadsStr[11]; + char IdOfThreadStr[11]; + char IndexOfThreadStr[11]; + +} ACPI_DB_METHOD_INFO; + +typedef struct acpi_integrity_info +{ + UINT32 Nodes; + UINT32 Objects; + +} ACPI_INTEGRITY_INFO; + + +#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 +#define ACPI_DB_CONSOLE_OUTPUT 0x02 +#define ACPI_DB_DUPLICATE_OUTPUT 0x03 + + +/***************************************************************************** + * + * Debug + * + ****************************************************************************/ + +/* Entry for a memory allocation (debug only) */ + +#define ACPI_MEM_MALLOC 0 +#define ACPI_MEM_CALLOC 1 +#define ACPI_MAX_MODULE_NAME 16 + +#define ACPI_COMMON_DEBUG_MEM_HEADER \ + struct acpi_debug_mem_block *Previous; \ + struct acpi_debug_mem_block *Next; \ + UINT32 Size; \ + UINT32 Component; \ + UINT32 Line; \ + char Module[ACPI_MAX_MODULE_NAME]; \ + UINT8 AllocType; + +typedef struct acpi_debug_mem_header +{ + ACPI_COMMON_DEBUG_MEM_HEADER + +} ACPI_DEBUG_MEM_HEADER; + +typedef struct acpi_debug_mem_block +{ + ACPI_COMMON_DEBUG_MEM_HEADER + UINT64 UserSpace; + +} ACPI_DEBUG_MEM_BLOCK; + + +#define ACPI_MEM_LIST_GLOBAL 0 +#define ACPI_MEM_LIST_NSNODE 1 +#define ACPI_MEM_LIST_MAX 1 +#define ACPI_NUM_MEM_LISTS 2 + + +#endif /* __ACLOCAL_H__ */ diff --git a/source/include/acmacros.h b/source/include/acmacros.h new file mode 100644 index 000000000000..cdb9cb109e06 --- /dev/null +++ b/source/include/acmacros.h @@ -0,0 +1,540 @@ +/****************************************************************************** + * + * Name: acmacros.h - C macros for the entire subsystem. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACMACROS_H__ +#define __ACMACROS_H__ + + +/* + * Extract data using a pointer. Any more than a byte and we + * get into potential aligment issues -- see the STORE macros below. + * Use with care. + */ +#define ACPI_GET8(ptr) *ACPI_CAST_PTR (UINT8, ptr) +#define ACPI_GET16(ptr) *ACPI_CAST_PTR (UINT16, ptr) +#define ACPI_GET32(ptr) *ACPI_CAST_PTR (UINT32, ptr) +#define ACPI_GET64(ptr) *ACPI_CAST_PTR (UINT64, ptr) +#define ACPI_SET8(ptr) *ACPI_CAST_PTR (UINT8, ptr) +#define ACPI_SET16(ptr) *ACPI_CAST_PTR (UINT16, ptr) +#define ACPI_SET32(ptr) *ACPI_CAST_PTR (UINT32, ptr) +#define ACPI_SET64(ptr) *ACPI_CAST_PTR (UINT64, ptr) + +/* + * printf() format helpers + */ + +/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ + +#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#else +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#endif + + +/* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. + * Otherwise, we have to move one byte at a time. + */ +#ifdef ACPI_BIG_ENDIAN +/* + * Macros for big-endian machines + */ + +/* These macros reverse the bytes during the move, converting little-endian to big endian */ + + /* Big Endian <== Little Endian */ + /* Hi...Lo Lo...Hi */ +/* 16-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_16_TO_16(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[1];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[0];} + +#define ACPI_MOVE_16_TO_32(d, s) {(*(UINT32 *)(void *)(d))=0;\ + ((UINT8 *)(void *)(d))[2] = ((UINT8 *)(void *)(s))[1];\ + ((UINT8 *)(void *)(d))[3] = ((UINT8 *)(void *)(s))[0];} + +#define ACPI_MOVE_16_TO_64(d, s) {(*(UINT64 *)(void *)(d))=0;\ + ((UINT8 *)(void *)(d))[6] = ((UINT8 *)(void *)(s))[1];\ + ((UINT8 *)(void *)(d))[7] = ((UINT8 *)(void *)(s))[0];} + +/* 32-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ + +#define ACPI_MOVE_32_TO_32(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[3];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[2];\ + (( UINT8 *)(void *)(d))[2] = ((UINT8 *)(void *)(s))[1];\ + (( UINT8 *)(void *)(d))[3] = ((UINT8 *)(void *)(s))[0];} + +#define ACPI_MOVE_32_TO_64(d, s) {(*(UINT64 *)(void *)(d))=0;\ + ((UINT8 *)(void *)(d))[4] = ((UINT8 *)(void *)(s))[3];\ + ((UINT8 *)(void *)(d))[5] = ((UINT8 *)(void *)(s))[2];\ + ((UINT8 *)(void *)(d))[6] = ((UINT8 *)(void *)(s))[1];\ + ((UINT8 *)(void *)(d))[7] = ((UINT8 *)(void *)(s))[0];} + +/* 64-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ + +#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */ + +#define ACPI_MOVE_64_TO_64(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[7];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[6];\ + (( UINT8 *)(void *)(d))[2] = ((UINT8 *)(void *)(s))[5];\ + (( UINT8 *)(void *)(d))[3] = ((UINT8 *)(void *)(s))[4];\ + (( UINT8 *)(void *)(d))[4] = ((UINT8 *)(void *)(s))[3];\ + (( UINT8 *)(void *)(d))[5] = ((UINT8 *)(void *)(s))[2];\ + (( UINT8 *)(void *)(d))[6] = ((UINT8 *)(void *)(s))[1];\ + (( UINT8 *)(void *)(d))[7] = ((UINT8 *)(void *)(s))[0];} +#else +/* + * Macros for little-endian machines + */ + +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED + +/* The hardware supports unaligned transfers, just do the little-endian move */ + +/* 16-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_16_TO_16(d, s) *(UINT16 *)(void *)(d) = *(UINT16 *)(void *)(s) +#define ACPI_MOVE_16_TO_32(d, s) *(UINT32 *)(void *)(d) = *(UINT16 *)(void *)(s) +#define ACPI_MOVE_16_TO_64(d, s) *(UINT64 *)(void *)(d) = *(UINT16 *)(void *)(s) + +/* 32-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ +#define ACPI_MOVE_32_TO_32(d, s) *(UINT32 *)(void *)(d) = *(UINT32 *)(void *)(s) +#define ACPI_MOVE_32_TO_64(d, s) *(UINT64 *)(void *)(d) = *(UINT32 *)(void *)(s) + +/* 64-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ +#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */ +#define ACPI_MOVE_64_TO_64(d, s) *(UINT64 *)(void *)(d) = *(UINT64 *)(void *)(s) + +#else +/* + * The hardware does not support unaligned transfers. We must move the + * data one byte at a time. These macros work whether the source or + * the destination (or both) is/are unaligned. (Little-endian move) + */ + +/* 16-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_16_TO_16(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[0];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[1];} + +#define ACPI_MOVE_16_TO_32(d, s) {(*(UINT32 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);} +#define ACPI_MOVE_16_TO_64(d, s) {(*(UINT64 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);} + +/* 32-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ + +#define ACPI_MOVE_32_TO_32(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[0];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[1];\ + (( UINT8 *)(void *)(d))[2] = ((UINT8 *)(void *)(s))[2];\ + (( UINT8 *)(void *)(d))[3] = ((UINT8 *)(void *)(s))[3];} + +#define ACPI_MOVE_32_TO_64(d, s) {(*(UINT64 *)(void *)(d)) = 0; ACPI_MOVE_32_TO_32(d, s);} + +/* 64-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ +#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */ +#define ACPI_MOVE_64_TO_64(d, s) {(( UINT8 *)(void *)(d))[0] = ((UINT8 *)(void *)(s))[0];\ + (( UINT8 *)(void *)(d))[1] = ((UINT8 *)(void *)(s))[1];\ + (( UINT8 *)(void *)(d))[2] = ((UINT8 *)(void *)(s))[2];\ + (( UINT8 *)(void *)(d))[3] = ((UINT8 *)(void *)(s))[3];\ + (( UINT8 *)(void *)(d))[4] = ((UINT8 *)(void *)(s))[4];\ + (( UINT8 *)(void *)(d))[5] = ((UINT8 *)(void *)(s))[5];\ + (( UINT8 *)(void *)(d))[6] = ((UINT8 *)(void *)(s))[6];\ + (( UINT8 *)(void *)(d))[7] = ((UINT8 *)(void *)(s))[7];} +#endif +#endif + + +/* + * Fast power-of-two math macros for non-optimized compilers + */ +#define _ACPI_DIV(value, PowerOf2) ((UINT32) ((value) >> (PowerOf2))) +#define _ACPI_MUL(value, PowerOf2) ((UINT32) ((value) << (PowerOf2))) +#define _ACPI_MOD(value, Divisor) ((UINT32) ((value) & ((Divisor) -1))) + +#define ACPI_DIV_2(a) _ACPI_DIV(a, 1) +#define ACPI_MUL_2(a) _ACPI_MUL(a, 1) +#define ACPI_MOD_2(a) _ACPI_MOD(a, 2) + +#define ACPI_DIV_4(a) _ACPI_DIV(a, 2) +#define ACPI_MUL_4(a) _ACPI_MUL(a, 2) +#define ACPI_MOD_4(a) _ACPI_MOD(a, 4) + +#define ACPI_DIV_8(a) _ACPI_DIV(a, 3) +#define ACPI_MUL_8(a) _ACPI_MUL(a, 3) +#define ACPI_MOD_8(a) _ACPI_MOD(a, 8) + +#define ACPI_DIV_16(a) _ACPI_DIV(a, 4) +#define ACPI_MUL_16(a) _ACPI_MUL(a, 4) +#define ACPI_MOD_16(a) _ACPI_MOD(a, 16) + +#define ACPI_DIV_32(a) _ACPI_DIV(a, 5) +#define ACPI_MUL_32(a) _ACPI_MUL(a, 5) +#define ACPI_MOD_32(a) _ACPI_MOD(a, 32) + +/* + * Rounding macros (Power of two boundaries only) + */ +#define ACPI_ROUND_DOWN(value, boundary) (((ACPI_SIZE)(value)) & \ + (~(((ACPI_SIZE) boundary)-1))) + +#define ACPI_ROUND_UP(value, boundary) ((((ACPI_SIZE)(value)) + \ + (((ACPI_SIZE) boundary)-1)) & \ + (~(((ACPI_SIZE) boundary)-1))) + +/* Note: sizeof(ACPI_SIZE) evaluates to either 4 or 8 (32- vs 64-bit mode) */ + +#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a, 4) +#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a, 8) +#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a, sizeof(ACPI_SIZE)) + +#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a, 4) +#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a, 8) +#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a, sizeof(ACPI_SIZE)) + +#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7) +#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a)) + +#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10) + +/* Generic (non-power-of-two) rounding */ + +#define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary)) + +#define ACPI_IS_MISALIGNED(value) (((ACPI_SIZE) value) & (sizeof(ACPI_SIZE)-1)) + +/* + * Bitmask creation + * Bit positions start at zero. + * MASK_BITS_ABOVE creates a mask starting AT the position and above + * MASK_BITS_BELOW creates a mask starting one bit BELOW the position + */ +#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_UINT64_MAX) << ((UINT32) (position)))) +#define ACPI_MASK_BITS_BELOW(position) ((ACPI_UINT64_MAX) << ((UINT32) (position))) + +/* Bitfields within ACPI registers */ + +#define ACPI_REGISTER_PREPARE_BITS(Val, Pos, Mask) ((Val << Pos) & Mask) +#define ACPI_REGISTER_INSERT_VALUE(Reg, Pos, Mask, Val) Reg = (Reg & (~(Mask))) | ACPI_REGISTER_PREPARE_BITS(Val, Pos, Mask) + +#define ACPI_INSERT_BITS(Target, Mask, Source) Target = ((Target & (~(Mask))) | (Source & Mask)) + +/* + * An ACPI_NAMESPACE_NODE can appear in some contexts + * where a pointer to an ACPI_OPERAND_OBJECT can also + * appear. This macro is used to distinguish them. + * + * The "Descriptor" field is the first field in both structures. + */ +#define ACPI_GET_DESCRIPTOR_TYPE(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType) +#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType = t) + +/* + * Macros for the master AML opcode table + */ +#if defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) +#define ACPI_OP(Name, PArgs, IArgs, ObjType, Class, Type, Flags) \ + {Name, (UINT32)(PArgs), (UINT32)(IArgs), (UINT32)(Flags), ObjType, Class, Type} +#else +#define ACPI_OP(Name, PArgs, IArgs, ObjType, Class, Type, Flags) \ + {(UINT32)(PArgs), (UINT32)(IArgs), (UINT32)(Flags), ObjType, Class, Type} +#endif + +#define ARG_TYPE_WIDTH 5 +#define ARG_1(x) ((UINT32)(x)) +#define ARG_2(x) ((UINT32)(x) << (1 * ARG_TYPE_WIDTH)) +#define ARG_3(x) ((UINT32)(x) << (2 * ARG_TYPE_WIDTH)) +#define ARG_4(x) ((UINT32)(x) << (3 * ARG_TYPE_WIDTH)) +#define ARG_5(x) ((UINT32)(x) << (4 * ARG_TYPE_WIDTH)) +#define ARG_6(x) ((UINT32)(x) << (5 * ARG_TYPE_WIDTH)) + +#define ARGI_LIST1(a) (ARG_1(a)) +#define ARGI_LIST2(a, b) (ARG_1(b)|ARG_2(a)) +#define ARGI_LIST3(a, b, c) (ARG_1(c)|ARG_2(b)|ARG_3(a)) +#define ARGI_LIST4(a, b, c, d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a)) +#define ARGI_LIST5(a, b, c, d, e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a)) +#define ARGI_LIST6(a, b, c, d, e, f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a)) + +#define ARGP_LIST1(a) (ARG_1(a)) +#define ARGP_LIST2(a, b) (ARG_1(a)|ARG_2(b)) +#define ARGP_LIST3(a, b, c) (ARG_1(a)|ARG_2(b)|ARG_3(c)) +#define ARGP_LIST4(a, b, c, d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)) +#define ARGP_LIST5(a, b, c, d, e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)) +#define ARGP_LIST6(a, b, c, d, e, f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f)) + +#define GET_CURRENT_ARG_TYPE(List) (List & ((UINT32) 0x1F)) +#define INCREMENT_ARG_LIST(List) (List >>= ((UINT32) ARG_TYPE_WIDTH)) + +/* + * Ascii error messages can be configured out + */ +#ifndef ACPI_NO_ERROR_MESSAGES +/* + * Error reporting. Callers module and line number are inserted by AE_INFO, + * the plist contains a set of parens to allow variable-length lists. + * These macros are used for both the debug and non-debug versions of the code. + */ +#define ACPI_ERROR_NAMESPACE(s, e) AcpiUtNamespaceError (AE_INFO, s, e); +#define ACPI_ERROR_METHOD(s, n, p, e) AcpiUtMethodError (AE_INFO, s, n, p, e); +#define ACPI_WARN_PREDEFINED(plist) AcpiUtPredefinedWarning plist +#define ACPI_INFO_PREDEFINED(plist) AcpiUtPredefinedInfo plist + +#else + +/* No error messages */ + +#define ACPI_ERROR_NAMESPACE(s, e) +#define ACPI_ERROR_METHOD(s, n, p, e) +#define ACPI_WARN_PREDEFINED(plist) +#define ACPI_INFO_PREDEFINED(plist) + +#endif /* ACPI_NO_ERROR_MESSAGES */ + +/* + * Debug macros that are conditionally compiled + */ +#ifdef ACPI_DEBUG_OUTPUT +/* + * Function entry tracing + */ +#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ + AcpiUtTrace(ACPI_DEBUG_PARAMETERS) +#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \ + AcpiUtTracePtr(ACPI_DEBUG_PARAMETERS, (void *)b) +#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \ + AcpiUtTraceU32(ACPI_DEBUG_PARAMETERS, (UINT32)b) +#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \ + AcpiUtTraceStr(ACPI_DEBUG_PARAMETERS, (char *)b) + +#define ACPI_FUNCTION_ENTRY() AcpiUtTrackStackPtr() + +/* + * Function exit tracing. + * WARNING: These macros include a return statement. This is usually considered + * bad form, but having a separate exit macro is very ugly and difficult to maintain. + * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros + * so that "_AcpiFunctionName" is defined. + * + * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining + * about these constructs. + */ +#ifdef ACPI_USE_DO_WHILE_0 +#define ACPI_DO_WHILE0(a) do a while(0) +#else +#define ACPI_DO_WHILE0(a) a +#endif + +#define return_VOID ACPI_DO_WHILE0 ({ \ + AcpiUtExit (ACPI_DEBUG_PARAMETERS); \ + return;}) +/* + * There are two versions of most of the return macros. The default version is + * safer, since it avoids side-effects by guaranteeing that the argument will + * not be evaluated twice. + * + * A less-safe version of the macros is provided for optional use if the + * compiler uses excessive CPU stack (for example, this may happen in the + * debug case if code optimzation is disabled.) + */ +#ifndef ACPI_SIMPLE_RETURN_MACROS + +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ + register ACPI_STATUS _s = (s); \ + AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, _s); \ + return (_s); }) +#define return_PTR(s) ACPI_DO_WHILE0 ({ \ + register void *_s = (void *) (s); \ + AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) _s); \ + return (_s); }) +#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ + register UINT64 _s = (s); \ + AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, _s); \ + return (_s); }) +#define return_UINT8(s) ACPI_DO_WHILE0 ({ \ + register UINT8 _s = (UINT8) (s); \ + AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \ + return (_s); }) +#define return_UINT32(s) ACPI_DO_WHILE0 ({ \ + register UINT32 _s = (UINT32) (s); \ + AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \ + return (_s); }) +#else /* Use original less-safe macros */ + +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ + AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, (s)); \ + return((s)); }) +#define return_PTR(s) ACPI_DO_WHILE0 ({ \ + AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) (s)); \ + return((s)); }) +#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ + AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) (s)); \ + return((s)); }) +#define return_UINT8(s) return_VALUE(s) +#define return_UINT32(s) return_VALUE(s) + +#endif /* ACPI_SIMPLE_RETURN_MACROS */ + +/* Conditional execution */ + +#define ACPI_DEBUG_EXEC(a) a +#define ACPI_DEBUG_ONLY_MEMBERS(a) a; +#define _VERBOSE_STRUCTURES + + +/* Various object display routines for debug */ + +#define ACPI_DUMP_STACK_ENTRY(a) AcpiExDumpOperand((a), 0) +#define ACPI_DUMP_OPERANDS(a, b ,c) AcpiExDumpOperands(a, b, c) +#define ACPI_DUMP_ENTRY(a, b) AcpiNsDumpEntry (a, b) +#define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d) +#define ACPI_DUMP_BUFFER(a, b) AcpiUtDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) + +#else +/* + * This is the non-debug case -- make everything go away, + * leaving no executable debug code! + */ +#define ACPI_DEBUG_EXEC(a) +#define ACPI_DEBUG_ONLY_MEMBERS(a) +#define ACPI_FUNCTION_TRACE(a) +#define ACPI_FUNCTION_TRACE_PTR(a, b) +#define ACPI_FUNCTION_TRACE_U32(a, b) +#define ACPI_FUNCTION_TRACE_STR(a, b) +#define ACPI_FUNCTION_EXIT +#define ACPI_FUNCTION_STATUS_EXIT(s) +#define ACPI_FUNCTION_VALUE_EXIT(s) +#define ACPI_FUNCTION_ENTRY() +#define ACPI_DUMP_STACK_ENTRY(a) +#define ACPI_DUMP_OPERANDS(a, b, c) +#define ACPI_DUMP_ENTRY(a, b) +#define ACPI_DUMP_TABLES(a, b) +#define ACPI_DUMP_PATHNAME(a, b, c, d) +#define ACPI_DUMP_BUFFER(a, b) +#define ACPI_DEBUG_PRINT(pl) +#define ACPI_DEBUG_PRINT_RAW(pl) + +#define return_VOID return +#define return_ACPI_STATUS(s) return(s) +#define return_VALUE(s) return(s) +#define return_UINT8(s) return(s) +#define return_UINT32(s) return(s) +#define return_PTR(s) return(s) + +#endif /* ACPI_DEBUG_OUTPUT */ + + +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr +#else +#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL +#endif + + +/* + * Some code only gets executed when the debugger is built in. + * Note that this is entirely independent of whether the + * DEBUG_PRINT stuff (set by ACPI_DEBUG_OUTPUT) is on, or not. + */ +#ifdef ACPI_DEBUGGER +#define ACPI_DEBUGGER_EXEC(a) a +#else +#define ACPI_DEBUGGER_EXEC(a) +#endif + + +/* + * Memory allocation tracking (DEBUG ONLY) + */ +#define ACPI_MEM_PARAMETERS _COMPONENT, _AcpiModuleName, __LINE__ + +#ifndef ACPI_DBG_TRACK_ALLOCATIONS + +/* Memory allocation */ + +#define ACPI_ALLOCATE(a) AcpiUtAllocate((ACPI_SIZE) (a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE_ZEROED(a) AcpiUtAllocateZeroed((ACPI_SIZE) (a), ACPI_MEM_PARAMETERS) +#define ACPI_FREE(a) AcpiOsFree(a) +#define ACPI_MEM_TRACKING(a) + +#else + +/* Memory allocation */ + +#define ACPI_ALLOCATE(a) AcpiUtAllocateAndTrack((ACPI_SIZE) (a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE_ZEROED(a) AcpiUtAllocateZeroedAndTrack((ACPI_SIZE) (a), ACPI_MEM_PARAMETERS) +#define ACPI_FREE(a) AcpiUtFreeAndTrack(a, ACPI_MEM_PARAMETERS) +#define ACPI_MEM_TRACKING(a) a + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + + +/* + * Macros used for ACPICA utilities only + */ + +/* Generate a UUID */ + +#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \ + (b) & 0xFF, ((b) >> 8) & 0xFF, \ + (c) & 0xFF, ((c) >> 8) & 0xFF, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) + +#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) + + +#endif /* ACMACROS_H */ diff --git a/source/include/acnames.h b/source/include/acnames.h new file mode 100644 index 000000000000..f0bbde8541c1 --- /dev/null +++ b/source/include/acnames.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Name: acnames.h - Global names and strings + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACNAMES_H__ +#define __ACNAMES_H__ + +/* Method names - these methods can appear anywhere in the namespace */ + +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__CID "_CID" +#define METHOD_NAME__UID "_UID" +#define METHOD_NAME__ADR "_ADR" +#define METHOD_NAME__INI "_INI" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__BBN "_BBN" +#define METHOD_NAME__PRT "_PRT" +#define METHOD_NAME__CRS "_CRS" +#define METHOD_NAME__PRS "_PRS" +#define METHOD_NAME__AEI "_AEI" +#define METHOD_NAME__PRW "_PRW" +#define METHOD_NAME__SRS "_SRS" + +/* Method names - these methods must appear at the namespace root */ + +#define METHOD_NAME__BFS "\\_BFS" +#define METHOD_NAME__GTS "\\_GTS" +#define METHOD_NAME__PTS "\\_PTS" +#define METHOD_NAME__SST "\\_SI._SST" +#define METHOD_NAME__WAK "\\_WAK" + +/* Definitions of the predefined namespace names */ + +#define ACPI_UNKNOWN_NAME (UINT32) 0x3F3F3F3F /* Unknown name is "????" */ +#define ACPI_ROOT_NAME (UINT32) 0x5F5F5F5C /* Root name is "\___" */ + +#define ACPI_PREFIX_MIXED (UINT32) 0x69706341 /* "Acpi" */ +#define ACPI_PREFIX_LOWER (UINT32) 0x69706361 /* "acpi" */ + +#define ACPI_NS_ROOT_PATH "\\" +#define ACPI_NS_SYSTEM_BUS "_SB_" + +#endif /* __ACNAMES_H__ */ + + diff --git a/source/include/acnamesp.h b/source/include/acnamesp.h new file mode 100644 index 000000000000..5e22cb538895 --- /dev/null +++ b/source/include/acnamesp.h @@ -0,0 +1,477 @@ +/****************************************************************************** + * + * Name: acnamesp.h - Namespace subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACNAMESP_H__ +#define __ACNAMESP_H__ + + +/* To search the entire name space, pass this as SearchBase */ + +#define ACPI_NS_ALL ((ACPI_HANDLE)0) + +/* + * Elements of AcpiNsProperties are bit significant + * and should be one-to-one with values of ACPI_OBJECT_TYPE + */ +#define ACPI_NS_NORMAL 0 +#define ACPI_NS_NEWSCOPE 1 /* a definition of this type opens a name scope */ +#define ACPI_NS_LOCAL 2 /* suppress search of enclosing scopes */ + +/* Flags for AcpiNsLookup, AcpiNsSearchAndEnter */ + +#define ACPI_NS_NO_UPSEARCH 0 +#define ACPI_NS_SEARCH_PARENT 0x01 +#define ACPI_NS_DONT_OPEN_SCOPE 0x02 +#define ACPI_NS_NO_PEER_SEARCH 0x04 +#define ACPI_NS_ERROR_IF_FOUND 0x08 +#define ACPI_NS_PREFIX_IS_SCOPE 0x10 +#define ACPI_NS_EXTERNAL 0x20 +#define ACPI_NS_TEMPORARY 0x40 + +/* Flags for AcpiNsWalkNamespace */ + +#define ACPI_NS_WALK_NO_UNLOCK 0 +#define ACPI_NS_WALK_UNLOCK 0x01 +#define ACPI_NS_WALK_TEMP_NODES 0x02 + +/* Object is not a package element */ + +#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX + +/* Always emit warning message, not dependent on node flags */ + +#define ACPI_WARN_ALWAYS 0 + + +/* + * nsinit - Namespace initialization + */ +ACPI_STATUS +AcpiNsInitializeObjects ( + void); + +ACPI_STATUS +AcpiNsInitializeDevices ( + void); + + +/* + * nsload - Namespace loading + */ +ACPI_STATUS +AcpiNsLoadNamespace ( + void); + +ACPI_STATUS +AcpiNsLoadTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *Node); + + +/* + * nswalk - walk the namespace + */ +ACPI_STATUS +AcpiNsWalkNamespace ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE StartObject, + UINT32 MaxDepth, + UINT32 Flags, + ACPI_WALK_CALLBACK PreOrderVisit, + ACPI_WALK_CALLBACK PostOrderVisit, + void *Context, + void **ReturnValue); + +ACPI_NAMESPACE_NODE * +AcpiNsGetNextNode ( + ACPI_NAMESPACE_NODE *Parent, + ACPI_NAMESPACE_NODE *Child); + +ACPI_NAMESPACE_NODE * +AcpiNsGetNextNodeTyped ( + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE *Parent, + ACPI_NAMESPACE_NODE *Child); + +/* + * nsparse - table parsing + */ +ACPI_STATUS +AcpiNsParseTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode); + +ACPI_STATUS +AcpiNsOneCompleteParse ( + UINT32 PassNumber, + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode); + + +/* + * nsaccess - Top-level namespace access + */ +ACPI_STATUS +AcpiNsRootInitialize ( + void); + +ACPI_STATUS +AcpiNsLookup ( + ACPI_GENERIC_STATE *ScopeInfo, + char *Name, + ACPI_OBJECT_TYPE Type, + ACPI_INTERPRETER_MODE InterpreterMode, + UINT32 Flags, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **RetNode); + + +/* + * nsalloc - Named object allocation/deallocation + */ +ACPI_NAMESPACE_NODE * +AcpiNsCreateNode ( + UINT32 Name); + +void +AcpiNsDeleteNode ( + ACPI_NAMESPACE_NODE *Node); + +void +AcpiNsRemoveNode ( + ACPI_NAMESPACE_NODE *Node); + +void +AcpiNsDeleteNamespaceSubtree ( + ACPI_NAMESPACE_NODE *ParentHandle); + +void +AcpiNsDeleteNamespaceByOwner ( + ACPI_OWNER_ID OwnerId); + +void +AcpiNsDetachObject ( + ACPI_NAMESPACE_NODE *Node); + +void +AcpiNsDeleteChildren ( + ACPI_NAMESPACE_NODE *Parent); + +int +AcpiNsCompareNames ( + char *Name1, + char *Name2); + + +/* + * nsdump - Namespace dump/print utilities + */ +void +AcpiNsDumpTables ( + ACPI_HANDLE SearchBase, + UINT32 MaxDepth); + +void +AcpiNsDumpEntry ( + ACPI_HANDLE Handle, + UINT32 DebugLevel); + +void +AcpiNsDumpPathname ( + ACPI_HANDLE Handle, + char *Msg, + UINT32 Level, + UINT32 Component); + +void +AcpiNsPrintPathname ( + UINT32 NumSegments, + char *Pathname); + +ACPI_STATUS +AcpiNsDumpOneObject ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +void +AcpiNsDumpObjects ( + ACPI_OBJECT_TYPE Type, + UINT8 DisplayType, + UINT32 MaxDepth, + ACPI_OWNER_ID OwnerId, + ACPI_HANDLE StartHandle); + + +/* + * nseval - Namespace evaluation functions + */ +ACPI_STATUS +AcpiNsEvaluate ( + ACPI_EVALUATE_INFO *Info); + +void +AcpiNsExecModuleCodeList ( + void); + + +/* + * nspredef - Support for predefined/reserved names + */ +ACPI_STATUS +AcpiNsCheckPredefinedNames ( + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + ACPI_STATUS ReturnStatus, + ACPI_OPERAND_OBJECT **ReturnObject); + +const ACPI_PREDEFINED_INFO * +AcpiNsCheckForPredefinedName ( + ACPI_NAMESPACE_NODE *Node); + +void +AcpiNsCheckParameterCount ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + const ACPI_PREDEFINED_INFO *Info); + + +/* + * nsnames - Name and Scope manipulation + */ +UINT32 +AcpiNsOpensScope ( + ACPI_OBJECT_TYPE Type); + +ACPI_STATUS +AcpiNsBuildExternalPath ( + ACPI_NAMESPACE_NODE *Node, + ACPI_SIZE Size, + char *NameBuffer); + +char * +AcpiNsGetExternalPathname ( + ACPI_NAMESPACE_NODE *Node); + +char * +AcpiNsNameOfCurrentScope ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiNsHandleToPathname ( + ACPI_HANDLE TargetHandle, + ACPI_BUFFER *Buffer); + +BOOLEAN +AcpiNsPatternMatch ( + ACPI_NAMESPACE_NODE *ObjNode, + char *SearchFor); + +ACPI_STATUS +AcpiNsGetNode ( + ACPI_NAMESPACE_NODE *PrefixNode, + const char *ExternalPathname, + UINT32 Flags, + ACPI_NAMESPACE_NODE **OutNode); + +ACPI_SIZE +AcpiNsGetPathnameLength ( + ACPI_NAMESPACE_NODE *Node); + + +/* + * nsobject - Object management for namespace nodes + */ +ACPI_STATUS +AcpiNsAttachObject ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OPERAND_OBJECT *Object, + ACPI_OBJECT_TYPE Type); + +ACPI_OPERAND_OBJECT * +AcpiNsGetAttachedObject ( + ACPI_NAMESPACE_NODE *Node); + +ACPI_OPERAND_OBJECT * +AcpiNsGetSecondaryObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +ACPI_STATUS +AcpiNsAttachData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler, + void *Data); + +ACPI_STATUS +AcpiNsDetachData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler); + +ACPI_STATUS +AcpiNsGetAttachedData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_HANDLER Handler, + void **Data); + + +/* + * nsrepair - General return object repair for all + * predefined methods/objects + */ +ACPI_STATUS +AcpiNsRepairObject ( + ACPI_PREDEFINED_DATA *Data, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +ACPI_STATUS +AcpiNsRepairPackageList ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ObjDescPtr); + +ACPI_STATUS +AcpiNsRepairNullElement ( + ACPI_PREDEFINED_DATA *Data, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +void +AcpiNsRemoveNullElements ( + ACPI_PREDEFINED_DATA *Data, + UINT8 PackageType, + ACPI_OPERAND_OBJECT *ObjDesc); + + +/* + * nsrepair2 - Return object repair for specific + * predefined methods/objects + */ +ACPI_STATUS +AcpiNsComplexRepairs ( + ACPI_PREDEFINED_DATA *Data, + ACPI_NAMESPACE_NODE *Node, + ACPI_STATUS ValidateStatus, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + + +/* + * nssearch - Namespace searching and entry + */ +ACPI_STATUS +AcpiNsSearchAndEnter ( + UINT32 EntryName, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *Node, + ACPI_INTERPRETER_MODE InterpreterMode, + ACPI_OBJECT_TYPE Type, + UINT32 Flags, + ACPI_NAMESPACE_NODE **RetNode); + +ACPI_STATUS +AcpiNsSearchOneScope ( + UINT32 EntryName, + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type, + ACPI_NAMESPACE_NODE **RetNode); + +void +AcpiNsInstallNode ( + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE *ParentNode, + ACPI_NAMESPACE_NODE *Node, + ACPI_OBJECT_TYPE Type); + + +/* + * nsutils - Utility functions + */ +BOOLEAN +AcpiNsValidRootPrefix ( + char Prefix); + +ACPI_OBJECT_TYPE +AcpiNsGetType ( + ACPI_NAMESPACE_NODE *Node); + +UINT32 +AcpiNsLocal ( + ACPI_OBJECT_TYPE Type); + +void +AcpiNsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Msg); + +ACPI_STATUS +AcpiNsBuildInternalName ( + ACPI_NAMESTRING_INFO *Info); + +void +AcpiNsGetInternalNameLength ( + ACPI_NAMESTRING_INFO *Info); + +ACPI_STATUS +AcpiNsInternalizeName ( + const char *DottedName, + char **ConvertedName); + +ACPI_STATUS +AcpiNsExternalizeName ( + UINT32 InternalNameLength, + const char *InternalName, + UINT32 *ConvertedNameLength, + char **ConvertedName); + +ACPI_NAMESPACE_NODE * +AcpiNsValidateHandle ( + ACPI_HANDLE Handle); + +void +AcpiNsTerminate ( + void); + +#endif /* __ACNAMESP_H__ */ diff --git a/source/include/acobject.h b/source/include/acobject.h new file mode 100644 index 000000000000..41a8e086491f --- /dev/null +++ b/source/include/acobject.h @@ -0,0 +1,586 @@ + +/****************************************************************************** + * + * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACOBJECT_H +#define _ACOBJECT_H + +/* acpisrc:StructDefs -- for acpisrc conversion */ + + +/* + * The ACPI_OPERAND_OBJECT is used to pass AML operands from the dispatcher + * to the interpreter, and to keep track of the various handlers such as + * address space handlers and notify handlers. The object is a constant + * size in order to allow it to be cached and reused. + * + * Note: The object is optimized to be aligned and will not work if it is + * byte-packed. + */ +#if ACPI_MACHINE_WIDTH == 64 +#pragma pack(8) +#else +#pragma pack(4) +#endif + +/******************************************************************************* + * + * Common Descriptors + * + ******************************************************************************/ + +/* + * Common area for all objects. + * + * DescriptorType is used to differentiate between internal descriptors, and + * must be in the same place across all descriptors + * + * Note: The DescriptorType and Type fields must appear in the identical + * position in both the ACPI_NAMESPACE_NODE and ACPI_OPERAND_OBJECT + * structures. + */ +#define ACPI_OBJECT_COMMON_HEADER \ + union acpi_operand_object *NextObject; /* Objects linked to parent NS node */\ + UINT8 DescriptorType; /* To differentiate various internal objs */\ + UINT8 Type; /* ACPI_OBJECT_TYPE */\ + UINT16 ReferenceCount; /* For object deletion management */\ + UINT8 Flags; + /* + * Note: There are 3 bytes available here before the + * next natural alignment boundary (for both 32/64 cases) + */ + +/* Values for Flag byte above */ + +#define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ +#define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ +#define AOPOBJ_DATA_VALID 0x04 /* Object is intialized and data is valid */ +#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ +#define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ +#define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ + + +/****************************************************************************** + * + * Basic data types + * + *****************************************************************************/ + +typedef struct acpi_object_common +{ + ACPI_OBJECT_COMMON_HEADER + +} ACPI_OBJECT_COMMON; + + +typedef struct acpi_object_integer +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 Fill[3]; /* Prevent warning on some compilers */ + UINT64 Value; + +} ACPI_OBJECT_INTEGER; + + +/* + * Note: The String and Buffer object must be identical through the Pointer + * and length elements. There is code that depends on this. + * + * Fields common to both Strings and Buffers + */ +#define ACPI_COMMON_BUFFER_INFO(_Type) \ + _Type *Pointer; \ + UINT32 Length; + + +typedef struct acpi_object_string /* Null terminated, ASCII characters only */ +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_BUFFER_INFO (char) /* String in AML stream or allocated string */ + +} ACPI_OBJECT_STRING; + + +typedef struct acpi_object_buffer +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_BUFFER_INFO (UINT8) /* Buffer in AML stream or allocated buffer */ + UINT32 AmlLength; + UINT8 *AmlStart; + ACPI_NAMESPACE_NODE *Node; /* Link back to parent node */ + +} ACPI_OBJECT_BUFFER; + + +typedef struct acpi_object_package +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_NAMESPACE_NODE *Node; /* Link back to parent node */ + union acpi_operand_object **Elements; /* Array of pointers to AcpiObjects */ + UINT8 *AmlStart; + UINT32 AmlLength; + UINT32 Count; /* # of elements in package */ + +} ACPI_OBJECT_PACKAGE; + + +/****************************************************************************** + * + * Complex data types + * + *****************************************************************************/ + +typedef struct acpi_object_event +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_SEMAPHORE OsSemaphore; /* Actual OS synchronization object */ + +} ACPI_OBJECT_EVENT; + + +typedef struct acpi_object_mutex +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 SyncLevel; /* 0-15, specified in Mutex() call */ + UINT16 AcquisitionDepth; /* Allow multiple Acquires, same thread */ + ACPI_MUTEX OsMutex; /* Actual OS synchronization object */ + ACPI_THREAD_ID ThreadId; /* Current owner of the mutex */ + struct acpi_thread_state *OwnerThread; /* Current owner of the mutex */ + union acpi_operand_object *Prev; /* Link for list of acquired mutexes */ + union acpi_operand_object *Next; /* Link for list of acquired mutexes */ + ACPI_NAMESPACE_NODE *Node; /* Containing namespace node */ + UINT8 OriginalSyncLevel; /* Owner's original sync level (0-15) */ + +} ACPI_OBJECT_MUTEX; + + +typedef struct acpi_object_region +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 SpaceId; + ACPI_NAMESPACE_NODE *Node; /* Containing namespace node */ + union acpi_operand_object *Handler; /* Handler for region access */ + union acpi_operand_object *Next; + ACPI_PHYSICAL_ADDRESS Address; + UINT32 Length; + +} ACPI_OBJECT_REGION; + + +typedef struct acpi_object_method +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 InfoFlags; + UINT8 ParamCount; + UINT8 SyncLevel; + union acpi_operand_object *Mutex; + UINT8 *AmlStart; + union + { + ACPI_INTERNAL_METHOD Implementation; + union acpi_operand_object *Handler; + } Dispatch; + + UINT32 AmlLength; + UINT8 ThreadCount; + ACPI_OWNER_ID OwnerId; + +} ACPI_OBJECT_METHOD; + +/* Flags for InfoFlags field above */ + +#define ACPI_METHOD_MODULE_LEVEL 0x01 /* Method is actually module-level code */ +#define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */ +#define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */ +#define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */ +#define ACPI_METHOD_MODIFIED_NAMESPACE 0x10 /* Method modified the namespace */ + + +/****************************************************************************** + * + * Objects that can be notified. All share a common NotifyInfo area. + * + *****************************************************************************/ + +/* + * Common fields for objects that support ASL notifications + */ +#define ACPI_COMMON_NOTIFY_INFO \ + union acpi_operand_object *SystemNotify; /* Handler for system notifies */\ + union acpi_operand_object *DeviceNotify; /* Handler for driver notifies */\ + union acpi_operand_object *Handler; /* Handler for Address space */ + + +typedef struct acpi_object_notify_common /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_NOTIFY_INFO + +} ACPI_OBJECT_NOTIFY_COMMON; + + +typedef struct acpi_object_device +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_NOTIFY_INFO + ACPI_GPE_BLOCK_INFO *GpeBlock; + +} ACPI_OBJECT_DEVICE; + + +typedef struct acpi_object_power_resource +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_NOTIFY_INFO + UINT32 SystemLevel; + UINT32 ResourceOrder; + +} ACPI_OBJECT_POWER_RESOURCE; + + +typedef struct acpi_object_processor +{ + ACPI_OBJECT_COMMON_HEADER + + /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ + + UINT8 ProcId; + UINT8 Length; + ACPI_COMMON_NOTIFY_INFO + ACPI_IO_ADDRESS Address; + +} ACPI_OBJECT_PROCESSOR; + + +typedef struct acpi_object_thermal_zone +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_NOTIFY_INFO + +} ACPI_OBJECT_THERMAL_ZONE; + + +/****************************************************************************** + * + * Fields. All share a common header/info field. + * + *****************************************************************************/ + +/* + * Common bitfield for the field objects + * "Field Datum" -- a datum from the actual field object + * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field + */ +#define ACPI_COMMON_FIELD_INFO \ + UINT8 FieldFlags; /* Access, update, and lock bits */\ + UINT8 Attribute; /* From AccessAs keyword */\ + UINT8 AccessByteWidth; /* Read/Write size in bytes */\ + ACPI_NAMESPACE_NODE *Node; /* Link back to parent node */\ + UINT32 BitLength; /* Length of field in bits */\ + UINT32 BaseByteOffset; /* Byte offset within containing object */\ + UINT32 Value; /* Value to store into the Bank or Index register */\ + UINT8 StartFieldBitOffset;/* Bit offset within first field datum (0-63) */\ + UINT8 AccessLength; /* For serial regions/fields */ + + +typedef struct acpi_object_field_common /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + union acpi_operand_object *RegionObj; /* Parent Operation Region object (REGION/BANK fields only) */ + +} ACPI_OBJECT_FIELD_COMMON; + + +typedef struct acpi_object_region_field +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + UINT16 ResourceLength; + union acpi_operand_object *RegionObj; /* Containing OpRegion object */ + UINT8 *ResourceBuffer; /* ResourceTemplate for serial regions/fields */ + +} ACPI_OBJECT_REGION_FIELD; + + +typedef struct acpi_object_bank_field +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + union acpi_operand_object *RegionObj; /* Containing OpRegion object */ + union acpi_operand_object *BankObj; /* BankSelect Register object */ + +} ACPI_OBJECT_BANK_FIELD; + + +typedef struct acpi_object_index_field +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + + /* + * No "RegionObj" pointer needed since the Index and Data registers + * are each field definitions unto themselves. + */ + union acpi_operand_object *IndexObj; /* Index register */ + union acpi_operand_object *DataObj; /* Data register */ + +} ACPI_OBJECT_INDEX_FIELD; + + +/* The BufferField is different in that it is part of a Buffer, not an OpRegion */ + +typedef struct acpi_object_buffer_field +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + union acpi_operand_object *BufferObj; /* Containing Buffer object */ + +} ACPI_OBJECT_BUFFER_FIELD; + + +/****************************************************************************** + * + * Objects for handlers + * + *****************************************************************************/ + +typedef struct acpi_object_notify_handler +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_NAMESPACE_NODE *Node; /* Parent device */ + ACPI_NOTIFY_HANDLER Handler; + void *Context; + +} ACPI_OBJECT_NOTIFY_HANDLER; + + +typedef struct acpi_object_addr_handler +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 SpaceId; + UINT8 HandlerFlags; + ACPI_ADR_SPACE_HANDLER Handler; + ACPI_NAMESPACE_NODE *Node; /* Parent device */ + void *Context; + ACPI_ADR_SPACE_SETUP Setup; + union acpi_operand_object *RegionList; /* regions using this handler */ + union acpi_operand_object *Next; + +} ACPI_OBJECT_ADDR_HANDLER; + +/* Flags for address handler (HandlerFlags) */ + +#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x01 + + +/****************************************************************************** + * + * Special internal objects + * + *****************************************************************************/ + +/* + * The Reference object is used for these opcodes: + * Arg[0-6], Local[0-7], IndexOp, NameOp, RefOfOp, LoadOp, LoadTableOp, DebugOp + * The Reference.Class differentiates these types. + */ +typedef struct acpi_object_reference +{ + ACPI_OBJECT_COMMON_HEADER + UINT8 Class; /* Reference Class */ + UINT8 TargetType; /* Used for Index Op */ + UINT8 Reserved; + void *Object; /* NameOp=>HANDLE to obj, IndexOp=>ACPI_OPERAND_OBJECT */ + ACPI_NAMESPACE_NODE *Node; /* RefOf or Namepath */ + union acpi_operand_object **Where; /* Target of Index */ + UINT32 Value; /* Used for Local/Arg/Index/DdbHandle */ + +} ACPI_OBJECT_REFERENCE; + +/* Values for Reference.Class above */ + +typedef enum +{ + ACPI_REFCLASS_LOCAL = 0, /* Method local */ + ACPI_REFCLASS_ARG = 1, /* Method argument */ + ACPI_REFCLASS_REFOF = 2, /* Result of RefOf() TBD: Split to Ref/Node and Ref/OperandObj? */ + ACPI_REFCLASS_INDEX = 3, /* Result of Index() */ + ACPI_REFCLASS_TABLE = 4, /* DdbHandle - Load(), LoadTable() */ + ACPI_REFCLASS_NAME = 5, /* Reference to a named object */ + ACPI_REFCLASS_DEBUG = 6, /* Debug object */ + + ACPI_REFCLASS_MAX = 6 + +} ACPI_REFERENCE_CLASSES; + + +/* + * Extra object is used as additional storage for types that + * have AML code in their declarations (TermArgs) that must be + * evaluated at run time. + * + * Currently: Region and FieldUnit types + */ +typedef struct acpi_object_extra +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_NAMESPACE_NODE *Method_REG; /* _REG method for this region (if any) */ + ACPI_NAMESPACE_NODE *ScopeNode; + void *RegionContext; /* Region-specific data */ + UINT8 *AmlStart; + UINT32 AmlLength; + +} ACPI_OBJECT_EXTRA; + + +/* Additional data that can be attached to namespace nodes */ + +typedef struct acpi_object_data +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_OBJECT_HANDLER Handler; + void *Pointer; + +} ACPI_OBJECT_DATA; + + +/* Structure used when objects are cached for reuse */ + +typedef struct acpi_object_cache_list +{ + ACPI_OBJECT_COMMON_HEADER + union acpi_operand_object *Next; /* Link for object cache and internal lists*/ + +} ACPI_OBJECT_CACHE_LIST; + + +/****************************************************************************** + * + * ACPI_OPERAND_OBJECT Descriptor - a giant union of all of the above + * + *****************************************************************************/ + +typedef union acpi_operand_object +{ + ACPI_OBJECT_COMMON Common; + ACPI_OBJECT_INTEGER Integer; + ACPI_OBJECT_STRING String; + ACPI_OBJECT_BUFFER Buffer; + ACPI_OBJECT_PACKAGE Package; + ACPI_OBJECT_EVENT Event; + ACPI_OBJECT_METHOD Method; + ACPI_OBJECT_MUTEX Mutex; + ACPI_OBJECT_REGION Region; + ACPI_OBJECT_NOTIFY_COMMON CommonNotify; + ACPI_OBJECT_DEVICE Device; + ACPI_OBJECT_POWER_RESOURCE PowerResource; + ACPI_OBJECT_PROCESSOR Processor; + ACPI_OBJECT_THERMAL_ZONE ThermalZone; + ACPI_OBJECT_FIELD_COMMON CommonField; + ACPI_OBJECT_REGION_FIELD Field; + ACPI_OBJECT_BUFFER_FIELD BufferField; + ACPI_OBJECT_BANK_FIELD BankField; + ACPI_OBJECT_INDEX_FIELD IndexField; + ACPI_OBJECT_NOTIFY_HANDLER Notify; + ACPI_OBJECT_ADDR_HANDLER AddressSpace; + ACPI_OBJECT_REFERENCE Reference; + ACPI_OBJECT_EXTRA Extra; + ACPI_OBJECT_DATA Data; + ACPI_OBJECT_CACHE_LIST Cache; + + /* + * Add namespace node to union in order to simplify code that accepts both + * ACPI_OPERAND_OBJECTs and ACPI_NAMESPACE_NODEs. The structures share + * a common DescriptorType field in order to differentiate them. + */ + ACPI_NAMESPACE_NODE Node; + +} ACPI_OPERAND_OBJECT; + + +/****************************************************************************** + * + * ACPI_DESCRIPTOR - objects that share a common descriptor identifier + * + *****************************************************************************/ + +/* Object descriptor types */ + +#define ACPI_DESC_TYPE_CACHED 0x01 /* Used only when object is cached */ +#define ACPI_DESC_TYPE_STATE 0x02 +#define ACPI_DESC_TYPE_STATE_UPDATE 0x03 +#define ACPI_DESC_TYPE_STATE_PACKAGE 0x04 +#define ACPI_DESC_TYPE_STATE_CONTROL 0x05 +#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x06 +#define ACPI_DESC_TYPE_STATE_PSCOPE 0x07 +#define ACPI_DESC_TYPE_STATE_WSCOPE 0x08 +#define ACPI_DESC_TYPE_STATE_RESULT 0x09 +#define ACPI_DESC_TYPE_STATE_NOTIFY 0x0A +#define ACPI_DESC_TYPE_STATE_THREAD 0x0B +#define ACPI_DESC_TYPE_WALK 0x0C +#define ACPI_DESC_TYPE_PARSER 0x0D +#define ACPI_DESC_TYPE_OPERAND 0x0E +#define ACPI_DESC_TYPE_NAMED 0x0F +#define ACPI_DESC_TYPE_MAX 0x0F + + +typedef struct acpi_common_descriptor +{ + void *CommonPointer; + UINT8 DescriptorType; /* To differentiate various internal objs */ + +} ACPI_COMMON_DESCRIPTOR; + +typedef union acpi_descriptor +{ + ACPI_COMMON_DESCRIPTOR Common; + ACPI_OPERAND_OBJECT Object; + ACPI_NAMESPACE_NODE Node; + ACPI_PARSE_OBJECT Op; + +} ACPI_DESCRIPTOR; + +#pragma pack() + +#endif /* _ACOBJECT_H */ diff --git a/source/include/acopcode.h b/source/include/acopcode.h new file mode 100644 index 000000000000..e182a07e6197 --- /dev/null +++ b/source/include/acopcode.h @@ -0,0 +1,329 @@ +/****************************************************************************** + * + * Name: acopcode.h - AML opcode information for the AML parser and interpreter + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACOPCODE_H__ +#define __ACOPCODE_H__ + +#define MAX_EXTENDED_OPCODE 0x88 +#define NUM_EXTENDED_OPCODE (MAX_EXTENDED_OPCODE + 1) +#define MAX_INTERNAL_OPCODE +#define NUM_INTERNAL_OPCODE (MAX_INTERNAL_OPCODE + 1) + +/* Used for non-assigned opcodes */ + +#define _UNK 0x6B + +/* + * Reserved ASCII characters. Do not use any of these for + * internal opcodes, since they are used to differentiate + * name strings from AML opcodes + */ +#define _ASC 0x6C +#define _NAM 0x6C +#define _PFX 0x6D + + +/* + * All AML opcodes and the parse-time arguments for each. Used by the AML + * parser Each list is compressed into a 32-bit number and stored in the + * master opcode table (in psopcode.c). + */ +#define ARGP_ACCESSFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_ACQUIRE_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_WORDDATA) +#define ARGP_ADD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_ALIAS_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_NAME) +#define ARGP_ARG0 ARG_NONE +#define ARGP_ARG1 ARG_NONE +#define ARGP_ARG2 ARG_NONE +#define ARGP_ARG3 ARG_NONE +#define ARGP_ARG4 ARG_NONE +#define ARGP_ARG5 ARG_NONE +#define ARGP_ARG6 ARG_NONE +#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_BIT_AND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NAND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_OR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_XOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BREAK_OP ARG_NONE +#define ARGP_BREAK_POINT_OP ARG_NONE +#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST) +#define ARGP_BYTE_OP ARGP_LIST1 (ARGP_BYTEDATA) +#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME) +#define ARGP_CONNECTFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_CONTINUE_OP ARG_NONE +#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME) +#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_DATA_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_DEBUG_OP ARG_NONE +#define ARGP_DECREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_DIVIDE_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET, ARGP_TARGET) +#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA) +#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST) +#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME) +#define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG) +#define ARGP_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FROM_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_INCREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME) +#define ARGP_LOAD_TABLE_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LOCAL0 ARG_NONE +#define ARGP_LOCAL1 ARG_NONE +#define ARGP_LOCAL2 ARG_NONE +#define ARGP_LOCAL3 ARG_NONE +#define ARGP_LOCAL4 ARG_NONE +#define ARGP_LOCAL5 ARG_NONE +#define ARGP_LOCAL6 ARG_NONE +#define ARGP_LOCAL7 ARG_NONE +#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST) +#define ARGP_METHODCALL_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_MID_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MOD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MULTIPLY_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MUTEX_OP ARGP_LIST2 (ARGP_NAME, ARGP_BYTEDATA) +#define ARGP_NAME_OP ARGP_LIST2 (ARGP_NAME, ARGP_DATAOBJ) +#define ARGP_NAMEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_NOOP_OP ARG_NONE +#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_ONE_OP ARG_NONE +#define ARGP_ONES_OP ARG_NONE +#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST) +#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST) +#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST) +#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA) +#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_RESET_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_REVISION_OP ARG_NONE +#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST) +#define ARGP_SERIALFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_STATICSTRING_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_STORE_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SUPERNAME) +#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST) +#define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_TIMER_OP ARG_NONE +#define ARGP_TO_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_UNLOAD_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_DATAOBJLIST) +#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA) +#define ARGP_ZERO_OP ARG_NONE + + +/* + * All AML opcodes and the runtime arguments for each. Used by the AML + * interpreter Each list is compressed into a 32-bit number and stored + * in the master opcode table (in psopcode.c). + * + * (Used by PrepOperands procedure and the ASL Compiler) + */ +#define ARGI_ACCESSFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_INTEGER) +#define ARGI_ADD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_ALIAS_OP ARGI_INVALID_OPCODE +#define ARGI_ARG0 ARG_NONE +#define ARGI_ARG1 ARG_NONE +#define ARGI_ARG2 ARG_NONE +#define ARGI_ARG3 ARG_NONE +#define ARGI_ARG4 ARG_NONE +#define ARGI_ARG5 ARG_NONE +#define ARGI_ARG6 ARG_NONE +#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BREAK_OP ARG_NONE +#define ARGI_BREAK_POINT_OP ARG_NONE +#define ARGI_BUFFER_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_BYTE_OP ARGI_INVALID_OPCODE +#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE +#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF) +#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF) +#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF) +#define ARGI_CONNECTFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE +#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET) +#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) +#define ARGI_DEBUG_OP ARG_NONE +#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) +#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING) +#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE +#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF) +#define ARGI_DWORD_OP ARGI_INVALID_OPCODE +#define ARGI_ELSE_OP ARGI_INVALID_OPCODE +#define ARGI_EVENT_OP ARGI_INVALID_OPCODE +#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) +#define ARGI_IF_OP ARGI_INVALID_OPCODE +#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) +#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) +#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) +#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) +#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION_OR_BUFFER,ARGI_TARGETREF) +#define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_ANYTYPE) +#define ARGI_LOCAL0 ARG_NONE +#define ARGI_LOCAL1 ARG_NONE +#define ARGI_LOCAL2 ARG_NONE +#define ARGI_LOCAL3 ARG_NONE +#define ARGI_LOCAL4 ARG_NONE +#define ARGI_LOCAL5 ARG_NONE +#define ARGI_LOCAL6 ARG_NONE +#define ARGI_LOCAL7 ARG_NONE +#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_COMPUTEDATA, ARGI_INTEGER,ARGI_COMPUTEDATA,ARGI_INTEGER) +#define ARGI_METHOD_OP ARGI_INVALID_OPCODE +#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE +#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFER_OR_STRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_MOD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE +#define ARGI_NAME_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE +#define ARGI_NOOP_OP ARG_NONE +#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER) +#define ARGI_ONE_OP ARG_NONE +#define ARGI_ONES_OP ARG_NONE +#define ARGI_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE +#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE +#define ARGI_QWORD_OP ARGI_INVALID_OPCODE +#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_OBJECT_REF) +#define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX) +#define ARGI_RESERVEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_RETURN_OP ARGI_INVALID_OPCODE +#define ARGI_REVISION_OP ARG_NONE +#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE +#define ARGI_SERIALFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT) +#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE +#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_TARGETREF) +#define ARGI_STRING_OP ARGI_INVALID_OPCODE +#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE +#define ARGI_TIMER_OP ARG_NONE +#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) +#define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET) +#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) +#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE) +#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER) +#define ARGI_WHILE_OP ARGI_INVALID_OPCODE +#define ARGI_WORD_OP ARGI_INVALID_OPCODE +#define ARGI_ZERO_OP ARG_NONE + +#endif /* __ACOPCODE_H__ */ diff --git a/source/include/acoutput.h b/source/include/acoutput.h new file mode 100644 index 000000000000..88c1cab71221 --- /dev/null +++ b/source/include/acoutput.h @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * Name: acoutput.h -- debug output + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACOUTPUT_H__ +#define __ACOUTPUT_H__ + +/* + * Debug levels and component IDs. These are used to control the + * granularity of the output of the ACPI_DEBUG_PRINT macro -- on a + * per-component basis and a per-exception-type basis. + */ + +/* Component IDs are used in the global "DebugLayer" */ + +#define ACPI_UTILITIES 0x00000001 +#define ACPI_HARDWARE 0x00000002 +#define ACPI_EVENTS 0x00000004 +#define ACPI_TABLES 0x00000008 +#define ACPI_NAMESPACE 0x00000010 +#define ACPI_PARSER 0x00000020 +#define ACPI_DISPATCHER 0x00000040 +#define ACPI_EXECUTER 0x00000080 +#define ACPI_RESOURCES 0x00000100 +#define ACPI_CA_DEBUGGER 0x00000200 +#define ACPI_OS_SERVICES 0x00000400 +#define ACPI_CA_DISASSEMBLER 0x00000800 + +/* Component IDs for ACPI tools and utilities */ + +#define ACPI_COMPILER 0x00001000 +#define ACPI_TOOLS 0x00002000 +#define ACPI_EXAMPLE 0x00004000 +#define ACPI_DRIVER 0x00008000 +#define DT_COMPILER 0x00010000 + +#define ACPI_ALL_COMPONENTS 0x0001FFFF +#define ACPI_COMPONENT_DEFAULT (ACPI_ALL_COMPONENTS) + +/* Component IDs reserved for ACPI drivers */ + +#define ACPI_ALL_DRIVERS 0xFFFF0000 + + +/* + * Raw debug output levels, do not use these in the ACPI_DEBUG_PRINT macros + */ +#define ACPI_LV_INIT 0x00000001 +#define ACPI_LV_DEBUG_OBJECT 0x00000002 +#define ACPI_LV_INFO 0x00000004 +#define ACPI_LV_REPAIR 0x00000008 +#define ACPI_LV_ALL_EXCEPTIONS 0x0000000F + +/* Trace verbosity level 1 [Standard Trace Level] */ + +#define ACPI_LV_INIT_NAMES 0x00000020 +#define ACPI_LV_PARSE 0x00000040 +#define ACPI_LV_LOAD 0x00000080 +#define ACPI_LV_DISPATCH 0x00000100 +#define ACPI_LV_EXEC 0x00000200 +#define ACPI_LV_NAMES 0x00000400 +#define ACPI_LV_OPREGION 0x00000800 +#define ACPI_LV_BFIELD 0x00001000 +#define ACPI_LV_TABLES 0x00002000 +#define ACPI_LV_VALUES 0x00004000 +#define ACPI_LV_OBJECTS 0x00008000 +#define ACPI_LV_RESOURCES 0x00010000 +#define ACPI_LV_USER_REQUESTS 0x00020000 +#define ACPI_LV_PACKAGE 0x00040000 +#define ACPI_LV_VERBOSITY1 0x0007FF40 | ACPI_LV_ALL_EXCEPTIONS + +/* Trace verbosity level 2 [Function tracing and memory allocation] */ + +#define ACPI_LV_ALLOCATIONS 0x00100000 +#define ACPI_LV_FUNCTIONS 0x00200000 +#define ACPI_LV_OPTIMIZATIONS 0x00400000 +#define ACPI_LV_VERBOSITY2 0x00700000 | ACPI_LV_VERBOSITY1 +#define ACPI_LV_ALL ACPI_LV_VERBOSITY2 + +/* Trace verbosity level 3 [Threading, I/O, and Interrupts] */ + +#define ACPI_LV_MUTEX 0x01000000 +#define ACPI_LV_THREADS 0x02000000 +#define ACPI_LV_IO 0x04000000 +#define ACPI_LV_INTERRUPTS 0x08000000 +#define ACPI_LV_VERBOSITY3 0x0F000000 | ACPI_LV_VERBOSITY2 + +/* Exceptionally verbose output -- also used in the global "DebugLevel" */ + +#define ACPI_LV_AML_DISASSEMBLE 0x10000000 +#define ACPI_LV_VERBOSE_INFO 0x20000000 +#define ACPI_LV_FULL_TABLES 0x40000000 +#define ACPI_LV_EVENTS 0x80000000 +#define ACPI_LV_VERBOSE 0xF0000000 + + +/* + * Debug level macros that are used in the DEBUG_PRINT macros + */ +#define ACPI_DEBUG_LEVEL(dl) (UINT32) dl,ACPI_DEBUG_PARAMETERS + +/* + * Exception level -- used in the global "DebugLevel" + * + * Note: For errors, use the ACPI_ERROR or ACPI_EXCEPTION interfaces. + * For warnings, use ACPI_WARNING. + */ +#define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) +#define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) +#define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) +#define ACPI_DB_REPAIR ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR) +#define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) + +/* Trace level -- also used in the global "DebugLevel" */ + +#define ACPI_DB_INIT_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES) +#define ACPI_DB_THREADS ACPI_DEBUG_LEVEL (ACPI_LV_THREADS) +#define ACPI_DB_PARSE ACPI_DEBUG_LEVEL (ACPI_LV_PARSE) +#define ACPI_DB_DISPATCH ACPI_DEBUG_LEVEL (ACPI_LV_DISPATCH) +#define ACPI_DB_LOAD ACPI_DEBUG_LEVEL (ACPI_LV_LOAD) +#define ACPI_DB_EXEC ACPI_DEBUG_LEVEL (ACPI_LV_EXEC) +#define ACPI_DB_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_NAMES) +#define ACPI_DB_OPREGION ACPI_DEBUG_LEVEL (ACPI_LV_OPREGION) +#define ACPI_DB_BFIELD ACPI_DEBUG_LEVEL (ACPI_LV_BFIELD) +#define ACPI_DB_TABLES ACPI_DEBUG_LEVEL (ACPI_LV_TABLES) +#define ACPI_DB_FUNCTIONS ACPI_DEBUG_LEVEL (ACPI_LV_FUNCTIONS) +#define ACPI_DB_OPTIMIZATIONS ACPI_DEBUG_LEVEL (ACPI_LV_OPTIMIZATIONS) +#define ACPI_DB_VALUES ACPI_DEBUG_LEVEL (ACPI_LV_VALUES) +#define ACPI_DB_OBJECTS ACPI_DEBUG_LEVEL (ACPI_LV_OBJECTS) +#define ACPI_DB_ALLOCATIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALLOCATIONS) +#define ACPI_DB_RESOURCES ACPI_DEBUG_LEVEL (ACPI_LV_RESOURCES) +#define ACPI_DB_IO ACPI_DEBUG_LEVEL (ACPI_LV_IO) +#define ACPI_DB_INTERRUPTS ACPI_DEBUG_LEVEL (ACPI_LV_INTERRUPTS) +#define ACPI_DB_USER_REQUESTS ACPI_DEBUG_LEVEL (ACPI_LV_USER_REQUESTS) +#define ACPI_DB_PACKAGE ACPI_DEBUG_LEVEL (ACPI_LV_PACKAGE) +#define ACPI_DB_MUTEX ACPI_DEBUG_LEVEL (ACPI_LV_MUTEX) +#define ACPI_DB_EVENTS ACPI_DEBUG_LEVEL (ACPI_LV_EVENTS) + +#define ACPI_DB_ALL ACPI_DEBUG_LEVEL (ACPI_LV_ALL) + +/* Defaults for DebugLevel, debug and normal */ + +#define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT | ACPI_LV_REPAIR) +#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT | ACPI_LV_REPAIR) +#define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) + + +#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) +/* + * The module name is used primarily for error and debug messages. + * The __FILE__ macro is not very useful for this, because it + * usually includes the entire pathname to the module making the + * debug output difficult to read. + */ +#define ACPI_MODULE_NAME(Name) static const char ACPI_UNUSED_VAR _AcpiModuleName[] = Name; +#else +/* + * For the no-debug and no-error-msg cases, we must at least define + * a null module name. + */ +#define ACPI_MODULE_NAME(Name) +#define _AcpiModuleName "" +#endif + +/* + * Ascii error messages can be configured out + */ +#ifndef ACPI_NO_ERROR_MESSAGES +#define AE_INFO _AcpiModuleName, __LINE__ + +/* + * Error reporting. Callers module and line number are inserted by AE_INFO, + * the plist contains a set of parens to allow variable-length lists. + * These macros are used for both the debug and non-debug versions of the code. + */ +#define ACPI_INFO(plist) AcpiInfo plist +#define ACPI_WARNING(plist) AcpiWarning plist +#define ACPI_EXCEPTION(plist) AcpiException plist +#define ACPI_ERROR(plist) AcpiError plist +#define ACPI_DEBUG_OBJECT(obj,l,i) AcpiExDoDebugObject(obj,l,i) + +#else + +/* No error messages */ + +#define ACPI_INFO(plist) +#define ACPI_WARNING(plist) +#define ACPI_EXCEPTION(plist) +#define ACPI_ERROR(plist) +#define ACPI_DEBUG_OBJECT(obj,l,i) + +#endif /* ACPI_NO_ERROR_MESSAGES */ + + +/* + * Debug macros that are conditionally compiled + */ +#ifdef ACPI_DEBUG_OUTPUT + +/* + * If ACPI_GET_FUNCTION_NAME was not defined in the compiler-dependent header, + * define it now. This is the case where there the compiler does not support + * a __FUNCTION__ macro or equivalent. + */ +#ifndef ACPI_GET_FUNCTION_NAME +#define ACPI_GET_FUNCTION_NAME _AcpiFunctionName + +/* + * The Name parameter should be the procedure name as a quoted string. + * The function name is also used by the function exit macros below. + * Note: (const char) is used to be compatible with the debug interfaces + * and macros such as __FUNCTION__. + */ +#define ACPI_FUNCTION_NAME(Name) static const char _AcpiFunctionName[] = #Name; + +#else +/* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */ + +#define ACPI_FUNCTION_NAME(Name) +#endif /* ACPI_GET_FUNCTION_NAME */ + +/* + * Common parameters used for debug output functions: + * line number, function name, module(file) name, component ID + */ +#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _AcpiModuleName, _COMPONENT + +/* + * Master debug print macros + * Print message if and only if: + * 1) Debug print for the current component is enabled + * 2) Debug error level or trace level for the print statement is enabled + */ +#define ACPI_DEBUG_PRINT(plist) AcpiDebugPrint plist +#define ACPI_DEBUG_PRINT_RAW(plist) AcpiDebugPrintRaw plist + +#else +/* + * This is the non-debug case -- make everything go away, + * leaving no executable debug code! + */ +#define ACPI_FUNCTION_NAME(a) +#define ACPI_DEBUG_PRINT(pl) +#define ACPI_DEBUG_PRINT_RAW(pl) + +#endif /* ACPI_DEBUG_OUTPUT */ + + +#endif /* __ACOUTPUT_H__ */ diff --git a/source/include/acparser.h b/source/include/acparser.h new file mode 100644 index 000000000000..f46d3cbc2ca9 --- /dev/null +++ b/source/include/acparser.h @@ -0,0 +1,331 @@ +/****************************************************************************** + * + * Module Name: acparser.h - AML Parser subcomponent prototypes and defines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ACPARSER_H__ +#define __ACPARSER_H__ + + +#define OP_HAS_RETURN_VALUE 1 + +/* Variable number of arguments. This field must be 32 bits */ + +#define ACPI_VAR_ARGS ACPI_UINT32_MAX + + +#define ACPI_PARSE_DELETE_TREE 0x0001 +#define ACPI_PARSE_NO_TREE_DELETE 0x0000 +#define ACPI_PARSE_TREE_MASK 0x0001 + +#define ACPI_PARSE_LOAD_PASS1 0x0010 +#define ACPI_PARSE_LOAD_PASS2 0x0020 +#define ACPI_PARSE_EXECUTE 0x0030 +#define ACPI_PARSE_MODE_MASK 0x0030 + +#define ACPI_PARSE_DEFERRED_OP 0x0100 +#define ACPI_PARSE_DISASSEMBLE 0x0200 + +#define ACPI_PARSE_MODULE_LEVEL 0x0400 + +/****************************************************************************** + * + * Parser interfaces + * + *****************************************************************************/ + + +/* + * psxface - Parser external interfaces + */ +ACPI_STATUS +AcpiPsExecuteMethod ( + ACPI_EVALUATE_INFO *Info); + + +/* + * psargs - Parse AML opcode arguments + */ +UINT8 * +AcpiPsGetNextPackageEnd ( + ACPI_PARSE_STATE *ParserState); + +char * +AcpiPsGetNextNamestring ( + ACPI_PARSE_STATE *ParserState); + +void +AcpiPsGetNextSimpleArg ( + ACPI_PARSE_STATE *ParserState, + UINT32 ArgType, + ACPI_PARSE_OBJECT *Arg); + +ACPI_STATUS +AcpiPsGetNextNamepath ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *Arg, + BOOLEAN MethodCall); + +ACPI_STATUS +AcpiPsGetNextArg ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_STATE *ParserState, + UINT32 ArgType, + ACPI_PARSE_OBJECT **ReturnArg); + + +/* + * psfind + */ +ACPI_PARSE_OBJECT * +AcpiPsFindName ( + ACPI_PARSE_OBJECT *Scope, + UINT32 Name, + UINT32 Opcode); + +ACPI_PARSE_OBJECT* +AcpiPsGetParent ( + ACPI_PARSE_OBJECT *Op); + + +/* + * psopcode - AML Opcode information + */ +const ACPI_OPCODE_INFO * +AcpiPsGetOpcodeInfo ( + UINT16 Opcode); + +char * +AcpiPsGetOpcodeName ( + UINT16 Opcode); + +UINT8 +AcpiPsGetArgumentCount ( + UINT32 OpType); + + +/* + * psparse - top level parsing routines + */ +ACPI_STATUS +AcpiPsParseAml ( + ACPI_WALK_STATE *WalkState); + +UINT32 +AcpiPsGetOpcodeSize ( + UINT32 Opcode); + +UINT16 +AcpiPsPeekOpcode ( + ACPI_PARSE_STATE *state); + +ACPI_STATUS +AcpiPsCompleteThisOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +ACPI_STATUS +AcpiPsNextParseState ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS CallbackStatus); + + +/* + * psloop - main parse loop + */ +ACPI_STATUS +AcpiPsParseLoop ( + ACPI_WALK_STATE *WalkState); + + +/* + * psscope - Scope stack management routines + */ +ACPI_STATUS +AcpiPsInitScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *Root); + +ACPI_PARSE_OBJECT * +AcpiPsGetParentScope ( + ACPI_PARSE_STATE *state); + +BOOLEAN +AcpiPsHasCompletedScope ( + ACPI_PARSE_STATE *ParserState); + +void +AcpiPsPopScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT **Op, + UINT32 *ArgList, + UINT32 *ArgCount); + +ACPI_STATUS +AcpiPsPushScope ( + ACPI_PARSE_STATE *ParserState, + ACPI_PARSE_OBJECT *Op, + UINT32 RemainingArgs, + UINT32 ArgCount); + +void +AcpiPsCleanupScope ( + ACPI_PARSE_STATE *state); + + +/* + * pstree - parse tree manipulation routines + */ +void +AcpiPsAppendArg( + ACPI_PARSE_OBJECT *op, + ACPI_PARSE_OBJECT *arg); + +ACPI_PARSE_OBJECT* +AcpiPsFind ( + ACPI_PARSE_OBJECT *Scope, + char *Path, + UINT16 Opcode, + UINT32 Create); + +ACPI_PARSE_OBJECT * +AcpiPsGetArg( + ACPI_PARSE_OBJECT *op, + UINT32 argn); + +ACPI_PARSE_OBJECT * +AcpiPsGetDepthNext ( + ACPI_PARSE_OBJECT *Origin, + ACPI_PARSE_OBJECT *Op); + + +/* + * pswalk - parse tree walk routines + */ +ACPI_STATUS +AcpiPsWalkParsedAml ( + ACPI_PARSE_OBJECT *StartOp, + ACPI_PARSE_OBJECT *EndOp, + ACPI_OPERAND_OBJECT *MthDesc, + ACPI_NAMESPACE_NODE *StartNode, + ACPI_OPERAND_OBJECT **Params, + ACPI_OPERAND_OBJECT **CallerReturnDesc, + ACPI_OWNER_ID OwnerId, + ACPI_PARSE_DOWNWARDS DescendingCallback, + ACPI_PARSE_UPWARDS AscendingCallback); + +ACPI_STATUS +AcpiPsGetNextWalkOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_PARSE_UPWARDS AscendingCallback); + +ACPI_STATUS +AcpiPsDeleteCompletedOp ( + ACPI_WALK_STATE *WalkState); + +void +AcpiPsDeleteParseTree ( + ACPI_PARSE_OBJECT *root); + + +/* + * psutils - parser utilities + */ +ACPI_PARSE_OBJECT * +AcpiPsCreateScopeOp ( + void); + +void +AcpiPsInitOp ( + ACPI_PARSE_OBJECT *op, + UINT16 opcode); + +ACPI_PARSE_OBJECT * +AcpiPsAllocOp ( + UINT16 opcode); + +void +AcpiPsFreeOp ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiPsIsLeadingChar ( + UINT32 c); + +BOOLEAN +AcpiPsIsPrefixChar ( + UINT32 c); + +UINT32 +AcpiPsGetName( + ACPI_PARSE_OBJECT *op); + +void +AcpiPsSetName( + ACPI_PARSE_OBJECT *op, + UINT32 name); + + +/* + * psdump - display parser tree + */ +UINT32 +AcpiPsSprintPath ( + char *BufferStart, + UINT32 BufferSize, + ACPI_PARSE_OBJECT *Op); + +UINT32 +AcpiPsSprintOp ( + char *BufferStart, + UINT32 BufferSize, + ACPI_PARSE_OBJECT *Op); + +void +AcpiPsShow ( + ACPI_PARSE_OBJECT *op); + + +#endif /* __ACPARSER_H__ */ diff --git a/source/include/acpi.h b/source/include/acpi.h new file mode 100644 index 000000000000..aa40219112b7 --- /dev/null +++ b/source/include/acpi.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Name: acpi.h - Master public include file used to interface to ACPICA + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACPI_H__ +#define __ACPI_H__ + +/* + * Public include files for use by code that will interface to ACPICA. + * + * Information includes the ACPICA data types, names, exceptions, and + * external interface prototypes. Also included are the definitions for + * all ACPI tables (FADT, MADT, etc.) + * + * Note: The order of these include files is important. + */ +#include "platform/acenv.h" /* Environment-specific items */ +#include "acnames.h" /* Common ACPI names and strings */ +#include "actypes.h" /* ACPICA data types and structures */ +#include "acexcep.h" /* ACPICA exceptions */ +#include "actbl.h" /* ACPI table definitions */ +#include "acoutput.h" /* Error output and Debug macros */ +#include "acrestyp.h" /* Resource Descriptor structs */ +#include "acpiosxf.h" /* OSL interfaces (ACPICA-to-OS) */ +#include "acpixf.h" /* ACPI core subsystem external interfaces */ + +#endif /* __ACPI_H__ */ diff --git a/source/include/acpiosxf.h b/source/include/acpiosxf.h new file mode 100644 index 000000000000..b79d0e6ade4e --- /dev/null +++ b/source/include/acpiosxf.h @@ -0,0 +1,416 @@ + +/****************************************************************************** + * + * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These + * interfaces must be implemented by OSL to interface the + * ACPI components to the host operating system. + * + *****************************************************************************/ + + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACPIOSXF_H__ +#define __ACPIOSXF_H__ + +#include "platform/acenv.h" +#include "actypes.h" + + +/* Types for AcpiOsExecute */ + +typedef enum +{ + OSL_GLOBAL_LOCK_HANDLER, + OSL_NOTIFY_HANDLER, + OSL_GPE_HANDLER, + OSL_DEBUGGER_THREAD, + OSL_EC_POLL_HANDLER, + OSL_EC_BURST_HANDLER + +} ACPI_EXECUTE_TYPE; + +#define ACPI_NO_UNIT_LIMIT ((UINT32) -1) +#define ACPI_MUTEX_SEM 1 + + +/* Functions for AcpiOsSignal */ + +#define ACPI_SIGNAL_FATAL 0 +#define ACPI_SIGNAL_BREAKPOINT 1 + +typedef struct acpi_signal_fatal_info +{ + UINT32 Type; + UINT32 Code; + UINT32 Argument; + +} ACPI_SIGNAL_FATAL_INFO; + + +/* + * OSL Initialization and shutdown primitives + */ +ACPI_STATUS +AcpiOsInitialize ( + void); + +ACPI_STATUS +AcpiOsTerminate ( + void); + + +/* + * ACPI Table interfaces + */ +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void); + +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal); + +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); + +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength); + + +/* + * Spinlock primitives + */ +ACPI_STATUS +AcpiOsCreateLock ( + ACPI_SPINLOCK *OutHandle); + +void +AcpiOsDeleteLock ( + ACPI_SPINLOCK Handle); + +ACPI_CPU_FLAGS +AcpiOsAcquireLock ( + ACPI_SPINLOCK Handle); + +void +AcpiOsReleaseLock ( + ACPI_SPINLOCK Handle, + ACPI_CPU_FLAGS Flags); + + +/* + * Semaphore primitives + */ +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_SEMAPHORE *OutHandle); + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_SEMAPHORE Handle); + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units, + UINT16 Timeout); + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units); + + +/* + * Mutex primitives. May be configured to use semaphores instead via + * ACPI_MUTEX_TYPE (see platform/acenv.h) + */ +#if (ACPI_MUTEX_TYPE != ACPI_BINARY_SEMAPHORE) + +ACPI_STATUS +AcpiOsCreateMutex ( + ACPI_MUTEX *OutHandle); + +void +AcpiOsDeleteMutex ( + ACPI_MUTEX Handle); + +ACPI_STATUS +AcpiOsAcquireMutex ( + ACPI_MUTEX Handle, + UINT16 Timeout); + +void +AcpiOsReleaseMutex ( + ACPI_MUTEX Handle); +#endif + + +/* + * Memory allocation and mapping + */ +void * +AcpiOsAllocate ( + ACPI_SIZE Size); + +void +AcpiOsFree ( + void * Memory); + +void * +AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS Where, + ACPI_SIZE Length); + +void +AcpiOsUnmapMemory ( + void *LogicalAddress, + ACPI_SIZE Size); + +ACPI_STATUS +AcpiOsGetPhysicalAddress ( + void *LogicalAddress, + ACPI_PHYSICAL_ADDRESS *PhysicalAddress); + + +/* + * Memory/Object Cache + */ +ACPI_STATUS +AcpiOsCreateCache ( + char *CacheName, + UINT16 ObjectSize, + UINT16 MaxDepth, + ACPI_CACHE_T **ReturnCache); + +ACPI_STATUS +AcpiOsDeleteCache ( + ACPI_CACHE_T *Cache); + +ACPI_STATUS +AcpiOsPurgeCache ( + ACPI_CACHE_T *Cache); + +void * +AcpiOsAcquireObject ( + ACPI_CACHE_T *Cache); + +ACPI_STATUS +AcpiOsReleaseObject ( + ACPI_CACHE_T *Cache, + void *Object); + + +/* + * Interrupt handlers + */ +ACPI_STATUS +AcpiOsInstallInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine, + void *Context); + +ACPI_STATUS +AcpiOsRemoveInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine); + + +/* + * Threads and Scheduling + */ +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void); + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context); + +void +AcpiOsWaitEventsComplete ( + void *Context); + +void +AcpiOsSleep ( + UINT64 Milliseconds); + +void +AcpiOsStall ( + UINT32 Microseconds); + + +/* + * Platform and hardware-independent I/O interfaces + */ +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width); + +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width); + + +/* + * Platform and hardware-independent physical memory interfaces + */ +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 *Value, + UINT32 Width); + +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 Value, + UINT32 Width); + + +/* + * Platform and hardware-independent PCI configuration space access + * Note: Can't use "Register" as a parameter, changed to "Reg" -- + * certain compilers complain. + */ +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Reg, + UINT64 *Value, + UINT32 Width); + +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Reg, + UINT64 Value, + UINT32 Width); + + +/* + * Miscellaneous + */ +BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length); + +BOOLEAN +AcpiOsWritable ( + void *Pointer, + ACPI_SIZE Length); + +UINT64 +AcpiOsGetTimer ( + void); + +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info); + + +/* + * Debug print routines + */ +void ACPI_INTERNAL_VAR_XFACE +AcpiOsPrintf ( + const char *Format, + ...); + +void +AcpiOsVprintf ( + const char *Format, + va_list Args); + +void +AcpiOsRedirectOutput ( + void *Destination); + + +/* + * Debug input + */ +ACPI_STATUS +AcpiOsGetLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead); + + +/* + * Directory manipulation + */ +void * +AcpiOsOpenDirectory ( + char *Pathname, + char *WildcardSpec, + char RequestedFileType); + +/* RequesteFileType values */ + +#define REQUEST_FILE_ONLY 0 +#define REQUEST_DIR_ONLY 1 + + +char * +AcpiOsGetNextFilename ( + void *DirHandle); + +void +AcpiOsCloseDirectory ( + void *DirHandle); + + +#endif /* __ACPIOSXF_H__ */ diff --git a/source/include/acpixf.h b/source/include/acpixf.h new file mode 100644 index 000000000000..fafa51f8ebf4 --- /dev/null +++ b/source/include/acpixf.h @@ -0,0 +1,785 @@ + +/****************************************************************************** + * + * Name: acpixf.h - External interfaces to the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __ACXFACE_H__ +#define __ACXFACE_H__ + +/* Current ACPICA subsystem version in YYYYMMDD format */ + +#define ACPI_CA_VERSION 0x20120215 + +#include "acconfig.h" +#include "actypes.h" +#include "actbl.h" + +/* + * Globals that are publically available + */ +extern UINT32 AcpiCurrentGpeCount; +extern ACPI_TABLE_FADT AcpiGbl_FADT; +extern BOOLEAN AcpiGbl_SystemAwakeAndRunning; +extern BOOLEAN AcpiGbl_ReducedHardware; /* ACPI 5.0 */ + +/* Runtime configuration of debug print levels */ + +extern UINT32 AcpiDbgLevel; +extern UINT32 AcpiDbgLayer; + +/* ACPICA runtime options */ + +extern UINT8 AcpiGbl_EnableInterpreterSlack; +extern UINT8 AcpiGbl_AllMethodsSerialized; +extern UINT8 AcpiGbl_CreateOsiMethod; +extern UINT8 AcpiGbl_UseDefaultRegisterWidths; +extern ACPI_NAME AcpiGbl_TraceMethodName; +extern UINT32 AcpiGbl_TraceFlags; +extern UINT8 AcpiGbl_EnableAmlDebugObject; +extern UINT8 AcpiGbl_CopyDsdtLocally; +extern UINT8 AcpiGbl_TruncateIoAddresses; +extern UINT8 AcpiGbl_DisableAutoRepair; + + +/* + * Hardware-reduced prototypes. All interfaces that use these macros will + * be configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag + * is set to TRUE. + */ +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_DEPENDENT_RETURN_STATUS(Prototype) \ + Prototype; + +#define ACPI_HW_DEPENDENT_RETURN_OK(Prototype) \ + Prototype; + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + Prototype; + +#else +#define ACPI_HW_DEPENDENT_RETURN_STATUS(Prototype) \ + static ACPI_INLINE Prototype {return(AE_NOT_CONFIGURED);} + +#define ACPI_HW_DEPENDENT_RETURN_OK(Prototype) \ + static ACPI_INLINE Prototype {return(AE_OK);} + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {} + +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/* + * Initialization + */ +ACPI_STATUS +AcpiInitializeTables ( + ACPI_TABLE_DESC *InitialStorage, + UINT32 InitialTableCount, + BOOLEAN AllowResize); + +ACPI_STATUS +AcpiInitializeSubsystem ( + void); + +ACPI_STATUS +AcpiEnableSubsystem ( + UINT32 Flags); + +ACPI_STATUS +AcpiInitializeObjects ( + UINT32 Flags); + +ACPI_STATUS +AcpiTerminate ( + void); + + +/* + * Miscellaneous global interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnable ( + void)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiDisable ( + void)) + +ACPI_STATUS +AcpiSubsystemStatus ( + void); + +ACPI_STATUS +AcpiGetSystemInfo ( + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiGetStatistics ( + ACPI_STATISTICS *Stats); + +const char * +AcpiFormatException ( + ACPI_STATUS Exception); + +ACPI_STATUS +AcpiPurgeCachedObjects ( + void); + +ACPI_STATUS +AcpiInstallInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiRemoveInterface ( + ACPI_STRING InterfaceName); + +UINT32 +AcpiCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + ACPI_SIZE Length, + BOOLEAN Warn); + + +/* + * ACPI Memory management + */ +void * +AcpiAllocate ( + UINT32 Size); + +void * +AcpiCallocate ( + UINT32 Size); + +void +AcpiFree ( + void *Address); + + +/* + * ACPI table manipulation interfaces + */ +ACPI_STATUS +AcpiReallocateRootTable ( + void); + +ACPI_STATUS +AcpiFindRootPointer ( + ACPI_SIZE *RsdpAddress); + +ACPI_STATUS +AcpiLoadTables ( + void); + +ACPI_STATUS +AcpiGetTableHeader ( + ACPI_STRING Signature, + UINT32 Instance, + ACPI_TABLE_HEADER *OutTableHeader); + +ACPI_STATUS +AcpiGetTable ( + ACPI_STRING Signature, + UINT32 Instance, + ACPI_TABLE_HEADER **OutTable); + +ACPI_STATUS +AcpiGetTableByIndex ( + UINT32 TableIndex, + ACPI_TABLE_HEADER **OutTable); + +ACPI_STATUS +AcpiInstallTableHandler ( + ACPI_TABLE_HANDLER Handler, + void *Context); + +ACPI_STATUS +AcpiRemoveTableHandler ( + ACPI_TABLE_HANDLER Handler); + + +/* + * Namespace and name interfaces + */ +ACPI_STATUS +AcpiWalkNamespace ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE StartObject, + UINT32 MaxDepth, + ACPI_WALK_CALLBACK PreOrderVisit, + ACPI_WALK_CALLBACK PostOrderVisit, + void *Context, + void **ReturnValue); + +ACPI_STATUS +AcpiGetDevices ( + char *HID, + ACPI_WALK_CALLBACK UserFunction, + void *Context, + void **ReturnValue); + +ACPI_STATUS +AcpiGetName ( + ACPI_HANDLE Object, + UINT32 NameType, + ACPI_BUFFER *RetPathPtr); + +ACPI_STATUS +AcpiGetHandle ( + ACPI_HANDLE Parent, + ACPI_STRING Pathname, + ACPI_HANDLE *RetHandle); + +ACPI_STATUS +AcpiAttachData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler, + void *Data); + +ACPI_STATUS +AcpiDetachData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler); + +ACPI_STATUS +AcpiGetData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler, + void **Data); + +ACPI_STATUS +AcpiDebugTrace ( + char *Name, + UINT32 DebugLevel, + UINT32 DebugLayer, + UINT32 Flags); + + +/* + * Object manipulation and enumeration + */ +ACPI_STATUS +AcpiEvaluateObject ( + ACPI_HANDLE Object, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ParameterObjects, + ACPI_BUFFER *ReturnObjectBuffer); + +ACPI_STATUS +AcpiEvaluateObjectTyped ( + ACPI_HANDLE Object, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ExternalParams, + ACPI_BUFFER *ReturnBuffer, + ACPI_OBJECT_TYPE ReturnType); + +ACPI_STATUS +AcpiGetObjectInfo ( + ACPI_HANDLE Object, + ACPI_DEVICE_INFO **ReturnBuffer); + +ACPI_STATUS +AcpiInstallMethod ( + UINT8 *Buffer); + +ACPI_STATUS +AcpiGetNextObject ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE Parent, + ACPI_HANDLE Child, + ACPI_HANDLE *OutHandle); + +ACPI_STATUS +AcpiGetType ( + ACPI_HANDLE Object, + ACPI_OBJECT_TYPE *OutType); + +ACPI_STATUS +AcpiGetParent ( + ACPI_HANDLE Object, + ACPI_HANDLE *OutHandle); + + +/* + * Handler interfaces + */ +ACPI_STATUS +AcpiInstallInitializationHandler ( + ACPI_INIT_HANDLER Handler, + UINT32 Function); + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallGlobalEventHandler ( + ACPI_GBL_EVENT_HANDLER Handler, + void *Context)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallFixedEventHandler ( + UINT32 AcpiEvent, + ACPI_EVENT_HANDLER Handler, + void *Context)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveFixedEventHandler ( + UINT32 AcpiEvent, + ACPI_EVENT_HANDLER Handler)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT32 Type, + ACPI_GPE_HANDLER Address, + void *Context)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + ACPI_GPE_HANDLER Address)) + +ACPI_STATUS +AcpiInstallNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler, + void *Context); + +ACPI_STATUS +AcpiRemoveNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler); + +ACPI_STATUS +AcpiInstallAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context); + +ACPI_STATUS +AcpiRemoveAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler); + +ACPI_STATUS +AcpiInstallExceptionHandler ( + ACPI_EXCEPTION_HANDLER Handler); + +ACPI_STATUS +AcpiInstallInterfaceHandler ( + ACPI_INTERFACE_HANDLER Handler); + + +/* + * Global Lock interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiAcquireGlobalLock ( + UINT16 Timeout, + UINT32 *Handle)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiReleaseGlobalLock ( + UINT32 Handle)) + + +/* + * Interfaces to AML mutex objects + */ +ACPI_STATUS +AcpiAcquireMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + UINT16 Timeout); + +ACPI_STATUS +AcpiReleaseMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname); + + +/* + * Fixed Event interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnableEvent ( + UINT32 Event, + UINT32 Flags)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiDisableEvent ( + UINT32 Event, + UINT32 Flags)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiClearEvent ( + UINT32 Event)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetEventStatus ( + UINT32 Event, + ACPI_EVENT_STATUS *EventStatus)) + + +/* + * General Purpose Event (GPE) Interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiUpdateAllGpes ( + void)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnableGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiDisableGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiClearGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiSetGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT8 Action)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiFinishGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiSetupGpeForWake ( + ACPI_HANDLE ParentDevice, + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiSetGpeWakeMask ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT8 Action)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetGpeStatus ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + ACPI_EVENT_STATUS *EventStatus)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiDisableAllGpes ( + void)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnableAllRuntimeGpes ( + void)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetGpeDevice ( + UINT32 GpeIndex, + ACPI_HANDLE *GpeDevice)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallGpeBlock ( + ACPI_HANDLE GpeDevice, + ACPI_GENERIC_ADDRESS *GpeBlockAddress, + UINT32 RegisterCount, + UINT32 InterruptNumber)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveGpeBlock ( + ACPI_HANDLE GpeDevice)) + + +/* + * Resource interfaces + */ +typedef +ACPI_STATUS (*ACPI_WALK_RESOURCE_CALLBACK) ( + ACPI_RESOURCE *Resource, + void *Context); + +ACPI_STATUS +AcpiGetVendorResource ( + ACPI_HANDLE Device, + char *Name, + ACPI_VENDOR_UUID *Uuid, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiGetCurrentResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiGetPossibleResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiGetEventResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiWalkResources ( + ACPI_HANDLE Device, + char *Name, + ACPI_WALK_RESOURCE_CALLBACK UserFunction, + void *Context); + +ACPI_STATUS +AcpiSetCurrentResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *InBuffer); + +ACPI_STATUS +AcpiGetIrqRoutingTable ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiResourceToAddress64 ( + ACPI_RESOURCE *Resource, + ACPI_RESOURCE_ADDRESS64 *Out); + +ACPI_STATUS +AcpiBufferToResource ( + UINT8 *AmlBuffer, + UINT16 AmlBufferLength, + ACPI_RESOURCE **ResourcePtr); + + +/* + * Hardware (ACPI device) interfaces + */ +ACPI_STATUS +AcpiReset ( + void); + +ACPI_STATUS +AcpiRead ( + UINT64 *Value, + ACPI_GENERIC_ADDRESS *Reg); + +ACPI_STATUS +AcpiWrite ( + UINT64 Value, + ACPI_GENERIC_ADDRESS *Reg); + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiReadBitRegister ( + UINT32 RegisterId, + UINT32 *ReturnValue)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiWriteBitRegister ( + UINT32 RegisterId, + UINT32 Value)) + + +/* + * Sleep/Wake interfaces + */ +ACPI_STATUS +AcpiGetSleepTypeData ( + UINT8 SleepState, + UINT8 *Slp_TypA, + UINT8 *Slp_TypB); + +ACPI_STATUS +AcpiEnterSleepStatePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiEnterSleepState ( + UINT8 SleepState); + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnterSleepStateS4bios ( + void)) + +ACPI_STATUS +AcpiLeaveSleepStatePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiLeaveSleepState ( + UINT8 SleepState); + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiSetFirmwareWakingVector ( + UINT32 PhysicalAddress)) + +#if ACPI_MACHINE_WIDTH == 64 +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiSetFirmwareWakingVector64 ( + UINT64 PhysicalAddress)) +#endif + + +/* + * ACPI Timer interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimerResolution ( + UINT32 *Resolution)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimer ( + UINT32 *Ticks)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimerDuration ( + UINT32 StartTicks, + UINT32 EndTicks, + UINT32 *TimeElapsed)) + + +/* + * Error/Warning output + */ +void ACPI_INTERNAL_VAR_XFACE +AcpiError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) ACPI_PRINTF_LIKE(3); + +void ACPI_INTERNAL_VAR_XFACE +AcpiException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...) ACPI_PRINTF_LIKE(4); + +void ACPI_INTERNAL_VAR_XFACE +AcpiWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) ACPI_PRINTF_LIKE(3); + +void ACPI_INTERNAL_VAR_XFACE +AcpiInfo ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) ACPI_PRINTF_LIKE(3); + + +/* + * Debug output + */ +#ifdef ACPI_DEBUG_OUTPUT + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrint ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) ACPI_PRINTF_LIKE(6); + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrintRaw ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) ACPI_PRINTF_LIKE(6); +#endif + +#endif /* __ACXFACE_H__ */ diff --git a/source/include/acpredef.h b/source/include/acpredef.h new file mode 100644 index 000000000000..c17a6d914542 --- /dev/null +++ b/source/include/acpredef.h @@ -0,0 +1,564 @@ +/****************************************************************************** + * + * Name: acpredef - Information table for ACPI predefined methods and objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACPREDEF_H__ +#define __ACPREDEF_H__ + + +/****************************************************************************** + * + * Return Package types + * + * 1) PTYPE1 packages do not contain sub-packages. + * + * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: + * object type + * count + * object type + * count + * + * ACPI_PTYPE1_VAR: Variable-length length: + * object type (Int/Buf/Ref) + * + * ACPI_PTYPE1_OPTION: Package has some required and some optional elements + * (Used for _PRW) + * + * + * 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each + * of the different types describe the contents of each of the sub-packages. + * + * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: + * object type + * count + * object type + * count + * (Used for _ALR,_MLS,_PSS,_TRT,_TSS) + * + * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element: + * object type + * (Used for _CSD,_PSD,_TSD) + * + * ACPI_PTYPE2_PKG_COUNT: Count of subpackages at start, 1 or 2 object types: + * object type + * count + * object type + * count + * (Used for _CST) + * + * ACPI_PTYPE2_FIXED: Each subpackage is of Fixed-length + * (Used for _PRT) + * + * ACPI_PTYPE2_MIN: Each subpackage has a Variable-length but minimum length + * (Used for _HPX) + * + * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length + * (Used for _ART, _FPS) + * + * ACPI_PTYPE2_FIX_VAR: Each subpackage consists of some fixed-length elements + * followed by an optional element + * object type + * count + * object type + * count = 0 (optional) + * (Used for _DLM) + * + *****************************************************************************/ + +enum AcpiReturnPackageTypes +{ + ACPI_PTYPE1_FIXED = 1, + ACPI_PTYPE1_VAR = 2, + ACPI_PTYPE1_OPTION = 3, + ACPI_PTYPE2 = 4, + ACPI_PTYPE2_COUNT = 5, + ACPI_PTYPE2_PKG_COUNT = 6, + ACPI_PTYPE2_FIXED = 7, + ACPI_PTYPE2_MIN = 8, + ACPI_PTYPE2_REV_FIXED = 9, + ACPI_PTYPE2_FIX_VAR = 10 +}; + + +#ifdef ACPI_CREATE_PREDEFINED_TABLE +/* + * Predefined method/object information table. + * + * These are the names that can actually be evaluated via AcpiEvaluateObject. + * Not present in this table are the following: + * + * 1) Predefined/Reserved names that are never evaluated via + * AcpiEvaluateObject: + * _Lxx and _Exx GPE methods + * _Qxx EC methods + * _T_x compiler temporary variables + * + * 2) Predefined names that never actually exist within the AML code: + * Predefined resource descriptor field names + * + * 3) Predefined names that are implemented within ACPICA: + * _OSI + * + * 4) Some predefined names that are not documented within the ACPI spec. + * _WDG, _WED + * + * The main entries in the table each contain the following items: + * + * Name - The ACPI reserved name + * ParamCount - Number of arguments to the method + * ExpectedBtypes - Allowed type(s) for the return value. + * 0 means that no return value is expected. + * + * For methods that return packages, the next entry in the table contains + * information about the expected structure of the package. This information + * is saved here (rather than in a separate table) in order to minimize the + * overall size of the stored data. + * + * Note: The additional braces are intended to promote portability. + */ +static const ACPI_PREDEFINED_INFO PredefinedNames[] = +{ + {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC1", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC2", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC3", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC4", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC5", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC6", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC7", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC8", 0, ACPI_RTYPE_INTEGER}}, + {{"_AC9", 0, ACPI_RTYPE_INTEGER}}, + {{"_ADR", 0, ACPI_RTYPE_INTEGER}}, + {{"_AEI", 0, ACPI_RTYPE_BUFFER}}, + {{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL4", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL5", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL6", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL7", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL8", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_AL9", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_ALC", 0, ACPI_RTYPE_INTEGER}}, + {{"_ALI", 0, ACPI_RTYPE_INTEGER}}, + {{"_ALP", 0, ACPI_RTYPE_INTEGER}}, + {{"_ALR", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2 (Ints) */ + {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, + + {{"_ALT", 0, ACPI_RTYPE_INTEGER}}, + {{"_ART", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ + {{{ACPI_PTYPE2_REV_FIXED,ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 11,0}}, + + {{"_BBN", 0, ACPI_RTYPE_INTEGER}}, + {{"_BCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, + + {{"_BCM", 1, 0}}, + {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, + {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, + {{"_BFS", 1, 0}}, + {{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4,0}}, + + {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4,0}}, + + {{"_BLT", 3, 0}}, + {{"_BMA", 1, ACPI_RTYPE_INTEGER}}, + {{"_BMC", 1, 0}}, + {{"_BMD", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (5 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, + + {{"_BMS", 1, ACPI_RTYPE_INTEGER}}, + {{"_BQC", 0, ACPI_RTYPE_INTEGER}}, + {{"_BST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, + + {{"_BTM", 1, ACPI_RTYPE_INTEGER}}, + {{"_BTP", 1, 0}}, + {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ + {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, + {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, + + {{"_CLS", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0}, 0,0}}, + + {{"_CPC", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Bufs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0,0}, 0,0}}, + + {{"_CRS", 0, ACPI_RTYPE_BUFFER}}, + {{"_CRT", 0, ACPI_RTYPE_INTEGER}}, + {{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */ + {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, + + {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ + {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, + + {{"_CWS", 1, ACPI_RTYPE_INTEGER}}, + {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, + {{"_DCS", 0, ACPI_RTYPE_INTEGER}}, + {{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, + {{"_DDN", 0, ACPI_RTYPE_STRING}}, + {{"_DEP", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_DGS", 0, ACPI_RTYPE_INTEGER}}, + {{"_DIS", 0, 0}}, + + {{"_DLM", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */ + {{{ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1, ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER}, 0,0}}, + + {{"_DMA", 0, ACPI_RTYPE_BUFFER}}, + {{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, + + {{"_DOS", 1, 0}}, + {{"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ + {{"_DSS", 1, 0}}, + {{"_DSW", 3, 0}}, + {{"_DTI", 1, 0}}, + {{"_EC_", 0, ACPI_RTYPE_INTEGER}}, + {{"_EDL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs)*/ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_EJ0", 1, 0}}, + {{"_EJ1", 1, 0}}, + {{"_EJ2", 1, 0}}, + {{"_EJ3", 1, 0}}, + {{"_EJ4", 1, 0}}, + {{"_EJD", 0, ACPI_RTYPE_STRING}}, + {{"_ERR", 3, ACPI_RTYPE_INTEGER}}, /* Internal use only, used by ACPICA test suites */ + {{"_EVT", 1, 0}}, + {{"_FDE", 0, ACPI_RTYPE_BUFFER}}, + {{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}}, + + {{"_FDM", 1, 0}}, + {{"_FIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, + + {{"_FIX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, + + {{"_FPS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ + {{{ACPI_PTYPE2_REV_FIXED,ACPI_RTYPE_INTEGER, 5, 0}, 0,0}}, + + {{"_FSL", 1, 0}}, + {{"_FST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0}, 0,0}}, + + + {{"_GAI", 0, ACPI_RTYPE_INTEGER}}, + {{"_GCP", 0, ACPI_RTYPE_INTEGER}}, + {{"_GHL", 0, ACPI_RTYPE_INTEGER}}, + {{"_GLK", 0, ACPI_RTYPE_INTEGER}}, + {{"_GPD", 0, ACPI_RTYPE_INTEGER}}, + {{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ + {{"_GRT", 0, ACPI_RTYPE_BUFFER}}, + {{"_GSB", 0, ACPI_RTYPE_INTEGER}}, + {{"_GTF", 0, ACPI_RTYPE_BUFFER}}, + {{"_GTM", 0, ACPI_RTYPE_BUFFER}}, + {{"_GTS", 1, 0}}, + {{"_GWS", 1, ACPI_RTYPE_INTEGER}}, + {{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, + {{"_HOT", 0, ACPI_RTYPE_INTEGER}}, + {{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, + + /* + * For _HPX, a single package is returned, containing a Variable-length number + * of sub-packages. Each sub-package contains a PCI record setting. + * There are several different type of record settings, of different + * lengths, but all elements of all settings are Integers. + */ + {{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */ + {{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, + + {{"_HRV", 0, ACPI_RTYPE_INTEGER}}, + {{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ + {{"_INI", 0, 0}}, + {{"_IRC", 0, 0}}, + {{"_LCK", 1, 0}}, + {{"_LID", 0, ACPI_RTYPE_INTEGER}}, + {{"_MAT", 0, ACPI_RTYPE_BUFFER}}, + {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8,0}, 0,0}}, + + {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ + {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, + + {{"_MSG", 1, 0}}, + {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, + {{"_NTT", 0, ACPI_RTYPE_INTEGER}}, + {{"_OFF", 0, 0}}, + {{"_ON_", 0, 0}}, + {{"_OS_", 0, ACPI_RTYPE_STRING}}, + {{"_OSC", 4, ACPI_RTYPE_BUFFER}}, + {{"_OST", 3, 0}}, + {{"_PAI", 1, ACPI_RTYPE_INTEGER}}, + {{"_PCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PCT", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, + + {{"_PDC", 1, 0}}, + {{"_PDL", 0, ACPI_RTYPE_INTEGER}}, + {{"_PIC", 1, 0}}, + {{"_PIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int),(3 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING}, 3,0}}, + + {{"_PLD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Bufs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0}, 0,0}}, + + {{"_PMC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (11 Int),(3 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING}, 3,0}}, + + {{"_PMD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PMM", 0, ACPI_RTYPE_INTEGER}}, + {{"_PPC", 0, ACPI_RTYPE_INTEGER}}, + {{"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* See dig64 spec */ + {{"_PR0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PR1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PR2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PRE", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PRS", 0, ACPI_RTYPE_BUFFER}}, + + /* + * For _PRT, many BIOSs reverse the 3rd and 4th Package elements (Source + * and SourceIndex). This bug is so prevalent that there is code in the + * ACPICA Resource Manager to detect this and switch them back. For now, + * do not allow and issue a warning. To allow this and eliminate the + * warning, add the ACPI_RTYPE_REFERENCE type to the 4th element (index 3) + * in the statement below. + */ + {{"_PRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ + {{{ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER,ACPI_RTYPE_INTEGER}, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, + ACPI_RTYPE_INTEGER}}, + + {{"_PRW", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ + {{{ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, + ACPI_RTYPE_INTEGER}, ACPI_RTYPE_REFERENCE,0}}, + + {{"_PS0", 0, 0}}, + {{"_PS1", 0, 0}}, + {{"_PS2", 0, 0}}, + {{"_PS3", 0, 0}}, + {{"_PSC", 0, ACPI_RTYPE_INTEGER}}, + {{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */ + {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}}, + + {{"_PSE", 1, 0}}, + {{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_PSR", 0, ACPI_RTYPE_INTEGER}}, + {{"_PSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (6 Int) */ + {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0}, 0,0}}, + + {{"_PSV", 0, ACPI_RTYPE_INTEGER}}, + {{"_PSW", 1, 0}}, + {{"_PTC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, + + {{"_PTP", 2, ACPI_RTYPE_INTEGER}}, + {{"_PTS", 1, 0}}, + {{"_PUR", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, + + {{"_PXM", 0, ACPI_RTYPE_INTEGER}}, + {{"_REG", 2, 0}}, + {{"_REV", 0, ACPI_RTYPE_INTEGER}}, + {{"_RMV", 0, ACPI_RTYPE_INTEGER}}, + {{"_ROM", 2, ACPI_RTYPE_BUFFER}}, + {{"_RTV", 0, ACPI_RTYPE_INTEGER}}, + + /* + * For _S0_ through _S5_, the ACPI spec defines a return Package + * containing 1 Integer, but most DSDTs have it wrong - 2,3, or 4 integers. + * Allow this by making the objects "Variable-length length", but all elements + * must be Integers. + */ + {{"_S0_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S1_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S2_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S3_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S4_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S5_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, + + {{"_S1D", 0, ACPI_RTYPE_INTEGER}}, + {{"_S2D", 0, ACPI_RTYPE_INTEGER}}, + {{"_S3D", 0, ACPI_RTYPE_INTEGER}}, + {{"_S4D", 0, ACPI_RTYPE_INTEGER}}, + {{"_S0W", 0, ACPI_RTYPE_INTEGER}}, + {{"_S1W", 0, ACPI_RTYPE_INTEGER}}, + {{"_S2W", 0, ACPI_RTYPE_INTEGER}}, + {{"_S3W", 0, ACPI_RTYPE_INTEGER}}, + {{"_S4W", 0, ACPI_RTYPE_INTEGER}}, + {{"_SBS", 0, ACPI_RTYPE_INTEGER}}, + {{"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ + /* Note: the 3-arg definition may be removed for ACPI 4.0 */ + {{"_SDD", 1, 0}}, + {{"_SEG", 0, ACPI_RTYPE_INTEGER}}, + {{"_SHL", 1, ACPI_RTYPE_INTEGER}}, + {{"_SLI", 0, ACPI_RTYPE_BUFFER}}, + {{"_SPD", 1, ACPI_RTYPE_INTEGER}}, + {{"_SRS", 1, 0}}, + {{"_SRT", 1, ACPI_RTYPE_INTEGER}}, + {{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ + {{"_SST", 1, 0}}, + {{"_STA", 0, ACPI_RTYPE_INTEGER}}, + {{"_STM", 3, 0}}, + {{"_STP", 2, ACPI_RTYPE_INTEGER}}, + {{"_STR", 0, ACPI_RTYPE_BUFFER}}, + {{"_STV", 2, ACPI_RTYPE_INTEGER}}, + {{"_SUB", 0, ACPI_RTYPE_STRING}}, + {{"_SUN", 0, ACPI_RTYPE_INTEGER}}, + {{"_SWS", 0, ACPI_RTYPE_INTEGER}}, + {{"_TC1", 0, ACPI_RTYPE_INTEGER}}, + {{"_TC2", 0, ACPI_RTYPE_INTEGER}}, + {{"_TDL", 0, ACPI_RTYPE_INTEGER}}, + {{"_TIP", 1, ACPI_RTYPE_INTEGER}}, + {{"_TIV", 1, ACPI_RTYPE_INTEGER}}, + {{"_TMP", 0, ACPI_RTYPE_INTEGER}}, + {{"_TPC", 0, ACPI_RTYPE_INTEGER}}, + {{"_TPT", 1, 0}}, + {{"_TRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2Ref/6Int */ + {{{ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 6, 0}}, + + {{"_TSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5Int with count */ + {{{ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, + + {{"_TSP", 0, ACPI_RTYPE_INTEGER}}, + {{"_TSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5Int */ + {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, + + {{"_TST", 0, ACPI_RTYPE_INTEGER}}, + {{"_TTS", 1, 0}}, + {{"_TZD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, + + {{"_TZM", 0, ACPI_RTYPE_REFERENCE}}, + {{"_TZP", 0, ACPI_RTYPE_INTEGER}}, + {{"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, + {{"_UPC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, + + {{"_UPD", 0, ACPI_RTYPE_INTEGER}}, + {{"_UPP", 0, ACPI_RTYPE_INTEGER}}, + {{"_VPO", 0, ACPI_RTYPE_INTEGER}}, + + /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ + + {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */ + + /* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */ + + {{"_WDG", 0, ACPI_RTYPE_BUFFER}}, + {{"_WED", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER}}, + + {{{0,0,0,0}, 0,0}} /* Table terminator */ +}; + +#if 0 + + /* This is an internally implemented control method, no need to check */ + {{"_OSI", 1, ACPI_RTYPE_INTEGER}}, + + /* TBD: */ + + _PRT - currently ignore reversed entries. Attempt to fix here? + Think about possibly fixing package elements like _BIF, etc. +#endif +#endif +#endif diff --git a/source/include/acresrc.h b/source/include/acresrc.h new file mode 100644 index 000000000000..c879fdc4a3f1 --- /dev/null +++ b/source/include/acresrc.h @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * Name: acresrc.h - Resource Manager function prototypes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACRESRC_H__ +#define __ACRESRC_H__ + +/* Need the AML resource descriptor structs */ + +#include "amlresrc.h" + + +/* + * If possible, pack the following structures to byte alignment, since we + * don't care about performance for debug output. Two cases where we cannot + * pack the structures: + * + * 1) Hardware does not support misaligned memory transfers + * 2) Compiler does not support pointers within packed structures + */ +#if (!defined(ACPI_MISALIGNMENT_NOT_SUPPORTED) && !defined(ACPI_PACKED_POINTERS_NOT_SUPPORTED)) +#pragma pack(1) +#endif + +/* + * Individual entry for the resource conversion tables + */ +typedef const struct acpi_rsconvert_info +{ + UINT8 Opcode; + UINT8 ResourceOffset; + UINT8 AmlOffset; + UINT8 Value; + +} ACPI_RSCONVERT_INFO; + +/* Resource conversion opcodes */ + +typedef enum +{ + ACPI_RSC_INITGET = 0, + ACPI_RSC_INITSET, + ACPI_RSC_FLAGINIT, + ACPI_RSC_1BITFLAG, + ACPI_RSC_2BITFLAG, + ACPI_RSC_3BITFLAG, + ACPI_RSC_ADDRESS, + ACPI_RSC_BITMASK, + ACPI_RSC_BITMASK16, + ACPI_RSC_COUNT, + ACPI_RSC_COUNT16, + ACPI_RSC_COUNT_GPIO_PIN, + ACPI_RSC_COUNT_GPIO_RES, + ACPI_RSC_COUNT_GPIO_VEN, + ACPI_RSC_COUNT_SERIAL_RES, + ACPI_RSC_COUNT_SERIAL_VEN, + ACPI_RSC_DATA8, + ACPI_RSC_EXIT_EQ, + ACPI_RSC_EXIT_LE, + ACPI_RSC_EXIT_NE, + ACPI_RSC_LENGTH, + ACPI_RSC_MOVE_GPIO_PIN, + ACPI_RSC_MOVE_GPIO_RES, + ACPI_RSC_MOVE_SERIAL_RES, + ACPI_RSC_MOVE_SERIAL_VEN, + ACPI_RSC_MOVE8, + ACPI_RSC_MOVE16, + ACPI_RSC_MOVE32, + ACPI_RSC_MOVE64, + ACPI_RSC_SET8, + ACPI_RSC_SOURCE, + ACPI_RSC_SOURCEX + +} ACPI_RSCONVERT_OPCODES; + +/* Resource Conversion sub-opcodes */ + +#define ACPI_RSC_COMPARE_AML_LENGTH 0 +#define ACPI_RSC_COMPARE_VALUE 1 + +#define ACPI_RSC_TABLE_SIZE(d) (sizeof (d) / sizeof (ACPI_RSCONVERT_INFO)) + +#define ACPI_RS_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE,f) +#define AML_OFFSET(f) (UINT8) ACPI_OFFSET (AML_RESOURCE,f) + + +/* + * Individual entry for the resource dump tables + */ +typedef const struct acpi_rsdump_info +{ + UINT8 Opcode; + UINT8 Offset; + char *Name; + const char **Pointer; + +} ACPI_RSDUMP_INFO; + +/* Values for the Opcode field above */ + +typedef enum +{ + ACPI_RSD_TITLE = 0, + ACPI_RSD_1BITFLAG, + ACPI_RSD_2BITFLAG, + ACPI_RSD_3BITFLAG, + ACPI_RSD_ADDRESS, + ACPI_RSD_DWORDLIST, + ACPI_RSD_LITERAL, + ACPI_RSD_LONGLIST, + ACPI_RSD_SHORTLIST, + ACPI_RSD_SHORTLISTX, + ACPI_RSD_SOURCE, + ACPI_RSD_STRING, + ACPI_RSD_UINT8, + ACPI_RSD_UINT16, + ACPI_RSD_UINT32, + ACPI_RSD_UINT64, + ACPI_RSD_WORDLIST + +} ACPI_RSDUMP_OPCODES; + +/* restore default alignment */ + +#pragma pack() + + +/* Resource tables indexed by internal resource type */ + +extern const UINT8 AcpiGbl_AmlResourceSizes[]; +extern const UINT8 AcpiGbl_AmlResourceSerialBusSizes[]; +extern ACPI_RSCONVERT_INFO *AcpiGbl_SetResourceDispatch[]; + +/* Resource tables indexed by raw AML resource descriptor type */ + +extern const UINT8 AcpiGbl_ResourceStructSizes[]; +extern const UINT8 AcpiGbl_ResourceStructSerialBusSizes[]; +extern ACPI_RSCONVERT_INFO *AcpiGbl_GetResourceDispatch[]; + +extern ACPI_RSCONVERT_INFO *AcpiGbl_ConvertResourceSerialBusDispatch[]; + +typedef struct acpi_vendor_walk_info +{ + ACPI_VENDOR_UUID *Uuid; + ACPI_BUFFER *Buffer; + ACPI_STATUS Status; + +} ACPI_VENDOR_WALK_INFO; + + +/* + * rscreate + */ +ACPI_STATUS +AcpiRsCreateResourceList ( + ACPI_OPERAND_OBJECT *AmlBuffer, + ACPI_BUFFER *OutputBuffer); + +ACPI_STATUS +AcpiRsCreateAmlResources ( + ACPI_RESOURCE *LinkedListBuffer, + ACPI_BUFFER *OutputBuffer); + +ACPI_STATUS +AcpiRsCreatePciRoutingTable ( + ACPI_OPERAND_OBJECT *PackageObject, + ACPI_BUFFER *OutputBuffer); + + +/* + * rsutils + */ +ACPI_STATUS +AcpiRsGetPrtMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiRsGetCrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiRsGetPrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiRsGetMethodData ( + ACPI_HANDLE Handle, + char *Path, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiRsSetSrsMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiRsGetAeiMethodData ( + ACPI_NAMESPACE_NODE *Node, + ACPI_BUFFER *RetBuffer); + +/* + * rscalc + */ +ACPI_STATUS +AcpiRsGetListLength ( + UINT8 *AmlBuffer, + UINT32 AmlBufferLength, + ACPI_SIZE *SizeNeeded); + +ACPI_STATUS +AcpiRsGetAmlLength ( + ACPI_RESOURCE *LinkedListBuffer, + ACPI_SIZE *SizeNeeded); + +ACPI_STATUS +AcpiRsGetPciRoutingTableLength ( + ACPI_OPERAND_OBJECT *PackageObject, + ACPI_SIZE *BufferSizeNeeded); + +ACPI_STATUS +AcpiRsConvertAmlToResources ( + UINT8 *Aml, + UINT32 Length, + UINT32 Offset, + UINT8 ResourceIndex, + void *Context); + +ACPI_STATUS +AcpiRsConvertResourcesToAml ( + ACPI_RESOURCE *Resource, + ACPI_SIZE AmlSizeNeeded, + UINT8 *OutputBuffer); + + +/* + * rsaddr + */ +void +AcpiRsSetAddressCommon ( + AML_RESOURCE *Aml, + ACPI_RESOURCE *Resource); + +BOOLEAN +AcpiRsGetAddressCommon ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml); + + +/* + * rsmisc + */ +ACPI_STATUS +AcpiRsConvertAmlToResource ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml, + ACPI_RSCONVERT_INFO *Info); + +ACPI_STATUS +AcpiRsConvertResourceToAml ( + ACPI_RESOURCE *Resource, + AML_RESOURCE *Aml, + ACPI_RSCONVERT_INFO *Info); + + +/* + * rsutils + */ +void +AcpiRsMoveData ( + void *Destination, + void *Source, + UINT16 ItemCount, + UINT8 MoveType); + +UINT8 +AcpiRsDecodeBitmask ( + UINT16 Mask, + UINT8 *List); + +UINT16 +AcpiRsEncodeBitmask ( + UINT8 *List, + UINT8 Count); + +ACPI_RS_LENGTH +AcpiRsGetResourceSource ( + ACPI_RS_LENGTH ResourceLength, + ACPI_RS_LENGTH MinimumLength, + ACPI_RESOURCE_SOURCE *ResourceSource, + AML_RESOURCE *Aml, + char *StringPtr); + +ACPI_RSDESC_SIZE +AcpiRsSetResourceSource ( + AML_RESOURCE *Aml, + ACPI_RS_LENGTH MinimumLength, + ACPI_RESOURCE_SOURCE *ResourceSource); + +void +AcpiRsSetResourceHeader ( + UINT8 DescriptorType, + ACPI_RSDESC_SIZE TotalLength, + AML_RESOURCE *Aml); + +void +AcpiRsSetResourceLength ( + ACPI_RSDESC_SIZE TotalLength, + AML_RESOURCE *Aml); + + +/* + * rsdump + */ +void +AcpiRsDumpResourceList ( + ACPI_RESOURCE *Resource); + +void +AcpiRsDumpIrqList ( + UINT8 *RouteTable); + + +/* + * Resource conversion tables + */ +extern ACPI_RSCONVERT_INFO AcpiRsConvertDma[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertEndDpf[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertIo[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertFixedIo[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertEndTag[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertMemory24[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertGenericReg[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertMemory32[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertFixedMemory32[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertAddress32[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertAddress16[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertAddress64[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertExtAddress64[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertGpio[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertSpiSerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertUartSerialBus[]; + +/* These resources require separate get/set tables */ + +extern ACPI_RSCONVERT_INFO AcpiRsGetIrq[]; +extern ACPI_RSCONVERT_INFO AcpiRsGetStartDpf[]; +extern ACPI_RSCONVERT_INFO AcpiRsGetVendorSmall[]; +extern ACPI_RSCONVERT_INFO AcpiRsGetVendorLarge[]; + +extern ACPI_RSCONVERT_INFO AcpiRsSetIrq[]; +extern ACPI_RSCONVERT_INFO AcpiRsSetStartDpf[]; +extern ACPI_RSCONVERT_INFO AcpiRsSetVendor[]; + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * rsinfo + */ +extern ACPI_RSDUMP_INFO *AcpiGbl_DumpResourceDispatch[]; +extern ACPI_RSDUMP_INFO *AcpiGbl_DumpSerialBusDispatch[]; + +/* + * rsdump + */ +extern ACPI_RSDUMP_INFO AcpiRsDumpIrq[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpDma[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpIo[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpVendor[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpEndTag[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpMemory24[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpMemory32[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpAddress16[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpAddress32[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpAddress64[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpGpio[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[]; +#endif + +#endif /* __ACRESRC_H__ */ diff --git a/source/include/acrestyp.h b/source/include/acrestyp.h new file mode 100644 index 000000000000..b927c9c58eb4 --- /dev/null +++ b/source/include/acrestyp.h @@ -0,0 +1,692 @@ +/****************************************************************************** + * + * Name: acrestyp.h - Defines, types, and structures for resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACRESTYP_H__ +#define __ACRESTYP_H__ + + +/* + * Definitions for Resource Attributes + */ +typedef UINT16 ACPI_RS_LENGTH; /* Resource Length field is fixed at 16 bits */ +typedef UINT32 ACPI_RSDESC_SIZE; /* Max Resource Descriptor size is (Length+3) = (64K-1)+3 */ + +/* + * Memory Attributes + */ +#define ACPI_READ_ONLY_MEMORY (UINT8) 0x00 +#define ACPI_READ_WRITE_MEMORY (UINT8) 0x01 + +#define ACPI_NON_CACHEABLE_MEMORY (UINT8) 0x00 +#define ACPI_CACHABLE_MEMORY (UINT8) 0x01 +#define ACPI_WRITE_COMBINING_MEMORY (UINT8) 0x02 +#define ACPI_PREFETCHABLE_MEMORY (UINT8) 0x03 + +/*! [Begin] no source code translation */ +/* + * IO Attributes + * The ISA IO ranges are: n000-n0FFh, n400-n4FFh, n800-n8FFh, nC00-nCFFh. + * The non-ISA IO ranges are: n100-n3FFh, n500-n7FFh, n900-nBFFh, nCD0-nFFFh. + */ +/*! [End] no source code translation !*/ + +#define ACPI_NON_ISA_ONLY_RANGES (UINT8) 0x01 +#define ACPI_ISA_ONLY_RANGES (UINT8) 0x02 +#define ACPI_ENTIRE_RANGE (ACPI_NON_ISA_ONLY_RANGES | ACPI_ISA_ONLY_RANGES) + +/* Type of translation - 1=Sparse, 0=Dense */ + +#define ACPI_SPARSE_TRANSLATION (UINT8) 0x01 + +/* + * IO Port Descriptor Decode + */ +#define ACPI_DECODE_10 (UINT8) 0x00 /* 10-bit IO address decode */ +#define ACPI_DECODE_16 (UINT8) 0x01 /* 16-bit IO address decode */ + +/* + * Interrupt attributes - used in multiple descriptors + */ + +/* Triggering */ + +#define ACPI_LEVEL_SENSITIVE (UINT8) 0x00 +#define ACPI_EDGE_SENSITIVE (UINT8) 0x01 + +/* Polarity */ + +#define ACPI_ACTIVE_HIGH (UINT8) 0x00 +#define ACPI_ACTIVE_LOW (UINT8) 0x01 +#define ACPI_ACTIVE_BOTH (UINT8) 0x02 + +/* Sharing */ + +#define ACPI_EXCLUSIVE (UINT8) 0x00 +#define ACPI_SHARED (UINT8) 0x01 +#define ACPI_EXCLUSIVE_AND_WAKE (UINT8) 0x02 +#define ACPI_SHARED_AND_WAKE (UINT8) 0x03 + +/* + * DMA Attributes + */ +#define ACPI_COMPATIBILITY (UINT8) 0x00 +#define ACPI_TYPE_A (UINT8) 0x01 +#define ACPI_TYPE_B (UINT8) 0x02 +#define ACPI_TYPE_F (UINT8) 0x03 + +#define ACPI_NOT_BUS_MASTER (UINT8) 0x00 +#define ACPI_BUS_MASTER (UINT8) 0x01 + +#define ACPI_TRANSFER_8 (UINT8) 0x00 +#define ACPI_TRANSFER_8_16 (UINT8) 0x01 +#define ACPI_TRANSFER_16 (UINT8) 0x02 + +/* + * Start Dependent Functions Priority definitions + */ +#define ACPI_GOOD_CONFIGURATION (UINT8) 0x00 +#define ACPI_ACCEPTABLE_CONFIGURATION (UINT8) 0x01 +#define ACPI_SUB_OPTIMAL_CONFIGURATION (UINT8) 0x02 + +/* + * 16, 32 and 64-bit Address Descriptor resource types + */ +#define ACPI_MEMORY_RANGE (UINT8) 0x00 +#define ACPI_IO_RANGE (UINT8) 0x01 +#define ACPI_BUS_NUMBER_RANGE (UINT8) 0x02 + +#define ACPI_ADDRESS_NOT_FIXED (UINT8) 0x00 +#define ACPI_ADDRESS_FIXED (UINT8) 0x01 + +#define ACPI_POS_DECODE (UINT8) 0x00 +#define ACPI_SUB_DECODE (UINT8) 0x01 + +/* Producer/Consumer */ + +#define ACPI_PRODUCER (UINT8) 0x00 +#define ACPI_CONSUMER (UINT8) 0x01 + + +/* + * If possible, pack the following structures to byte alignment + */ +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#pragma pack(1) +#endif + +/* UUID data structures for use in vendor-defined resource descriptors */ + +typedef struct acpi_uuid +{ + UINT8 Data[ACPI_UUID_LENGTH]; +} ACPI_UUID; + +typedef struct acpi_vendor_uuid +{ + UINT8 Subtype; + UINT8 Data[ACPI_UUID_LENGTH]; + +} ACPI_VENDOR_UUID; + +/* + * Structures used to describe device resources + */ +typedef struct acpi_resource_irq +{ + UINT8 DescriptorLength; + UINT8 Triggering; + UINT8 Polarity; + UINT8 Sharable; + UINT8 InterruptCount; + UINT8 Interrupts[1]; + +} ACPI_RESOURCE_IRQ; + +typedef struct acpi_resource_dma +{ + UINT8 Type; + UINT8 BusMaster; + UINT8 Transfer; + UINT8 ChannelCount; + UINT8 Channels[1]; + +} ACPI_RESOURCE_DMA; + +typedef struct acpi_resource_start_dependent +{ + UINT8 DescriptorLength; + UINT8 CompatibilityPriority; + UINT8 PerformanceRobustness; + +} ACPI_RESOURCE_START_DEPENDENT; + + +/* + * The END_DEPENDENT_FUNCTIONS_RESOURCE struct is not + * needed because it has no fields + */ + + +typedef struct acpi_resource_io +{ + UINT8 IoDecode; + UINT8 Alignment; + UINT8 AddressLength; + UINT16 Minimum; + UINT16 Maximum; + +} ACPI_RESOURCE_IO; + +typedef struct acpi_resource_fixed_io +{ + UINT16 Address; + UINT8 AddressLength; + +} ACPI_RESOURCE_FIXED_IO; + +typedef struct acpi_resource_fixed_dma +{ + UINT16 RequestLines; + UINT16 Channels; + UINT8 Width; + +} ACPI_RESOURCE_FIXED_DMA; + +/* Values for Width field above */ + +#define ACPI_DMA_WIDTH8 0 +#define ACPI_DMA_WIDTH16 1 +#define ACPI_DMA_WIDTH32 2 +#define ACPI_DMA_WIDTH64 3 +#define ACPI_DMA_WIDTH128 4 +#define ACPI_DMA_WIDTH256 5 + + +typedef struct acpi_resource_vendor +{ + UINT16 ByteLength; + UINT8 ByteData[1]; + +} ACPI_RESOURCE_VENDOR; + +/* Vendor resource with UUID info (introduced in ACPI 3.0) */ + +typedef struct acpi_resource_vendor_typed +{ + UINT16 ByteLength; + UINT8 UuidSubtype; + UINT8 Uuid[ACPI_UUID_LENGTH]; + UINT8 ByteData[1]; + +} ACPI_RESOURCE_VENDOR_TYPED; + +typedef struct acpi_resource_end_tag +{ + UINT8 Checksum; + +} ACPI_RESOURCE_END_TAG; + +typedef struct acpi_resource_memory24 +{ + UINT8 WriteProtect; + UINT16 Minimum; + UINT16 Maximum; + UINT16 Alignment; + UINT16 AddressLength; + +} ACPI_RESOURCE_MEMORY24; + +typedef struct acpi_resource_memory32 +{ + UINT8 WriteProtect; + UINT32 Minimum; + UINT32 Maximum; + UINT32 Alignment; + UINT32 AddressLength; + +} ACPI_RESOURCE_MEMORY32; + +typedef struct acpi_resource_fixed_memory32 +{ + UINT8 WriteProtect; + UINT32 Address; + UINT32 AddressLength; + +} ACPI_RESOURCE_FIXED_MEMORY32; + +typedef struct acpi_memory_attribute +{ + UINT8 WriteProtect; + UINT8 Caching; + UINT8 RangeType; + UINT8 Translation; + +} ACPI_MEMORY_ATTRIBUTE; + +typedef struct acpi_io_attribute +{ + UINT8 RangeType; + UINT8 Translation; + UINT8 TranslationType; + UINT8 Reserved1; + +} ACPI_IO_ATTRIBUTE; + +typedef union acpi_resource_attribute +{ + ACPI_MEMORY_ATTRIBUTE Mem; + ACPI_IO_ATTRIBUTE Io; + + /* Used for the *WordSpace macros */ + + UINT8 TypeSpecific; + +} ACPI_RESOURCE_ATTRIBUTE; + +typedef struct acpi_resource_source +{ + UINT8 Index; + UINT16 StringLength; + char *StringPtr; + +} ACPI_RESOURCE_SOURCE; + +/* Fields common to all address descriptors, 16/32/64 bit */ + +#define ACPI_RESOURCE_ADDRESS_COMMON \ + UINT8 ResourceType; \ + UINT8 ProducerConsumer; \ + UINT8 Decode; \ + UINT8 MinAddressFixed; \ + UINT8 MaxAddressFixed; \ + ACPI_RESOURCE_ATTRIBUTE Info; + +typedef struct acpi_resource_address +{ + ACPI_RESOURCE_ADDRESS_COMMON + +} ACPI_RESOURCE_ADDRESS; + +typedef struct acpi_resource_address16 +{ + ACPI_RESOURCE_ADDRESS_COMMON + UINT16 Granularity; + UINT16 Minimum; + UINT16 Maximum; + UINT16 TranslationOffset; + UINT16 AddressLength; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS16; + +typedef struct acpi_resource_address32 +{ + ACPI_RESOURCE_ADDRESS_COMMON + UINT32 Granularity; + UINT32 Minimum; + UINT32 Maximum; + UINT32 TranslationOffset; + UINT32 AddressLength; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS32; + +typedef struct acpi_resource_address64 +{ + ACPI_RESOURCE_ADDRESS_COMMON + UINT64 Granularity; + UINT64 Minimum; + UINT64 Maximum; + UINT64 TranslationOffset; + UINT64 AddressLength; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS64; + +typedef struct acpi_resource_extended_address64 +{ + ACPI_RESOURCE_ADDRESS_COMMON + UINT8 RevisionID; + UINT64 Granularity; + UINT64 Minimum; + UINT64 Maximum; + UINT64 TranslationOffset; + UINT64 AddressLength; + UINT64 TypeSpecific; + +} ACPI_RESOURCE_EXTENDED_ADDRESS64; + +typedef struct acpi_resource_extended_irq +{ + UINT8 ProducerConsumer; + UINT8 Triggering; + UINT8 Polarity; + UINT8 Sharable; + UINT8 InterruptCount; + ACPI_RESOURCE_SOURCE ResourceSource; + UINT32 Interrupts[1]; + +} ACPI_RESOURCE_EXTENDED_IRQ; + +typedef struct acpi_resource_generic_register +{ + UINT8 SpaceId; + UINT8 BitWidth; + UINT8 BitOffset; + UINT8 AccessSize; + UINT64 Address; + +} ACPI_RESOURCE_GENERIC_REGISTER; + +typedef struct acpi_resource_gpio +{ + UINT8 RevisionId; + UINT8 ConnectionType; + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */ + UINT8 PinConfig; + UINT8 Sharable; /* For values, see Interrupt Attributes above */ + UINT8 IoRestriction; + UINT8 Triggering; /* For values, see Interrupt Attributes above */ + UINT8 Polarity; /* For values, see Interrupt Attributes above */ + UINT16 DriveStrength; + UINT16 DebounceTimeout; + UINT16 PinTableLength; + UINT16 VendorLength; + ACPI_RESOURCE_SOURCE ResourceSource; + UINT16 *PinTable; + UINT8 *VendorData; + +} ACPI_RESOURCE_GPIO; + +/* Values for GPIO ConnectionType field above */ + +#define ACPI_RESOURCE_GPIO_TYPE_INT 0 +#define ACPI_RESOURCE_GPIO_TYPE_IO 1 + +/* Values for PinConfig field above */ + +#define ACPI_PIN_CONFIG_DEFAULT 0 +#define ACPI_PIN_CONFIG_PULLUP 1 +#define ACPI_PIN_CONFIG_PULLDOWN 2 +#define ACPI_PIN_CONFIG_NOPULL 3 + +/* Values for IoRestriction field above */ + +#define ACPI_IO_RESTRICT_NONE 0 +#define ACPI_IO_RESTRICT_INPUT 1 +#define ACPI_IO_RESTRICT_OUTPUT 2 +#define ACPI_IO_RESTRICT_NONE_PRESERVE 3 + + +/* Common structure for I2C, SPI, and UART serial descriptors */ + +#define ACPI_RESOURCE_SERIAL_COMMON \ + UINT8 RevisionId; \ + UINT8 Type; \ + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */\ + UINT8 SlaveMode; \ + UINT8 TypeRevisionId; \ + UINT16 TypeDataLength; \ + UINT16 VendorLength; \ + ACPI_RESOURCE_SOURCE ResourceSource; \ + UINT8 *VendorData; + +typedef struct acpi_resource_common_serialbus +{ + ACPI_RESOURCE_SERIAL_COMMON + +} ACPI_RESOURCE_COMMON_SERIALBUS; + +/* Values for the Type field above */ + +#define ACPI_RESOURCE_SERIAL_TYPE_I2C 1 +#define ACPI_RESOURCE_SERIAL_TYPE_SPI 2 +#define ACPI_RESOURCE_SERIAL_TYPE_UART 3 + +/* Values for SlaveMode field above */ + +#define ACPI_CONTROLLER_INITIATED 0 +#define ACPI_DEVICE_INITIATED 1 + + +typedef struct acpi_resource_i2c_serialbus +{ + ACPI_RESOURCE_SERIAL_COMMON + UINT8 AccessMode; + UINT16 SlaveAddress; + UINT32 ConnectionSpeed; + +} ACPI_RESOURCE_I2C_SERIALBUS; + +/* Values for AccessMode field above */ + +#define ACPI_I2C_7BIT_MODE 0 +#define ACPI_I2C_10BIT_MODE 1 + + +typedef struct acpi_resource_spi_serialbus +{ + ACPI_RESOURCE_SERIAL_COMMON + UINT8 WireMode; + UINT8 DevicePolarity; + UINT8 DataBitLength; + UINT8 ClockPhase; + UINT8 ClockPolarity; + UINT16 DeviceSelection; + UINT32 ConnectionSpeed; + +} ACPI_RESOURCE_SPI_SERIALBUS; + +/* Values for WireMode field above */ + +#define ACPI_SPI_4WIRE_MODE 0 +#define ACPI_SPI_3WIRE_MODE 1 + +/* Values for DevicePolarity field above */ + +#define ACPI_SPI_ACTIVE_LOW 0 +#define ACPI_SPI_ACTIVE_HIGH 1 + +/* Values for ClockPhase field above */ + +#define ACPI_SPI_FIRST_PHASE 0 +#define ACPI_SPI_SECOND_PHASE 1 + +/* Values for ClockPolarity field above */ + +#define ACPI_SPI_START_LOW 0 +#define ACPI_SPI_START_HIGH 1 + + +typedef struct acpi_resource_uart_serialbus +{ + ACPI_RESOURCE_SERIAL_COMMON + UINT8 Endian; + UINT8 DataBits; + UINT8 StopBits; + UINT8 FlowControl; + UINT8 Parity; + UINT8 LinesEnabled; + UINT16 RxFifoSize; + UINT16 TxFifoSize; + UINT32 DefaultBaudRate; + +} ACPI_RESOURCE_UART_SERIALBUS; + +/* Values for Endian field above */ + +#define ACPI_UART_LITTLE_ENDIAN 0 +#define ACPI_UART_BIG_ENDIAN 1 + +/* Values for DataBits field above */ + +#define ACPI_UART_5_DATA_BITS 0 +#define ACPI_UART_6_DATA_BITS 1 +#define ACPI_UART_7_DATA_BITS 2 +#define ACPI_UART_8_DATA_BITS 3 +#define ACPI_UART_9_DATA_BITS 4 + +/* Values for StopBits field above */ + +#define ACPI_UART_NO_STOP_BITS 0 +#define ACPI_UART_1_STOP_BIT 1 +#define ACPI_UART_1P5_STOP_BITS 2 +#define ACPI_UART_2_STOP_BITS 3 + +/* Values for FlowControl field above */ + +#define ACPI_UART_FLOW_CONTROL_NONE 0 +#define ACPI_UART_FLOW_CONTROL_HW 1 +#define ACPI_UART_FLOW_CONTROL_XON_XOFF 2 + +/* Values for Parity field above */ + +#define ACPI_UART_PARITY_NONE 0 +#define ACPI_UART_PARITY_EVEN 1 +#define ACPI_UART_PARITY_ODD 2 +#define ACPI_UART_PARITY_MARK 3 +#define ACPI_UART_PARITY_SPACE 4 + +/* Values for LinesEnabled bitfield above */ + +#define ACPI_UART_CARRIER_DETECT (1<<2) +#define ACPI_UART_RING_INDICATOR (1<<3) +#define ACPI_UART_DATA_SET_READY (1<<4) +#define ACPI_UART_DATA_TERMINAL_READY (1<<5) +#define ACPI_UART_CLEAR_TO_SEND (1<<6) +#define ACPI_UART_REQUEST_TO_SEND (1<<7) + + +/* ACPI_RESOURCE_TYPEs */ + +#define ACPI_RESOURCE_TYPE_IRQ 0 +#define ACPI_RESOURCE_TYPE_DMA 1 +#define ACPI_RESOURCE_TYPE_START_DEPENDENT 2 +#define ACPI_RESOURCE_TYPE_END_DEPENDENT 3 +#define ACPI_RESOURCE_TYPE_IO 4 +#define ACPI_RESOURCE_TYPE_FIXED_IO 5 +#define ACPI_RESOURCE_TYPE_VENDOR 6 +#define ACPI_RESOURCE_TYPE_END_TAG 7 +#define ACPI_RESOURCE_TYPE_MEMORY24 8 +#define ACPI_RESOURCE_TYPE_MEMORY32 9 +#define ACPI_RESOURCE_TYPE_FIXED_MEMORY32 10 +#define ACPI_RESOURCE_TYPE_ADDRESS16 11 +#define ACPI_RESOURCE_TYPE_ADDRESS32 12 +#define ACPI_RESOURCE_TYPE_ADDRESS64 13 +#define ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 14 /* ACPI 3.0 */ +#define ACPI_RESOURCE_TYPE_EXTENDED_IRQ 15 +#define ACPI_RESOURCE_TYPE_GENERIC_REGISTER 16 +#define ACPI_RESOURCE_TYPE_GPIO 17 /* ACPI 5.0 */ +#define ACPI_RESOURCE_TYPE_FIXED_DMA 18 /* ACPI 5.0 */ +#define ACPI_RESOURCE_TYPE_SERIAL_BUS 19 /* ACPI 5.0 */ +#define ACPI_RESOURCE_TYPE_MAX 19 + +/* Master union for resource descriptors */ + +typedef union acpi_resource_data +{ + ACPI_RESOURCE_IRQ Irq; + ACPI_RESOURCE_DMA Dma; + ACPI_RESOURCE_START_DEPENDENT StartDpf; + ACPI_RESOURCE_IO Io; + ACPI_RESOURCE_FIXED_IO FixedIo; + ACPI_RESOURCE_FIXED_DMA FixedDma; + ACPI_RESOURCE_VENDOR Vendor; + ACPI_RESOURCE_VENDOR_TYPED VendorTyped; + ACPI_RESOURCE_END_TAG EndTag; + ACPI_RESOURCE_MEMORY24 Memory24; + ACPI_RESOURCE_MEMORY32 Memory32; + ACPI_RESOURCE_FIXED_MEMORY32 FixedMemory32; + ACPI_RESOURCE_ADDRESS16 Address16; + ACPI_RESOURCE_ADDRESS32 Address32; + ACPI_RESOURCE_ADDRESS64 Address64; + ACPI_RESOURCE_EXTENDED_ADDRESS64 ExtAddress64; + ACPI_RESOURCE_EXTENDED_IRQ ExtendedIrq; + ACPI_RESOURCE_GENERIC_REGISTER GenericReg; + ACPI_RESOURCE_GPIO Gpio; + ACPI_RESOURCE_I2C_SERIALBUS I2cSerialBus; + ACPI_RESOURCE_SPI_SERIALBUS SpiSerialBus; + ACPI_RESOURCE_UART_SERIALBUS UartSerialBus; + ACPI_RESOURCE_COMMON_SERIALBUS CommonSerialBus; + + /* Common fields */ + + ACPI_RESOURCE_ADDRESS Address; /* Common 16/32/64 address fields */ + +} ACPI_RESOURCE_DATA; + + +/* Common resource header */ + +typedef struct acpi_resource +{ + UINT32 Type; + UINT32 Length; + ACPI_RESOURCE_DATA Data; + +} ACPI_RESOURCE; + +/* restore default alignment */ + +#pragma pack() + + +#define ACPI_RS_SIZE_NO_DATA 8 /* Id + Length fields */ +#define ACPI_RS_SIZE_MIN (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (12) +#define ACPI_RS_SIZE(Type) (UINT32) (ACPI_RS_SIZE_NO_DATA + sizeof (Type)) + +#define ACPI_NEXT_RESOURCE(Res) (ACPI_RESOURCE *)((UINT8 *) Res + Res->Length) + + +typedef struct acpi_pci_routing_table +{ + UINT32 Length; + UINT32 Pin; + UINT64 Address; /* here for 64-bit alignment */ + UINT32 SourceIndex; + char Source[4]; /* pad to 64 bits so sizeof() works in all cases */ + +} ACPI_PCI_ROUTING_TABLE; + +#endif /* __ACRESTYP_H__ */ + diff --git a/source/include/acstruct.h b/source/include/acstruct.h new file mode 100644 index 000000000000..b3927caa41fa --- /dev/null +++ b/source/include/acstruct.h @@ -0,0 +1,254 @@ +/****************************************************************************** + * + * Name: acstruct.h - Internal structs + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACSTRUCT_H__ +#define __ACSTRUCT_H__ + +/* acpisrc:StructDefs -- for acpisrc conversion */ + +/***************************************************************************** + * + * Tree walking typedefs and structs + * + ****************************************************************************/ + + +/* + * Walk state - current state of a parse tree walk. Used for both a leisurely + * stroll through the tree (for whatever reason), and for control method + * execution. + */ +#define ACPI_NEXT_OP_DOWNWARD 1 +#define ACPI_NEXT_OP_UPWARD 2 + +/* + * Groups of definitions for WalkType used for different implementations of + * walkers (never simultaneously) - flags for interpreter: + */ +#define ACPI_WALK_NON_METHOD 0 +#define ACPI_WALK_METHOD 0x01 +#define ACPI_WALK_METHOD_RESTART 0x02 + +/* Flags for iASL compiler only */ + +#define ACPI_WALK_CONST_REQUIRED 0x10 +#define ACPI_WALK_CONST_OPTIONAL 0x20 + + +typedef struct acpi_walk_state +{ + struct acpi_walk_state *Next; /* Next WalkState in list */ + UINT8 DescriptorType; /* To differentiate various internal objs */ + UINT8 WalkType; + UINT16 Opcode; /* Current AML opcode */ + UINT8 NextOpInfo; /* Info about NextOp */ + UINT8 NumOperands; /* Stack pointer for Operands[] array */ + UINT8 OperandIndex; /* Index into operand stack, to be used by AcpiDsObjStackPush */ + ACPI_OWNER_ID OwnerId; /* Owner of objects created during the walk */ + BOOLEAN LastPredicate; /* Result of last predicate */ + UINT8 CurrentResult; + UINT8 ReturnUsed; + UINT8 ScopeDepth; + UINT8 PassNumber; /* Parse pass during table load */ + UINT8 ResultSize; /* Total elements for the result stack */ + UINT8 ResultCount; /* Current number of occupied elements of result stack */ + UINT32 AmlOffset; + UINT32 ArgTypes; + UINT32 MethodBreakpoint; /* For single stepping */ + UINT32 UserBreakpoint; /* User AML breakpoint */ + UINT32 ParseFlags; + + ACPI_PARSE_STATE ParserState; /* Current state of parser */ + UINT32 PrevArgTypes; + UINT32 ArgCount; /* push for fixed or var args */ + + struct acpi_namespace_node Arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */ + struct acpi_namespace_node LocalVariables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ + union acpi_operand_object *Operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */ + union acpi_operand_object **Params; + + UINT8 *AmlLastWhile; + union acpi_operand_object **CallerReturnDesc; + ACPI_GENERIC_STATE *ControlState; /* List of control states (nested IFs) */ + struct acpi_namespace_node *DeferredNode; /* Used when executing deferred opcodes */ + union acpi_operand_object *ImplicitReturnObj; + struct acpi_namespace_node *MethodCallNode; /* Called method Node*/ + ACPI_PARSE_OBJECT *MethodCallOp; /* MethodCall Op if running a method */ + union acpi_operand_object *MethodDesc; /* Method descriptor if running a method */ + struct acpi_namespace_node *MethodNode; /* Method node if running a method. */ + ACPI_PARSE_OBJECT *Op; /* Current parser op */ + const ACPI_OPCODE_INFO *OpInfo; /* Info on current opcode */ + ACPI_PARSE_OBJECT *Origin; /* Start of walk [Obsolete] */ + union acpi_operand_object *ResultObj; + ACPI_GENERIC_STATE *Results; /* Stack of accumulated results */ + union acpi_operand_object *ReturnDesc; /* Return object, if any */ + ACPI_GENERIC_STATE *ScopeInfo; /* Stack of nested scopes */ + ACPI_PARSE_OBJECT *PrevOp; /* Last op that was processed */ + ACPI_PARSE_OBJECT *NextOp; /* next op to be processed */ + ACPI_THREAD_STATE *Thread; + ACPI_PARSE_DOWNWARDS DescendingCallback; + ACPI_PARSE_UPWARDS AscendingCallback; + +} ACPI_WALK_STATE; + + +/* Info used by AcpiNsInitializeObjects and AcpiDsInitializeObjects */ + +typedef struct acpi_init_walk_info +{ + UINT32 TableIndex; + UINT32 ObjectCount; + UINT32 MethodCount; + UINT32 DeviceCount; + UINT32 OpRegionCount; + UINT32 FieldCount; + UINT32 BufferCount; + UINT32 PackageCount; + UINT32 OpRegionInit; + UINT32 FieldInit; + UINT32 BufferInit; + UINT32 PackageInit; + ACPI_OWNER_ID OwnerId; + +} ACPI_INIT_WALK_INFO; + + +typedef struct acpi_get_devices_info +{ + ACPI_WALK_CALLBACK UserFunction; + void *Context; + char *Hid; + +} ACPI_GET_DEVICES_INFO; + + +typedef union acpi_aml_operands +{ + ACPI_OPERAND_OBJECT *Operands[7]; + + struct + { + ACPI_OBJECT_INTEGER *Type; + ACPI_OBJECT_INTEGER *Code; + ACPI_OBJECT_INTEGER *Argument; + + } Fatal; + + struct + { + ACPI_OPERAND_OBJECT *Source; + ACPI_OBJECT_INTEGER *Index; + ACPI_OPERAND_OBJECT *Target; + + } Index; + + struct + { + ACPI_OPERAND_OBJECT *Source; + ACPI_OBJECT_INTEGER *Index; + ACPI_OBJECT_INTEGER *Length; + ACPI_OPERAND_OBJECT *Target; + + } Mid; + +} ACPI_AML_OPERANDS; + + +/* + * Structure used to pass object evaluation parameters. + * Purpose is to reduce CPU stack use. + */ +typedef struct acpi_evaluate_info +{ + ACPI_NAMESPACE_NODE *PrefixNode; + char *Pathname; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT **Parameters; + ACPI_NAMESPACE_NODE *ResolvedNode; + ACPI_OPERAND_OBJECT *ReturnObject; + UINT8 ParamCount; + UINT8 PassNumber; + UINT8 ReturnObjectType; + UINT8 Flags; + +} ACPI_EVALUATE_INFO; + +/* Values for Flags above */ + +#define ACPI_IGNORE_RETURN_VALUE 1 + + +/* Info used by AcpiNsInitializeDevices */ + +typedef struct acpi_device_walk_info +{ + ACPI_TABLE_DESC *TableDesc; + ACPI_EVALUATE_INFO *EvaluateInfo; + UINT32 DeviceCount; + UINT32 Num_STA; + UINT32 Num_INI; + +} ACPI_DEVICE_WALK_INFO; + + +/* TBD: [Restructure] Merge with struct above */ + +typedef struct acpi_walk_info +{ + UINT32 DebugLevel; + UINT32 Count; + ACPI_OWNER_ID OwnerId; + UINT8 DisplayType; + +} ACPI_WALK_INFO; + +/* Display Types */ + +#define ACPI_DISPLAY_SUMMARY (UINT8) 0 +#define ACPI_DISPLAY_OBJECTS (UINT8) 1 +#define ACPI_DISPLAY_MASK (UINT8) 1 + +#define ACPI_DISPLAY_SHORT (UINT8) 2 + + +#endif diff --git a/source/include/actables.h b/source/include/actables.h new file mode 100644 index 000000000000..26a7947dc97b --- /dev/null +++ b/source/include/actables.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * Name: actables.h - ACPI table management + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTABLES_H__ +#define __ACTABLES_H__ + + +ACPI_STATUS +AcpiAllocateRootTable ( + UINT32 InitialTableCount); + +/* + * tbfadt - FADT parse/convert/validate + */ +void +AcpiTbParseFadt ( + UINT32 TableIndex); + +void +AcpiTbCreateLocalFadt ( + ACPI_TABLE_HEADER *Table, + UINT32 Length); + + +/* + * tbfind - find ACPI table + */ +ACPI_STATUS +AcpiTbFindTable ( + char *Signature, + char *OemId, + char *OemTableId, + UINT32 *TableIndex); + + +/* + * tbinstal - Table removal and deletion + */ +ACPI_STATUS +AcpiTbResizeRootTableList ( + void); + +ACPI_STATUS +AcpiTbVerifyTable ( + ACPI_TABLE_DESC *TableDesc); + +ACPI_TABLE_HEADER * +AcpiTbTableOverride ( + ACPI_TABLE_HEADER *TableHeader, + ACPI_TABLE_DESC *TableDesc); + +ACPI_STATUS +AcpiTbAddTable ( + ACPI_TABLE_DESC *TableDesc, + UINT32 *TableIndex); + +ACPI_STATUS +AcpiTbStoreTable ( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Table, + UINT32 Length, + UINT8 Flags, + UINT32 *TableIndex); + +void +AcpiTbDeleteTable ( + ACPI_TABLE_DESC *TableDesc); + +void +AcpiTbTerminate ( + void); + +ACPI_STATUS +AcpiTbDeleteNamespaceByOwner ( + UINT32 TableIndex); + +ACPI_STATUS +AcpiTbAllocateOwnerId ( + UINT32 TableIndex); + +ACPI_STATUS +AcpiTbReleaseOwnerId ( + UINT32 TableIndex); + +ACPI_STATUS +AcpiTbGetOwnerId ( + UINT32 TableIndex, + ACPI_OWNER_ID *OwnerId); + +BOOLEAN +AcpiTbIsTableLoaded ( + UINT32 TableIndex); + +void +AcpiTbSetTableLoadedFlag ( + UINT32 TableIndex, + BOOLEAN IsLoaded); + + +/* + * tbutils - table manager utilities + */ +ACPI_STATUS +AcpiTbInitializeFacs ( + void); + +BOOLEAN +AcpiTbTablesLoaded ( + void); + +void +AcpiTbPrintTableHeader( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Header); + +UINT8 +AcpiTbChecksum ( + UINT8 *Buffer, + UINT32 Length); + +ACPI_STATUS +AcpiTbVerifyChecksum ( + ACPI_TABLE_HEADER *Table, + UINT32 Length); + +void +AcpiTbCheckDsdtHeader ( + void); + +ACPI_TABLE_HEADER * +AcpiTbCopyDsdt ( + UINT32 TableIndex); + +void +AcpiTbInstallTable ( + ACPI_PHYSICAL_ADDRESS Address, + char *Signature, + UINT32 TableIndex); + +ACPI_STATUS +AcpiTbParseRootTable ( + ACPI_PHYSICAL_ADDRESS RsdpAddress); + +#endif /* __ACTABLES_H__ */ diff --git a/source/include/actbl.h b/source/include/actbl.h new file mode 100644 index 000000000000..7da7378d140c --- /dev/null +++ b/source/include/actbl.h @@ -0,0 +1,434 @@ +/****************************************************************************** + * + * Name: actbl.h - Basic ACPI Table Definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL_H__ +#define __ACTBL_H__ + + +/******************************************************************************* + * + * Fundamental ACPI tables + * + * This file contains definitions for the ACPI tables that are directly consumed + * by ACPICA. All other tables are consumed by the OS-dependent ACPI-related + * device drivers and other OS support code. + * + * The RSDP and FACS do not use the common ACPI table header. All other ACPI + * tables use the header. + * + ******************************************************************************/ + + +/* + * Values for description table header signatures for tables defined in this + * file. Useful because they make it more difficult to inadvertently type in + * the wrong signature. + */ +#define ACPI_SIG_DSDT "DSDT" /* Differentiated System Description Table */ +#define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */ +#define ACPI_SIG_FACS "FACS" /* Firmware ACPI Control Structure */ +#define ACPI_SIG_PSDT "PSDT" /* Persistent System Description Table */ +#define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Pointer */ +#define ACPI_SIG_RSDT "RSDT" /* Root System Description Table */ +#define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */ +#define ACPI_SIG_SSDT "SSDT" /* Secondary System Description Table */ +#define ACPI_RSDP_NAME "RSDP" /* Short name for RSDP, not signature */ + + +/* + * All tables and structures must be byte-packed to match the ACPI + * specification, since the tables are provided by the system BIOS + */ +#pragma pack(1) + +/* + * Note about bitfields: The UINT8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + + +/******************************************************************************* + * + * Master ACPI Table Header. This common header is used by all ACPI tables + * except the RSDP and FACS. + * + ******************************************************************************/ + +typedef struct acpi_table_header +{ + char Signature[ACPI_NAME_SIZE]; /* ASCII table signature */ + UINT32 Length; /* Length of table in bytes, including this header */ + UINT8 Revision; /* ACPI Specification minor version # */ + UINT8 Checksum; /* To make sum of entire table == 0 */ + char OemId[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ + char OemTableId[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ + UINT32 OemRevision; /* OEM revision number */ + char AslCompilerId[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */ + UINT32 AslCompilerRevision; /* ASL compiler version */ + +} ACPI_TABLE_HEADER; + + +/******************************************************************************* + * + * GAS - Generic Address Structure (ACPI 2.0+) + * + * Note: Since this structure is used in the ACPI tables, it is byte aligned. + * If misaliged access is not supported by the hardware, accesses to the + * 64-bit Address field must be performed with care. + * + ******************************************************************************/ + +typedef struct acpi_generic_address +{ + UINT8 SpaceId; /* Address space where struct or register exists */ + UINT8 BitWidth; /* Size in bits of given register */ + UINT8 BitOffset; /* Bit offset within the register */ + UINT8 AccessWidth; /* Minimum Access size (ACPI 3.0) */ + UINT64 Address; /* 64-bit address of struct or register */ + +} ACPI_GENERIC_ADDRESS; + + +/******************************************************************************* + * + * RSDP - Root System Description Pointer (Signature is "RSD PTR ") + * Version 2 + * + ******************************************************************************/ + +typedef struct acpi_table_rsdp +{ + char Signature[8]; /* ACPI signature, contains "RSD PTR " */ + UINT8 Checksum; /* ACPI 1.0 checksum */ + char OemId[ACPI_OEM_ID_SIZE]; /* OEM identification */ + UINT8 Revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ + UINT32 RsdtPhysicalAddress; /* 32-bit physical address of the RSDT */ + UINT32 Length; /* Table length in bytes, including header (ACPI 2.0+) */ + UINT64 XsdtPhysicalAddress; /* 64-bit physical address of the XSDT (ACPI 2.0+) */ + UINT8 ExtendedChecksum; /* Checksum of entire table (ACPI 2.0+) */ + UINT8 Reserved[3]; /* Reserved, must be zero */ + +} ACPI_TABLE_RSDP; + +/* Standalone struct for the ACPI 1.0 RSDP */ + +typedef struct acpi_rsdp_common +{ + char Signature[8]; + UINT8 Checksum; + char OemId[ACPI_OEM_ID_SIZE]; + UINT8 Revision; + UINT32 RsdtPhysicalAddress; + +} ACPI_RSDP_COMMON; + +/* Standalone struct for the extended part of the RSDP (ACPI 2.0+) */ + +typedef struct acpi_rsdp_extension +{ + UINT32 Length; + UINT64 XsdtPhysicalAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; + +} ACPI_RSDP_EXTENSION; + + +/******************************************************************************* + * + * RSDT/XSDT - Root System Description Tables + * Version 1 (both) + * + ******************************************************************************/ + +typedef struct acpi_table_rsdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 TableOffsetEntry[1]; /* Array of pointers to ACPI tables */ + +} ACPI_TABLE_RSDT; + +typedef struct acpi_table_xsdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 TableOffsetEntry[1]; /* Array of pointers to ACPI tables */ + +} ACPI_TABLE_XSDT; + + +/******************************************************************************* + * + * FACS - Firmware ACPI Control Structure (FACS) + * + ******************************************************************************/ + +typedef struct acpi_table_facs +{ + char Signature[4]; /* ASCII table signature */ + UINT32 Length; /* Length of structure, in bytes */ + UINT32 HardwareSignature; /* Hardware configuration signature */ + UINT32 FirmwareWakingVector; /* 32-bit physical address of the Firmware Waking Vector */ + UINT32 GlobalLock; /* Global Lock for shared hardware resources */ + UINT32 Flags; + UINT64 XFirmwareWakingVector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */ + UINT8 Version; /* Version of this table (ACPI 2.0+) */ + UINT8 Reserved[3]; /* Reserved, must be zero */ + UINT32 OspmFlags; /* Flags to be set by OSPM (ACPI 4.0) */ + UINT8 Reserved1[24]; /* Reserved, must be zero */ + +} ACPI_TABLE_FACS; + +/* Masks for GlobalLock flag field above */ + +#define ACPI_GLOCK_PENDING (1) /* 00: Pending global lock ownership */ +#define ACPI_GLOCK_OWNED (1<<1) /* 01: Global lock is owned */ + +/* Masks for Flags field above */ + +#define ACPI_FACS_S4_BIOS_PRESENT (1) /* 00: S4BIOS support is present */ +#define ACPI_FACS_64BIT_WAKE (1<<1) /* 01: 64-bit wake vector supported (ACPI 4.0) */ + +/* Masks for OspmFlags field above */ + +#define ACPI_FACS_64BIT_ENVIRONMENT (1) /* 00: 64-bit wake environment is required (ACPI 4.0) */ + + +/******************************************************************************* + * + * FADT - Fixed ACPI Description Table (Signature "FACP") + * Version 4 + * + ******************************************************************************/ + +/* Fields common to all versions of the FADT */ + +typedef struct acpi_table_fadt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Facs; /* 32-bit physical address of FACS */ + UINT32 Dsdt; /* 32-bit physical address of DSDT */ + UINT8 Model; /* System Interrupt Model (ACPI 1.0) - not used in ACPI 2.0+ */ + UINT8 PreferredProfile; /* Conveys preferred power management profile to OSPM. */ + UINT16 SciInterrupt; /* System vector of SCI interrupt */ + UINT32 SmiCommand; /* 32-bit Port address of SMI command port */ + UINT8 AcpiEnable; /* Value to write to smi_cmd to enable ACPI */ + UINT8 AcpiDisable; /* Value to write to smi_cmd to disable ACPI */ + UINT8 S4BiosRequest; /* Value to write to SMI CMD to enter S4BIOS state */ + UINT8 PstateControl; /* Processor performance state control*/ + UINT32 Pm1aEventBlock; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */ + UINT32 Pm1bEventBlock; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */ + UINT32 Pm1aControlBlock; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */ + UINT32 Pm1bControlBlock; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */ + UINT32 Pm2ControlBlock; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */ + UINT32 PmTimerBlock; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */ + UINT32 Gpe0Block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */ + UINT32 Gpe1Block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */ + UINT8 Pm1EventLength; /* Byte Length of ports at Pm1xEventBlock */ + UINT8 Pm1ControlLength; /* Byte Length of ports at Pm1xControlBlock */ + UINT8 Pm2ControlLength; /* Byte Length of ports at Pm2ControlBlock */ + UINT8 PmTimerLength; /* Byte Length of ports at PmTimerBlock */ + UINT8 Gpe0BlockLength; /* Byte Length of ports at Gpe0Block */ + UINT8 Gpe1BlockLength; /* Byte Length of ports at Gpe1Block */ + UINT8 Gpe1Base; /* Offset in GPE number space where GPE1 events start */ + UINT8 CstControl; /* Support for the _CST object and C States change notification */ + UINT16 C2Latency; /* Worst case HW latency to enter/exit C2 state */ + UINT16 C3Latency; /* Worst case HW latency to enter/exit C3 state */ + UINT16 FlushSize; /* Processor's memory cache line width, in bytes */ + UINT16 FlushStride; /* Number of flush strides that need to be read */ + UINT8 DutyOffset; /* Processor duty cycle index in processor's P_CNT reg */ + UINT8 DutyWidth; /* Processor duty cycle value bit width in P_CNT register */ + UINT8 DayAlarm; /* Index to day-of-month alarm in RTC CMOS RAM */ + UINT8 MonthAlarm; /* Index to month-of-year alarm in RTC CMOS RAM */ + UINT8 Century; /* Index to century in RTC CMOS RAM */ + UINT16 BootFlags; /* IA-PC Boot Architecture Flags (see below for individual flags) */ + UINT8 Reserved; /* Reserved, must be zero */ + UINT32 Flags; /* Miscellaneous flag bits (see below for individual flags) */ + ACPI_GENERIC_ADDRESS ResetRegister; /* 64-bit address of the Reset register */ + UINT8 ResetValue; /* Value to write to the ResetRegister port to reset the system */ + UINT8 Reserved4[3]; /* Reserved, must be zero */ + UINT64 XFacs; /* 64-bit physical address of FACS */ + UINT64 XDsdt; /* 64-bit physical address of DSDT */ + ACPI_GENERIC_ADDRESS XPm1aEventBlock; /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ + ACPI_GENERIC_ADDRESS XPm1bEventBlock; /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ + ACPI_GENERIC_ADDRESS XPm1aControlBlock; /* 64-bit Extended Power Mgt 1a Control Reg Blk address */ + ACPI_GENERIC_ADDRESS XPm1bControlBlock; /* 64-bit Extended Power Mgt 1b Control Reg Blk address */ + ACPI_GENERIC_ADDRESS XPm2ControlBlock; /* 64-bit Extended Power Mgt 2 Control Reg Blk address */ + ACPI_GENERIC_ADDRESS XPmTimerBlock; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ + ACPI_GENERIC_ADDRESS XGpe0Block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ + ACPI_GENERIC_ADDRESS XGpe1Block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ + ACPI_GENERIC_ADDRESS SleepControl; /* 64-bit Sleep Control register */ + ACPI_GENERIC_ADDRESS SleepStatus; /* 64-bit Sleep Status register */ + +} ACPI_TABLE_FADT; + + +/* Masks for FADT Boot Architecture Flags (BootFlags) */ + +#define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */ +#define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */ +#define ACPI_FADT_NO_VGA (1<<2) /* 02: [V4] It is not safe to probe for VGA hardware */ +#define ACPI_FADT_NO_MSI (1<<3) /* 03: [V4] Message Signaled Interrupts (MSI) must not be enabled */ +#define ACPI_FADT_NO_ASPM (1<<4) /* 04: [V4] PCIe ASPM control must not be enabled */ +#define ACPI_FADT_NO_CMOS_RTC (1<<5) /* 05: [V5] No CMOS real-time clock present */ + +/* Masks for FADT flags */ + +#define ACPI_FADT_WBINVD (1) /* 00: [V1] The wbinvd instruction works properly */ +#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] wbinvd flushes but does not invalidate caches */ +#define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: [V1] All processors support C1 state */ +#define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: [V1] C2 state works on MP system */ +#define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: [V1] Power button is handled as a control method device */ +#define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: [V1] Sleep button is handled as a control method device */ +#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status not in fixed register space */ +#define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: [V1] RTC alarm can wake system from S4 */ +#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: [V1] ACPI timer width is 32-bit (0=24-bit) */ +#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: [V1] Docking supported */ +#define ACPI_FADT_RESET_REGISTER (1<<10) /* 10: [V2] System reset via the FADT RESET_REG supported */ +#define ACPI_FADT_SEALED_CASE (1<<11) /* 11: [V3] No internal expansion capabilities and case is sealed */ +#define ACPI_FADT_HEADLESS (1<<12) /* 12: [V3] No local video capabilities or local input devices */ +#define ACPI_FADT_SLEEP_TYPE (1<<13) /* 13: [V3] Must execute native instruction after writing SLP_TYPx register */ +#define ACPI_FADT_PCI_EXPRESS_WAKE (1<<14) /* 14: [V4] System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ +#define ACPI_FADT_PLATFORM_CLOCK (1<<15) /* 15: [V4] OSPM should use platform-provided timer (ACPI 3.0) */ +#define ACPI_FADT_S4_RTC_VALID (1<<16) /* 16: [V4] Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ +#define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: [V4] System is compatible with remote power on (ACPI 3.0) */ +#define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: [V4] All local APICs must use cluster model (ACPI 3.0) */ +#define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: [V4] All local xAPICs must use physical dest mode (ACPI 3.0) */ +#define ACPI_FADT_HW_REDUCED (1<<20) /* 20: [V5] ACPI hardware is not implemented (ACPI 5.0) */ +#define ACPI_FADT_LOW_POWER_S0 (1<<21) /* 21: [V5] S0 power savings are equal or better than S3 (ACPI 5.0) */ + + +/* Values for PreferredProfile (Prefered Power Management Profiles) */ + +enum AcpiPreferedPmProfiles +{ + PM_UNSPECIFIED = 0, + PM_DESKTOP = 1, + PM_MOBILE = 2, + PM_WORKSTATION = 3, + PM_ENTERPRISE_SERVER = 4, + PM_SOHO_SERVER = 5, + PM_APPLIANCE_PC = 6, + PM_PERFORMANCE_SERVER = 7, + PM_TABLET = 8 +}; + +/* Values for SleepStatus and SleepControl registers (V5 FADT) */ + +#define ACPI_X_WAKE_STATUS 0x80 +#define ACPI_X_SLEEP_TYPE_MASK 0x1C +#define ACPI_X_SLEEP_TYPE_POSITION 0x02 +#define ACPI_X_SLEEP_ENABLE 0x20 + + +/* Reset to default packing */ + +#pragma pack() + + +/* + * Internal table-related structures + */ +typedef union acpi_name_union +{ + UINT32 Integer; + char Ascii[4]; + +} ACPI_NAME_UNION; + + +/* Internal ACPI Table Descriptor. One per ACPI table. */ + +typedef struct acpi_table_desc +{ + ACPI_PHYSICAL_ADDRESS Address; + ACPI_TABLE_HEADER *Pointer; + UINT32 Length; /* Length fixed at 32 bits */ + ACPI_NAME_UNION Signature; + ACPI_OWNER_ID OwnerId; + UINT8 Flags; + +} ACPI_TABLE_DESC; + +/* Masks for Flags field above */ + +#define ACPI_TABLE_ORIGIN_UNKNOWN (0) +#define ACPI_TABLE_ORIGIN_MAPPED (1) +#define ACPI_TABLE_ORIGIN_ALLOCATED (2) +#define ACPI_TABLE_ORIGIN_OVERRIDE (4) +#define ACPI_TABLE_ORIGIN_MASK (7) +#define ACPI_TABLE_IS_LOADED (8) + + +/* + * Get the remaining ACPI tables + */ +#include "actbl1.h" +#include "actbl2.h" +#include "actbl3.h" + +/* Macros used to generate offsets to specific table fields */ + +#define ACPI_FADT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_FADT, f) + +/* + * Sizes of the various flavors of FADT. We need to look closely + * at the FADT length because the version number essentially tells + * us nothing because of many BIOS bugs where the version does not + * match the expected length. In other words, the length of the + * FADT is the bottom line as to what the version really is. + * + * For reference, the values below are as follows: + * FADT V1 size: 0x074 + * FADT V2 size: 0x084 + * FADT V3 size: 0x0F4 + * FADT V4 size: 0x0F4 + * FADT V5 size: 0x10C + */ +#define ACPI_FADT_V1_SIZE (UINT32) (ACPI_FADT_OFFSET (Flags) + 4) +#define ACPI_FADT_V2_SIZE (UINT32) (ACPI_FADT_OFFSET (Reserved4[0]) + 3) +#define ACPI_FADT_V3_SIZE (UINT32) (ACPI_FADT_OFFSET (SleepControl)) +#define ACPI_FADT_V5_SIZE (UINT32) (sizeof (ACPI_TABLE_FADT)) + +#endif /* __ACTBL_H__ */ diff --git a/source/include/actbl1.h b/source/include/actbl1.h new file mode 100644 index 000000000000..824135d3dd2d --- /dev/null +++ b/source/include/actbl1.h @@ -0,0 +1,1132 @@ +/****************************************************************************** + * + * Name: actbl1.h - Additional ACPI table definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL1_H__ +#define __ACTBL1_H__ + + +/******************************************************************************* + * + * Additional ACPI Tables (1) + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + * The tables in this file are fully defined within the ACPI specification. + * + ******************************************************************************/ + + +/* + * Values for description table header signatures for tables defined in this + * file. Useful because they make it more difficult to inadvertently type in + * the wrong signature. + */ +#define ACPI_SIG_BERT "BERT" /* Boot Error Record Table */ +#define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ +#define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */ +#define ACPI_SIG_EINJ "EINJ" /* Error Injection table */ +#define ACPI_SIG_ERST "ERST" /* Error Record Serialization Table */ +#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */ +#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ +#define ACPI_SIG_MSCT "MSCT" /* Maximum System Characteristics Table */ +#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ +#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ +#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */ + + +/* + * All tables must be byte-packed to match the ACPI specification, since + * the tables are provided by the system BIOS. + */ +#pragma pack(1) + +/* + * Note about bitfields: The UINT8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + + +/******************************************************************************* + * + * Common subtable headers + * + ******************************************************************************/ + +/* Generic subtable header (used in MADT, SRAT, etc.) */ + +typedef struct acpi_subtable_header +{ + UINT8 Type; + UINT8 Length; + +} ACPI_SUBTABLE_HEADER; + + +/* Subtable header for WHEA tables (EINJ, ERST, WDAT) */ + +typedef struct acpi_whea_header +{ + UINT8 Action; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved; + ACPI_GENERIC_ADDRESS RegisterRegion; + UINT64 Value; /* Value used with Read/Write register */ + UINT64 Mask; /* Bitmask required for this register instruction */ + +} ACPI_WHEA_HEADER; + + +/******************************************************************************* + * + * BERT - Boot Error Record Table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_bert +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 RegionLength; /* Length of the boot error region */ + UINT64 Address; /* Physical addresss of the error region */ + +} ACPI_TABLE_BERT; + + +/* Boot Error Region (not a subtable, pointed to by Address field above) */ + +typedef struct acpi_bert_region +{ + UINT32 BlockStatus; /* Type of error information */ + UINT32 RawDataOffset; /* Offset to raw error data */ + UINT32 RawDataLength; /* Length of raw error data */ + UINT32 DataLength; /* Length of generic error data */ + UINT32 ErrorSeverity; /* Severity code */ + +} ACPI_BERT_REGION; + +/* Values for BlockStatus flags above */ + +#define ACPI_BERT_UNCORRECTABLE (1) +#define ACPI_BERT_CORRECTABLE (1<<1) +#define ACPI_BERT_MULTIPLE_UNCORRECTABLE (1<<2) +#define ACPI_BERT_MULTIPLE_CORRECTABLE (1<<3) +#define ACPI_BERT_ERROR_ENTRY_COUNT (0xFF<<4) /* 8 bits, error count */ + +/* Values for ErrorSeverity above */ + +enum AcpiBertErrorSeverity +{ + ACPI_BERT_ERROR_CORRECTABLE = 0, + ACPI_BERT_ERROR_FATAL = 1, + ACPI_BERT_ERROR_CORRECTED = 2, + ACPI_BERT_ERROR_NONE = 3, + ACPI_BERT_ERROR_RESERVED = 4 /* 4 and greater are reserved */ +}; + +/* + * Note: The generic error data that follows the ErrorSeverity field above + * uses the ACPI_HEST_GENERIC_DATA defined under the HEST table below + */ + + +/******************************************************************************* + * + * CPEP - Corrected Platform Error Polling table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_cpep +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 Reserved; + +} ACPI_TABLE_CPEP; + + +/* Subtable */ + +typedef struct acpi_cpep_polling +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Id; /* Processor ID */ + UINT8 Eid; /* Processor EID */ + UINT32 Interval; /* Polling interval (msec) */ + +} ACPI_CPEP_POLLING; + + +/******************************************************************************* + * + * ECDT - Embedded Controller Boot Resources Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_ecdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + ACPI_GENERIC_ADDRESS Control; /* Address of EC command/status register */ + ACPI_GENERIC_ADDRESS Data; /* Address of EC data register */ + UINT32 Uid; /* Unique ID - must be same as the EC _UID method */ + UINT8 Gpe; /* The GPE for the EC */ + UINT8 Id[1]; /* Full namepath of the EC in the ACPI namespace */ + +} ACPI_TABLE_ECDT; + + +/******************************************************************************* + * + * EINJ - Error Injection Table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_einj +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 HeaderLength; + UINT8 Flags; + UINT8 Reserved[3]; + UINT32 Entries; + +} ACPI_TABLE_EINJ; + + +/* EINJ Injection Instruction Entries (actions) */ + +typedef struct acpi_einj_entry +{ + ACPI_WHEA_HEADER WheaHeader; /* Common header for WHEA tables */ + +} ACPI_EINJ_ENTRY; + +/* Masks for Flags field above */ + +#define ACPI_EINJ_PRESERVE (1) + +/* Values for Action field above */ + +enum AcpiEinjActions +{ + ACPI_EINJ_BEGIN_OPERATION = 0, + ACPI_EINJ_GET_TRIGGER_TABLE = 1, + ACPI_EINJ_SET_ERROR_TYPE = 2, + ACPI_EINJ_GET_ERROR_TYPE = 3, + ACPI_EINJ_END_OPERATION = 4, + ACPI_EINJ_EXECUTE_OPERATION = 5, + ACPI_EINJ_CHECK_BUSY_STATUS = 6, + ACPI_EINJ_GET_COMMAND_STATUS = 7, + ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS = 8, + ACPI_EINJ_ACTION_RESERVED = 9, /* 9 and greater are reserved */ + ACPI_EINJ_TRIGGER_ERROR = 0xFF /* Except for this value */ +}; + +/* Values for Instruction field above */ + +enum AcpiEinjInstructions +{ + ACPI_EINJ_READ_REGISTER = 0, + ACPI_EINJ_READ_REGISTER_VALUE = 1, + ACPI_EINJ_WRITE_REGISTER = 2, + ACPI_EINJ_WRITE_REGISTER_VALUE = 3, + ACPI_EINJ_NOOP = 4, + ACPI_EINJ_FLUSH_CACHELINE = 5, + ACPI_EINJ_INSTRUCTION_RESERVED = 6 /* 6 and greater are reserved */ +}; + +typedef struct acpi_einj_error_type_with_addr +{ + UINT32 ErrorType; + UINT32 VendorStructOffset; + UINT32 Flags; + UINT32 ApicId; + UINT64 Address; + UINT64 Range; + UINT32 PcieId; + +} ACPI_EINJ_ERROR_TYPE_WITH_ADDR; + +typedef struct acpi_einj_vendor +{ + UINT32 Length; + UINT32 PcieId; + UINT16 VendorId; + UINT16 DeviceId; + UINT8 RevisionId; + UINT8 Reserved[3]; + +} ACPI_EINJ_VENDOR; + + +/* EINJ Trigger Error Action Table */ + +typedef struct acpi_einj_trigger +{ + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; + +} ACPI_EINJ_TRIGGER; + +/* Command status return values */ + +enum AcpiEinjCommandStatus +{ + ACPI_EINJ_SUCCESS = 0, + ACPI_EINJ_FAILURE = 1, + ACPI_EINJ_INVALID_ACCESS = 2, + ACPI_EINJ_STATUS_RESERVED = 3 /* 3 and greater are reserved */ +}; + + +/* Error types returned from ACPI_EINJ_GET_ERROR_TYPE (bitfield) */ + +#define ACPI_EINJ_PROCESSOR_CORRECTABLE (1) +#define ACPI_EINJ_PROCESSOR_UNCORRECTABLE (1<<1) +#define ACPI_EINJ_PROCESSOR_FATAL (1<<2) +#define ACPI_EINJ_MEMORY_CORRECTABLE (1<<3) +#define ACPI_EINJ_MEMORY_UNCORRECTABLE (1<<4) +#define ACPI_EINJ_MEMORY_FATAL (1<<5) +#define ACPI_EINJ_PCIX_CORRECTABLE (1<<6) +#define ACPI_EINJ_PCIX_UNCORRECTABLE (1<<7) +#define ACPI_EINJ_PCIX_FATAL (1<<8) +#define ACPI_EINJ_PLATFORM_CORRECTABLE (1<<9) +#define ACPI_EINJ_PLATFORM_UNCORRECTABLE (1<<10) +#define ACPI_EINJ_PLATFORM_FATAL (1<<11) +#define ACPI_EINJ_VENDOR_DEFINED (1<<31) + + +/******************************************************************************* + * + * ERST - Error Record Serialization Table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_erst +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 HeaderLength; + UINT32 Reserved; + UINT32 Entries; + +} ACPI_TABLE_ERST; + + +/* ERST Serialization Entries (actions) */ + +typedef struct acpi_erst_entry +{ + ACPI_WHEA_HEADER WheaHeader; /* Common header for WHEA tables */ + +} ACPI_ERST_ENTRY; + +/* Masks for Flags field above */ + +#define ACPI_ERST_PRESERVE (1) + +/* Values for Action field above */ + +enum AcpiErstActions +{ + ACPI_ERST_BEGIN_WRITE = 0, + ACPI_ERST_BEGIN_READ = 1, + ACPI_ERST_BEGIN_CLEAR = 2, + ACPI_ERST_END = 3, + ACPI_ERST_SET_RECORD_OFFSET = 4, + ACPI_ERST_EXECUTE_OPERATION = 5, + ACPI_ERST_CHECK_BUSY_STATUS = 6, + ACPI_ERST_GET_COMMAND_STATUS = 7, + ACPI_ERST_GET_RECORD_ID = 8, + ACPI_ERST_SET_RECORD_ID = 9, + ACPI_ERST_GET_RECORD_COUNT = 10, + ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, + ACPI_ERST_NOT_USED = 12, + ACPI_ERST_GET_ERROR_RANGE = 13, + ACPI_ERST_GET_ERROR_LENGTH = 14, + ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, + ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum AcpiErstInstructions +{ + ACPI_ERST_READ_REGISTER = 0, + ACPI_ERST_READ_REGISTER_VALUE = 1, + ACPI_ERST_WRITE_REGISTER = 2, + ACPI_ERST_WRITE_REGISTER_VALUE = 3, + ACPI_ERST_NOOP = 4, + ACPI_ERST_LOAD_VAR1 = 5, + ACPI_ERST_LOAD_VAR2 = 6, + ACPI_ERST_STORE_VAR1 = 7, + ACPI_ERST_ADD = 8, + ACPI_ERST_SUBTRACT = 9, + ACPI_ERST_ADD_VALUE = 10, + ACPI_ERST_SUBTRACT_VALUE = 11, + ACPI_ERST_STALL = 12, + ACPI_ERST_STALL_WHILE_TRUE = 13, + ACPI_ERST_SKIP_NEXT_IF_TRUE = 14, + ACPI_ERST_GOTO = 15, + ACPI_ERST_SET_SRC_ADDRESS_BASE = 16, + ACPI_ERST_SET_DST_ADDRESS_BASE = 17, + ACPI_ERST_MOVE_DATA = 18, + ACPI_ERST_INSTRUCTION_RESERVED = 19 /* 19 and greater are reserved */ +}; + +/* Command status return values */ + +enum AcpiErstCommandStatus +{ + ACPI_ERST_SUCESS = 0, + ACPI_ERST_NO_SPACE = 1, + ACPI_ERST_NOT_AVAILABLE = 2, + ACPI_ERST_FAILURE = 3, + ACPI_ERST_RECORD_EMPTY = 4, + ACPI_ERST_NOT_FOUND = 5, + ACPI_ERST_STATUS_RESERVED = 6 /* 6 and greater are reserved */ +}; + + +/* Error Record Serialization Information */ + +typedef struct acpi_erst_info +{ + UINT16 Signature; /* Should be "ER" */ + UINT8 Data[48]; + +} ACPI_ERST_INFO; + + +/******************************************************************************* + * + * HEST - Hardware Error Source Table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_hest +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 ErrorSourceCount; + +} ACPI_TABLE_HEST; + + +/* HEST subtable header */ + +typedef struct acpi_hest_header +{ + UINT16 Type; + UINT16 SourceId; + +} ACPI_HEST_HEADER; + + +/* Values for Type field above for subtables */ + +enum AcpiHestTypes +{ + ACPI_HEST_TYPE_IA32_CHECK = 0, + ACPI_HEST_TYPE_IA32_CORRECTED_CHECK = 1, + ACPI_HEST_TYPE_IA32_NMI = 2, + ACPI_HEST_TYPE_NOT_USED3 = 3, + ACPI_HEST_TYPE_NOT_USED4 = 4, + ACPI_HEST_TYPE_NOT_USED5 = 5, + ACPI_HEST_TYPE_AER_ROOT_PORT = 6, + ACPI_HEST_TYPE_AER_ENDPOINT = 7, + ACPI_HEST_TYPE_AER_BRIDGE = 8, + ACPI_HEST_TYPE_GENERIC_ERROR = 9, + ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ +}; + + +/* + * HEST substructures contained in subtables + */ + +/* + * IA32 Error Bank(s) - Follows the ACPI_HEST_IA_MACHINE_CHECK and + * ACPI_HEST_IA_CORRECTED structures. + */ +typedef struct acpi_hest_ia_error_bank +{ + UINT8 BankNumber; + UINT8 ClearStatusOnInit; + UINT8 StatusFormat; + UINT8 Reserved; + UINT32 ControlRegister; + UINT64 ControlData; + UINT32 StatusRegister; + UINT32 AddressRegister; + UINT32 MiscRegister; + +} ACPI_HEST_IA_ERROR_BANK; + + +/* Common HEST sub-structure for PCI/AER structures below (6,7,8) */ + +typedef struct acpi_hest_aer_common +{ + UINT16 Reserved1; + UINT8 Flags; + UINT8 Enabled; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT16 Reserved2; + UINT32 UncorrectableMask; + UINT32 UncorrectableSeverity; + UINT32 CorrectableMask; + UINT32 AdvancedCapabilities; + +} ACPI_HEST_AER_COMMON; + +/* Masks for HEST Flags fields */ + +#define ACPI_HEST_FIRMWARE_FIRST (1) +#define ACPI_HEST_GLOBAL (1<<1) + + +/* Hardware Error Notification */ + +typedef struct acpi_hest_notify +{ + UINT8 Type; + UINT8 Length; + UINT16 ConfigWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 PollingThresholdValue; + UINT32 PollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; + +} ACPI_HEST_NOTIFY; + +/* Values for Notify Type field above */ + +enum AcpiHestNotifyTypes +{ + ACPI_HEST_NOTIFY_POLLED = 0, + ACPI_HEST_NOTIFY_EXTERNAL = 1, + ACPI_HEST_NOTIFY_LOCAL = 2, + ACPI_HEST_NOTIFY_SCI = 3, + ACPI_HEST_NOTIFY_NMI = 4, + ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */ +}; + +/* Values for ConfigWriteEnable bitfield above */ + +#define ACPI_HEST_TYPE (1) +#define ACPI_HEST_POLL_INTERVAL (1<<1) +#define ACPI_HEST_POLL_THRESHOLD_VALUE (1<<2) +#define ACPI_HEST_POLL_THRESHOLD_WINDOW (1<<3) +#define ACPI_HEST_ERR_THRESHOLD_VALUE (1<<4) +#define ACPI_HEST_ERR_THRESHOLD_WINDOW (1<<5) + + +/* + * HEST subtables + */ + +/* 0: IA32 Machine Check Exception */ + +typedef struct acpi_hest_ia_machine_check +{ + ACPI_HEST_HEADER Header; + UINT16 Reserved1; + UINT8 Flags; + UINT8 Enabled; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityData; + UINT64 GlobalControlData; + UINT8 NumHardwareBanks; + UINT8 Reserved3[7]; + +} ACPI_HEST_IA_MACHINE_CHECK; + + +/* 1: IA32 Corrected Machine Check */ + +typedef struct acpi_hest_ia_corrected +{ + ACPI_HEST_HEADER Header; + UINT16 Reserved1; + UINT8 Flags; + UINT8 Enabled; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + ACPI_HEST_NOTIFY Notify; + UINT8 NumHardwareBanks; + UINT8 Reserved2[3]; + +} ACPI_HEST_IA_CORRECTED; + + +/* 2: IA32 Non-Maskable Interrupt */ + +typedef struct acpi_hest_ia_nmi +{ + ACPI_HEST_HEADER Header; + UINT32 Reserved; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + +} ACPI_HEST_IA_NMI; + + +/* 3,4,5: Not used */ + +/* 6: PCI Express Root Port AER */ + +typedef struct acpi_hest_aer_root +{ + ACPI_HEST_HEADER Header; + ACPI_HEST_AER_COMMON Aer; + UINT32 RootErrorCommand; + +} ACPI_HEST_AER_ROOT; + + +/* 7: PCI Express AER (AER Endpoint) */ + +typedef struct acpi_hest_aer +{ + ACPI_HEST_HEADER Header; + ACPI_HEST_AER_COMMON Aer; + +} ACPI_HEST_AER; + + +/* 8: PCI Express/PCI-X Bridge AER */ + +typedef struct acpi_hest_aer_bridge +{ + ACPI_HEST_HEADER Header; + ACPI_HEST_AER_COMMON Aer; + UINT32 UncorrectableMask2; + UINT32 UncorrectableSeverity2; + UINT32 AdvancedCapabilities2; + +} ACPI_HEST_AER_BRIDGE; + + +/* 9: Generic Hardware Error Source */ + +typedef struct acpi_hest_generic +{ + ACPI_HEST_HEADER Header; + UINT16 RelatedSourceId; + UINT8 Reserved; + UINT8 Enabled; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + ACPI_GENERIC_ADDRESS ErrorStatusAddress; + ACPI_HEST_NOTIFY Notify; + UINT32 ErrorBlockLength; + +} ACPI_HEST_GENERIC; + + +/* Generic Error Status block */ + +typedef struct acpi_hest_generic_status +{ + UINT32 BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; + +} ACPI_HEST_GENERIC_STATUS; + +/* Values for BlockStatus flags above */ + +#define ACPI_HEST_UNCORRECTABLE (1) +#define ACPI_HEST_CORRECTABLE (1<<1) +#define ACPI_HEST_MULTIPLE_UNCORRECTABLE (1<<2) +#define ACPI_HEST_MULTIPLE_CORRECTABLE (1<<3) +#define ACPI_HEST_ERROR_ENTRY_COUNT (0xFF<<4) /* 8 bits, error count */ + + +/* Generic Error Data entry */ + +typedef struct acpi_hest_generic_data +{ + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; + +} ACPI_HEST_GENERIC_DATA; + + +/******************************************************************************* + * + * MADT - Multiple APIC Description Table + * Version 3 + * + ******************************************************************************/ + +typedef struct acpi_table_madt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Address; /* Physical address of local APIC */ + UINT32 Flags; + +} ACPI_TABLE_MADT; + +/* Masks for Flags field above */ + +#define ACPI_MADT_PCAT_COMPAT (1) /* 00: System also has dual 8259s */ + +/* Values for PCATCompat flag */ + +#define ACPI_MADT_DUAL_PIC 0 +#define ACPI_MADT_MULTIPLE_APIC 1 + + +/* Values for MADT subtable type in ACPI_SUBTABLE_HEADER */ + +enum AcpiMadtType +{ + ACPI_MADT_TYPE_LOCAL_APIC = 0, + ACPI_MADT_TYPE_IO_APIC = 1, + ACPI_MADT_TYPE_INTERRUPT_OVERRIDE = 2, + ACPI_MADT_TYPE_NMI_SOURCE = 3, + ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4, + ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE = 5, + ACPI_MADT_TYPE_IO_SAPIC = 6, + ACPI_MADT_TYPE_LOCAL_SAPIC = 7, + ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8, + ACPI_MADT_TYPE_LOCAL_X2APIC = 9, + ACPI_MADT_TYPE_LOCAL_X2APIC_NMI = 10, + ACPI_MADT_TYPE_GENERIC_INTERRUPT = 11, + ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR = 12, + ACPI_MADT_TYPE_RESERVED = 13 /* 13 and greater are reserved */ +}; + + +/* + * MADT Sub-tables, correspond to Type in ACPI_SUBTABLE_HEADER + */ + +/* 0: Processor Local APIC */ + +typedef struct acpi_madt_local_apic +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 ProcessorId; /* ACPI processor id */ + UINT8 Id; /* Processor's local APIC id */ + UINT32 LapicFlags; + +} ACPI_MADT_LOCAL_APIC; + + +/* 1: IO APIC */ + +typedef struct acpi_madt_io_apic +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Id; /* I/O APIC ID */ + UINT8 Reserved; /* Reserved - must be zero */ + UINT32 Address; /* APIC physical address */ + UINT32 GlobalIrqBase; /* Global system interrupt where INTI lines start */ + +} ACPI_MADT_IO_APIC; + + +/* 2: Interrupt Override */ + +typedef struct acpi_madt_interrupt_override +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Bus; /* 0 - ISA */ + UINT8 SourceIrq; /* Interrupt source (IRQ) */ + UINT32 GlobalIrq; /* Global system interrupt */ + UINT16 IntiFlags; + +} ACPI_MADT_INTERRUPT_OVERRIDE; + + +/* 3: NMI Source */ + +typedef struct acpi_madt_nmi_source +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 IntiFlags; + UINT32 GlobalIrq; /* Global system interrupt */ + +} ACPI_MADT_NMI_SOURCE; + + +/* 4: Local APIC NMI */ + +typedef struct acpi_madt_local_apic_nmi +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 ProcessorId; /* ACPI processor id */ + UINT16 IntiFlags; + UINT8 Lint; /* LINTn to which NMI is connected */ + +} ACPI_MADT_LOCAL_APIC_NMI; + + +/* 5: Address Override */ + +typedef struct acpi_madt_local_apic_override +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved, must be zero */ + UINT64 Address; /* APIC physical address */ + +} ACPI_MADT_LOCAL_APIC_OVERRIDE; + + +/* 6: I/O Sapic */ + +typedef struct acpi_madt_io_sapic +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Id; /* I/O SAPIC ID */ + UINT8 Reserved; /* Reserved, must be zero */ + UINT32 GlobalIrqBase; /* Global interrupt for SAPIC start */ + UINT64 Address; /* SAPIC physical address */ + +} ACPI_MADT_IO_SAPIC; + + +/* 7: Local Sapic */ + +typedef struct acpi_madt_local_sapic +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 ProcessorId; /* ACPI processor id */ + UINT8 Id; /* SAPIC ID */ + UINT8 Eid; /* SAPIC EID */ + UINT8 Reserved[3]; /* Reserved, must be zero */ + UINT32 LapicFlags; + UINT32 Uid; /* Numeric UID - ACPI 3.0 */ + char UidString[1]; /* String UID - ACPI 3.0 */ + +} ACPI_MADT_LOCAL_SAPIC; + + +/* 8: Platform Interrupt Source */ + +typedef struct acpi_madt_interrupt_source +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 IntiFlags; + UINT8 Type; /* 1=PMI, 2=INIT, 3=corrected */ + UINT8 Id; /* Processor ID */ + UINT8 Eid; /* Processor EID */ + UINT8 IoSapicVector; /* Vector value for PMI interrupts */ + UINT32 GlobalIrq; /* Global system interrupt */ + UINT32 Flags; /* Interrupt Source Flags */ + +} ACPI_MADT_INTERRUPT_SOURCE; + +/* Masks for Flags field above */ + +#define ACPI_MADT_CPEI_OVERRIDE (1) + + +/* 9: Processor Local X2APIC (ACPI 4.0) */ + +typedef struct acpi_madt_local_x2apic +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 LocalApicId; /* Processor x2APIC ID */ + UINT32 LapicFlags; + UINT32 Uid; /* ACPI processor UID */ + +} ACPI_MADT_LOCAL_X2APIC; + + +/* 10: Local X2APIC NMI (ACPI 4.0) */ + +typedef struct acpi_madt_local_x2apic_nmi +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 IntiFlags; + UINT32 Uid; /* ACPI processor UID */ + UINT8 Lint; /* LINTn to which NMI is connected */ + UINT8 Reserved[3]; /* Reserved - must be zero */ + +} ACPI_MADT_LOCAL_X2APIC_NMI; + + +/* 11: Generic Interrupt (ACPI 5.0) */ + +typedef struct acpi_madt_generic_interrupt +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 GicId; + UINT32 Uid; + UINT32 Flags; + UINT32 ParkingVersion; + UINT32 PerformanceInterrupt; + UINT64 ParkedAddress; + UINT64 BaseAddress; + +} ACPI_MADT_GENERIC_INTERRUPT; + + +/* 12: Generic Distributor (ACPI 5.0) */ + +typedef struct acpi_madt_generic_distributor +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 GicId; + UINT64 BaseAddress; + UINT32 GlobalIrqBase; + UINT32 Reserved2; /* Reserved - must be zero */ + +} ACPI_MADT_GENERIC_DISTRIBUTOR; + + +/* + * Common flags fields for MADT subtables + */ + +/* MADT Local APIC flags (LapicFlags) and GIC flags */ + +#define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */ + +/* MADT MPS INTI flags (IntiFlags) */ + +#define ACPI_MADT_POLARITY_MASK (3) /* 00-01: Polarity of APIC I/O input signals */ +#define ACPI_MADT_TRIGGER_MASK (3<<2) /* 02-03: Trigger mode of APIC input signals */ + +/* Values for MPS INTI flags */ + +#define ACPI_MADT_POLARITY_CONFORMS 0 +#define ACPI_MADT_POLARITY_ACTIVE_HIGH 1 +#define ACPI_MADT_POLARITY_RESERVED 2 +#define ACPI_MADT_POLARITY_ACTIVE_LOW 3 + +#define ACPI_MADT_TRIGGER_CONFORMS (0) +#define ACPI_MADT_TRIGGER_EDGE (1<<2) +#define ACPI_MADT_TRIGGER_RESERVED (2<<2) +#define ACPI_MADT_TRIGGER_LEVEL (3<<2) + + +/******************************************************************************* + * + * MSCT - Maximum System Characteristics Table (ACPI 4.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_msct +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 ProximityOffset; /* Location of proximity info struct(s) */ + UINT32 MaxProximityDomains;/* Max number of proximity domains */ + UINT32 MaxClockDomains; /* Max number of clock domains */ + UINT64 MaxAddress; /* Max physical address in system */ + +} ACPI_TABLE_MSCT; + + +/* Subtable - Maximum Proximity Domain Information. Version 1 */ + +typedef struct acpi_msct_proximity +{ + UINT8 Revision; + UINT8 Length; + UINT32 RangeStart; /* Start of domain range */ + UINT32 RangeEnd; /* End of domain range */ + UINT32 ProcessorCapacity; + UINT64 MemoryCapacity; /* In bytes */ + +} ACPI_MSCT_PROXIMITY; + + +/******************************************************************************* + * + * SBST - Smart Battery Specification Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_sbst +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 WarningLevel; + UINT32 LowLevel; + UINT32 CriticalLevel; + +} ACPI_TABLE_SBST; + + +/******************************************************************************* + * + * SLIT - System Locality Distance Information Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_slit +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 LocalityCount; + UINT8 Entry[1]; /* Real size = localities^2 */ + +} ACPI_TABLE_SLIT; + + +/******************************************************************************* + * + * SRAT - System Resource Affinity Table + * Version 3 + * + ******************************************************************************/ + +typedef struct acpi_table_srat +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 TableRevision; /* Must be value '1' */ + UINT64 Reserved; /* Reserved, must be zero */ + +} ACPI_TABLE_SRAT; + +/* Values for subtable type in ACPI_SUBTABLE_HEADER */ + +enum AcpiSratType +{ + ACPI_SRAT_TYPE_CPU_AFFINITY = 0, + ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1, + ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2, + ACPI_SRAT_TYPE_RESERVED = 3 /* 3 and greater are reserved */ +}; + +/* + * SRAT Sub-tables, correspond to Type in ACPI_SUBTABLE_HEADER + */ + +/* 0: Processor Local APIC/SAPIC Affinity */ + +typedef struct acpi_srat_cpu_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 ProximityDomainLo; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomainHi[3]; + UINT32 Reserved; /* Reserved, must be zero */ + +} ACPI_SRAT_CPU_AFFINITY; + +/* Flags */ + +#define ACPI_SRAT_CPU_USE_AFFINITY (1) /* 00: Use affinity structure */ + + +/* 1: Memory Affinity */ + +typedef struct acpi_srat_mem_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 ProximityDomain; + UINT16 Reserved; /* Reserved, must be zero */ + UINT64 BaseAddress; + UINT64 Length; + UINT32 Reserved1; + UINT32 Flags; + UINT64 Reserved2; /* Reserved, must be zero */ + +} ACPI_SRAT_MEM_AFFINITY; + +/* Flags */ + +#define ACPI_SRAT_MEM_ENABLED (1) /* 00: Use affinity structure */ +#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1) /* 01: Memory region is hot pluggable */ +#define ACPI_SRAT_MEM_NON_VOLATILE (1<<2) /* 02: Memory region is non-volatile */ + + +/* 2: Processor Local X2_APIC Affinity (ACPI 4.0) */ + +typedef struct acpi_srat_x2apic_cpu_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved, must be zero */ + UINT32 ProximityDomain; + UINT32 ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT32 Reserved2; + +} ACPI_SRAT_X2APIC_CPU_AFFINITY; + +/* Flags for ACPI_SRAT_CPU_AFFINITY and ACPI_SRAT_X2APIC_CPU_AFFINITY */ + +#define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */ + + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL1_H__ */ diff --git a/source/include/actbl2.h b/source/include/actbl2.h new file mode 100644 index 000000000000..70c6a09a3c3f --- /dev/null +++ b/source/include/actbl2.h @@ -0,0 +1,1207 @@ +/****************************************************************************** + * + * Name: actbl2.h - ACPI Table Definitions (tables not in ACPI spec) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL2_H__ +#define __ACTBL2_H__ + + +/******************************************************************************* + * + * Additional ACPI Tables (2) + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + * The tables in this file are defined by third-party specifications, and are + * not defined directly by the ACPI specification itself. + * + ******************************************************************************/ + + +/* + * Values for description table header signatures for tables defined in this + * file. Useful because they make it more difficult to inadvertently type in + * the wrong signature. + */ +#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ +#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ +#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ +#define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ +#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ +#define ACPI_SIG_IBFT "IBFT" /* iSCSI Boot Firmware Table */ +#define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ +#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ +#define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */ +#define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */ +#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ +#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ +#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ +#define ACPI_SIG_WAET "WAET" /* Windows ACPI Emulated devices Table */ +#define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */ +#define ACPI_SIG_WDDT "WDDT" /* Watchdog Timer Description Table */ +#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ + +#ifdef ACPI_UNDEFINED_TABLES +/* + * These tables have been seen in the field, but no definition has been found + */ +#define ACPI_SIG_ATKG "ATKG" +#define ACPI_SIG_GSCI "GSCI" /* GMCH SCI table */ +#define ACPI_SIG_IEIT "IEIT" +#endif + +/* + * All tables must be byte-packed to match the ACPI specification, since + * the tables are provided by the system BIOS. + */ +#pragma pack(1) + +/* + * Note about bitfields: The UINT8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + + +/******************************************************************************* + * + * ASF - Alert Standard Format table (Signature "ASF!") + * Revision 0x10 + * + * Conforms to the Alert Standard Format Specification V2.0, 23 April 2003 + * + ******************************************************************************/ + +typedef struct acpi_table_asf +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_ASF; + + +/* ASF subtable header */ + +typedef struct acpi_asf_header +{ + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + +} ACPI_ASF_HEADER; + + +/* Values for Type field above */ + +enum AcpiAsfType +{ + ACPI_ASF_TYPE_INFO = 0, + ACPI_ASF_TYPE_ALERT = 1, + ACPI_ASF_TYPE_CONTROL = 2, + ACPI_ASF_TYPE_BOOT = 3, + ACPI_ASF_TYPE_ADDRESS = 4, + ACPI_ASF_TYPE_RESERVED = 5 +}; + +/* + * ASF subtables + */ + +/* 0: ASF Information */ + +typedef struct acpi_asf_info +{ + ACPI_ASF_HEADER Header; + UINT8 MinResetValue; + UINT8 MinPollInterval; + UINT16 SystemId; + UINT32 MfgId; + UINT8 Flags; + UINT8 Reserved2[3]; + +} ACPI_ASF_INFO; + +/* Masks for Flags field above */ + +#define ACPI_ASF_SMBUS_PROTOCOLS (1) + + +/* 1: ASF Alerts */ + +typedef struct acpi_asf_alert +{ + ACPI_ASF_HEADER Header; + UINT8 AssertMask; + UINT8 DeassertMask; + UINT8 Alerts; + UINT8 DataLength; + +} ACPI_ASF_ALERT; + +typedef struct acpi_asf_alert_data +{ + UINT8 Address; + UINT8 Command; + UINT8 Mask; + UINT8 Value; + UINT8 SensorType; + UINT8 Type; + UINT8 Offset; + UINT8 SourceType; + UINT8 Severity; + UINT8 SensorNumber; + UINT8 Entity; + UINT8 Instance; + +} ACPI_ASF_ALERT_DATA; + + +/* 2: ASF Remote Control */ + +typedef struct acpi_asf_remote +{ + ACPI_ASF_HEADER Header; + UINT8 Controls; + UINT8 DataLength; + UINT16 Reserved2; + +} ACPI_ASF_REMOTE; + +typedef struct acpi_asf_control_data +{ + UINT8 Function; + UINT8 Address; + UINT8 Command; + UINT8 Value; + +} ACPI_ASF_CONTROL_DATA; + + +/* 3: ASF RMCP Boot Options */ + +typedef struct acpi_asf_rmcp +{ + ACPI_ASF_HEADER Header; + UINT8 Capabilities[7]; + UINT8 CompletionCode; + UINT32 EnterpriseId; + UINT8 Command; + UINT16 Parameter; + UINT16 BootOptions; + UINT16 OemParameters; + +} ACPI_ASF_RMCP; + + +/* 4: ASF Address */ + +typedef struct acpi_asf_address +{ + ACPI_ASF_HEADER Header; + UINT8 EpromAddress; + UINT8 Devices; + +} ACPI_ASF_ADDRESS; + + +/******************************************************************************* + * + * BOOT - Simple Boot Flag Table + * Version 1 + * + * Conforms to the "Simple Boot Flag Specification", Version 2.1 + * + ******************************************************************************/ + +typedef struct acpi_table_boot +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 CmosIndex; /* Index in CMOS RAM for the boot register */ + UINT8 Reserved[3]; + +} ACPI_TABLE_BOOT; + + +/******************************************************************************* + * + * DBGP - Debug Port table + * Version 1 + * + * Conforms to the "Debug Port Specification", Version 1.00, 2/9/2000 + * + ******************************************************************************/ + +typedef struct acpi_table_dbgp +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Type; /* 0=full 16550, 1=subset of 16550 */ + UINT8 Reserved[3]; + ACPI_GENERIC_ADDRESS DebugPort; + +} ACPI_TABLE_DBGP; + + +/******************************************************************************* + * + * DMAR - DMA Remapping table + * Version 1 + * + * Conforms to "Intel Virtualization Technology for Directed I/O", + * Version 1.2, Sept. 2008 + * + ******************************************************************************/ + +typedef struct acpi_table_dmar +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Width; /* Host Address Width */ + UINT8 Flags; + UINT8 Reserved[10]; + +} ACPI_TABLE_DMAR; + +/* Masks for Flags field above */ + +#define ACPI_DMAR_INTR_REMAP (1) + + +/* DMAR subtable header */ + +typedef struct acpi_dmar_header +{ + UINT16 Type; + UINT16 Length; + +} ACPI_DMAR_HEADER; + +/* Values for subtable type in ACPI_DMAR_HEADER */ + +enum AcpiDmarType +{ + ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, + ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, + ACPI_DMAR_TYPE_ATSR = 2, + ACPI_DMAR_HARDWARE_AFFINITY = 3, + ACPI_DMAR_TYPE_RESERVED = 4 /* 4 and greater are reserved */ +}; + + +/* DMAR Device Scope structure */ + +typedef struct acpi_dmar_device_scope +{ + UINT8 EntryType; + UINT8 Length; + UINT16 Reserved; + UINT8 EnumerationId; + UINT8 Bus; + +} ACPI_DMAR_DEVICE_SCOPE; + +/* Values for EntryType in ACPI_DMAR_DEVICE_SCOPE */ + +enum AcpiDmarScopeType +{ + ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0, + ACPI_DMAR_SCOPE_TYPE_ENDPOINT = 1, + ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2, + ACPI_DMAR_SCOPE_TYPE_IOAPIC = 3, + ACPI_DMAR_SCOPE_TYPE_HPET = 4, + ACPI_DMAR_SCOPE_TYPE_RESERVED = 5 /* 5 and greater are reserved */ +}; + +typedef struct acpi_dmar_pci_path +{ + UINT8 Device; + UINT8 Function; + +} ACPI_DMAR_PCI_PATH; + + +/* + * DMAR Sub-tables, correspond to Type in ACPI_DMAR_HEADER + */ + +/* 0: Hardware Unit Definition */ + +typedef struct acpi_dmar_hardware_unit +{ + ACPI_DMAR_HEADER Header; + UINT8 Flags; + UINT8 Reserved; + UINT16 Segment; + UINT64 Address; /* Register Base Address */ + +} ACPI_DMAR_HARDWARE_UNIT; + +/* Masks for Flags field above */ + +#define ACPI_DMAR_INCLUDE_ALL (1) + + +/* 1: Reserved Memory Defininition */ + +typedef struct acpi_dmar_reserved_memory +{ + ACPI_DMAR_HEADER Header; + UINT16 Reserved; + UINT16 Segment; + UINT64 BaseAddress; /* 4K aligned base address */ + UINT64 EndAddress; /* 4K aligned limit address */ + +} ACPI_DMAR_RESERVED_MEMORY; + +/* Masks for Flags field above */ + +#define ACPI_DMAR_ALLOW_ALL (1) + + +/* 2: Root Port ATS Capability Reporting Structure */ + +typedef struct acpi_dmar_atsr +{ + ACPI_DMAR_HEADER Header; + UINT8 Flags; + UINT8 Reserved; + UINT16 Segment; + +} ACPI_DMAR_ATSR; + +/* Masks for Flags field above */ + +#define ACPI_DMAR_ALL_PORTS (1) + + +/* 3: Remapping Hardware Static Affinity Structure */ + +typedef struct acpi_dmar_rhsa +{ + ACPI_DMAR_HEADER Header; + UINT32 Reserved; + UINT64 BaseAddress; + UINT32 ProximityDomain; + +} ACPI_DMAR_RHSA; + + +/******************************************************************************* + * + * HPET - High Precision Event Timer table + * Version 1 + * + * Conforms to "IA-PC HPET (High Precision Event Timers) Specification", + * Version 1.0a, October 2004 + * + ******************************************************************************/ + +typedef struct acpi_table_hpet +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Id; /* Hardware ID of event timer block */ + ACPI_GENERIC_ADDRESS Address; /* Address of event timer block */ + UINT8 Sequence; /* HPET sequence number */ + UINT16 MinimumTick; /* Main counter min tick, periodic mode */ + UINT8 Flags; + +} ACPI_TABLE_HPET; + +/* Masks for Flags field above */ + +#define ACPI_HPET_PAGE_PROTECT_MASK (3) + +/* Values for Page Protect flags */ + +enum AcpiHpetPageProtect +{ + ACPI_HPET_NO_PAGE_PROTECT = 0, + ACPI_HPET_PAGE_PROTECT4 = 1, + ACPI_HPET_PAGE_PROTECT64 = 2 +}; + + +/******************************************************************************* + * + * IBFT - Boot Firmware Table + * Version 1 + * + * Conforms to "iSCSI Boot Firmware Table (iBFT) as Defined in ACPI 3.0b + * Specification", Version 1.01, March 1, 2007 + * + * Note: It appears that this table is not intended to appear in the RSDT/XSDT. + * Therefore, it is not currently supported by the disassembler. + * + ******************************************************************************/ + +typedef struct acpi_table_ibft +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Reserved[12]; + +} ACPI_TABLE_IBFT; + + +/* IBFT common subtable header */ + +typedef struct acpi_ibft_header +{ + UINT8 Type; + UINT8 Version; + UINT16 Length; + UINT8 Index; + UINT8 Flags; + +} ACPI_IBFT_HEADER; + +/* Values for Type field above */ + +enum AcpiIbftType +{ + ACPI_IBFT_TYPE_NOT_USED = 0, + ACPI_IBFT_TYPE_CONTROL = 1, + ACPI_IBFT_TYPE_INITIATOR = 2, + ACPI_IBFT_TYPE_NIC = 3, + ACPI_IBFT_TYPE_TARGET = 4, + ACPI_IBFT_TYPE_EXTENSIONS = 5, + ACPI_IBFT_TYPE_RESERVED = 6 /* 6 and greater are reserved */ +}; + + +/* IBFT subtables */ + +typedef struct acpi_ibft_control +{ + ACPI_IBFT_HEADER Header; + UINT16 Extensions; + UINT16 InitiatorOffset; + UINT16 Nic0Offset; + UINT16 Target0Offset; + UINT16 Nic1Offset; + UINT16 Target1Offset; + +} ACPI_IBFT_CONTROL; + +typedef struct acpi_ibft_initiator +{ + ACPI_IBFT_HEADER Header; + UINT8 SnsServer[16]; + UINT8 SlpServer[16]; + UINT8 PrimaryServer[16]; + UINT8 SecondaryServer[16]; + UINT16 NameLength; + UINT16 NameOffset; + +} ACPI_IBFT_INITIATOR; + +typedef struct acpi_ibft_nic +{ + ACPI_IBFT_HEADER Header; + UINT8 IpAddress[16]; + UINT8 SubnetMaskPrefix; + UINT8 Origin; + UINT8 Gateway[16]; + UINT8 PrimaryDns[16]; + UINT8 SecondaryDns[16]; + UINT8 Dhcp[16]; + UINT16 Vlan; + UINT8 MacAddress[6]; + UINT16 PciAddress; + UINT16 NameLength; + UINT16 NameOffset; + +} ACPI_IBFT_NIC; + +typedef struct acpi_ibft_target +{ + ACPI_IBFT_HEADER Header; + UINT8 TargetIpAddress[16]; + UINT16 TargetIpSocket; + UINT8 TargetBootLun[8]; + UINT8 ChapType; + UINT8 NicAssociation; + UINT16 TargetNameLength; + UINT16 TargetNameOffset; + UINT16 ChapNameLength; + UINT16 ChapNameOffset; + UINT16 ChapSecretLength; + UINT16 ChapSecretOffset; + UINT16 ReverseChapNameLength; + UINT16 ReverseChapNameOffset; + UINT16 ReverseChapSecretLength; + UINT16 ReverseChapSecretOffset; + +} ACPI_IBFT_TARGET; + + +/******************************************************************************* + * + * IVRS - I/O Virtualization Reporting Structure + * Version 1 + * + * Conforms to "AMD I/O Virtualization Technology (IOMMU) Specification", + * Revision 1.26, February 2009. + * + ******************************************************************************/ + +typedef struct acpi_table_ivrs +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Info; /* Common virtualization info */ + UINT64 Reserved; + +} ACPI_TABLE_IVRS; + +/* Values for Info field above */ + +#define ACPI_IVRS_PHYSICAL_SIZE 0x00007F00 /* 7 bits, physical address size */ +#define ACPI_IVRS_VIRTUAL_SIZE 0x003F8000 /* 7 bits, virtual address size */ +#define ACPI_IVRS_ATS_RESERVED 0x00400000 /* ATS address translation range reserved */ + + +/* IVRS subtable header */ + +typedef struct acpi_ivrs_header +{ + UINT8 Type; /* Subtable type */ + UINT8 Flags; + UINT16 Length; /* Subtable length */ + UINT16 DeviceId; /* ID of IOMMU */ + +} ACPI_IVRS_HEADER; + +/* Values for subtable Type above */ + +enum AcpiIvrsType +{ + ACPI_IVRS_TYPE_HARDWARE = 0x10, + ACPI_IVRS_TYPE_MEMORY1 = 0x20, + ACPI_IVRS_TYPE_MEMORY2 = 0x21, + ACPI_IVRS_TYPE_MEMORY3 = 0x22 +}; + +/* Masks for Flags field above for IVHD subtable */ + +#define ACPI_IVHD_TT_ENABLE (1) +#define ACPI_IVHD_PASS_PW (1<<1) +#define ACPI_IVHD_RES_PASS_PW (1<<2) +#define ACPI_IVHD_ISOC (1<<3) +#define ACPI_IVHD_IOTLB (1<<4) + +/* Masks for Flags field above for IVMD subtable */ + +#define ACPI_IVMD_UNITY (1) +#define ACPI_IVMD_READ (1<<1) +#define ACPI_IVMD_WRITE (1<<2) +#define ACPI_IVMD_EXCLUSION_RANGE (1<<3) + + +/* + * IVRS subtables, correspond to Type in ACPI_IVRS_HEADER + */ + +/* 0x10: I/O Virtualization Hardware Definition Block (IVHD) */ + +typedef struct acpi_ivrs_hardware +{ + ACPI_IVRS_HEADER Header; + UINT16 CapabilityOffset; /* Offset for IOMMU control fields */ + UINT64 BaseAddress; /* IOMMU control registers */ + UINT16 PciSegmentGroup; + UINT16 Info; /* MSI number and unit ID */ + UINT32 Reserved; + +} ACPI_IVRS_HARDWARE; + +/* Masks for Info field above */ + +#define ACPI_IVHD_MSI_NUMBER_MASK 0x001F /* 5 bits, MSI message number */ +#define ACPI_IVHD_UNIT_ID_MASK 0x1F00 /* 5 bits, UnitID */ + + +/* + * Device Entries for IVHD subtable, appear after ACPI_IVRS_HARDWARE structure. + * Upper two bits of the Type field are the (encoded) length of the structure. + * Currently, only 4 and 8 byte entries are defined. 16 and 32 byte entries + * are reserved for future use but not defined. + */ +typedef struct acpi_ivrs_de_header +{ + UINT8 Type; + UINT16 Id; + UINT8 DataSetting; + +} ACPI_IVRS_DE_HEADER; + +/* Length of device entry is in the top two bits of Type field above */ + +#define ACPI_IVHD_ENTRY_LENGTH 0xC0 + +/* Values for device entry Type field above */ + +enum AcpiIvrsDeviceEntryType +{ + /* 4-byte device entries, all use ACPI_IVRS_DEVICE4 */ + + ACPI_IVRS_TYPE_PAD4 = 0, + ACPI_IVRS_TYPE_ALL = 1, + ACPI_IVRS_TYPE_SELECT = 2, + ACPI_IVRS_TYPE_START = 3, + ACPI_IVRS_TYPE_END = 4, + + /* 8-byte device entries */ + + ACPI_IVRS_TYPE_PAD8 = 64, + ACPI_IVRS_TYPE_NOT_USED = 65, + ACPI_IVRS_TYPE_ALIAS_SELECT = 66, /* Uses ACPI_IVRS_DEVICE8A */ + ACPI_IVRS_TYPE_ALIAS_START = 67, /* Uses ACPI_IVRS_DEVICE8A */ + ACPI_IVRS_TYPE_EXT_SELECT = 70, /* Uses ACPI_IVRS_DEVICE8B */ + ACPI_IVRS_TYPE_EXT_START = 71, /* Uses ACPI_IVRS_DEVICE8B */ + ACPI_IVRS_TYPE_SPECIAL = 72 /* Uses ACPI_IVRS_DEVICE8C */ +}; + +/* Values for Data field above */ + +#define ACPI_IVHD_INIT_PASS (1) +#define ACPI_IVHD_EINT_PASS (1<<1) +#define ACPI_IVHD_NMI_PASS (1<<2) +#define ACPI_IVHD_SYSTEM_MGMT (3<<4) +#define ACPI_IVHD_LINT0_PASS (1<<6) +#define ACPI_IVHD_LINT1_PASS (1<<7) + + +/* Types 0-4: 4-byte device entry */ + +typedef struct acpi_ivrs_device4 +{ + ACPI_IVRS_DE_HEADER Header; + +} ACPI_IVRS_DEVICE4; + +/* Types 66-67: 8-byte device entry */ + +typedef struct acpi_ivrs_device8a +{ + ACPI_IVRS_DE_HEADER Header; + UINT8 Reserved1; + UINT16 UsedId; + UINT8 Reserved2; + +} ACPI_IVRS_DEVICE8A; + +/* Types 70-71: 8-byte device entry */ + +typedef struct acpi_ivrs_device8b +{ + ACPI_IVRS_DE_HEADER Header; + UINT32 ExtendedData; + +} ACPI_IVRS_DEVICE8B; + +/* Values for ExtendedData above */ + +#define ACPI_IVHD_ATS_DISABLED (1<<31) + +/* Type 72: 8-byte device entry */ + +typedef struct acpi_ivrs_device8c +{ + ACPI_IVRS_DE_HEADER Header; + UINT8 Handle; + UINT16 UsedId; + UINT8 Variety; + +} ACPI_IVRS_DEVICE8C; + +/* Values for Variety field above */ + +#define ACPI_IVHD_IOAPIC 1 +#define ACPI_IVHD_HPET 2 + + +/* 0x20, 0x21, 0x22: I/O Virtualization Memory Definition Block (IVMD) */ + +typedef struct acpi_ivrs_memory +{ + ACPI_IVRS_HEADER Header; + UINT16 AuxData; + UINT64 Reserved; + UINT64 StartAddress; + UINT64 MemoryLength; + +} ACPI_IVRS_MEMORY; + + +/******************************************************************************* + * + * MCFG - PCI Memory Mapped Configuration table and sub-table + * Version 1 + * + * Conforms to "PCI Firmware Specification", Revision 3.0, June 20, 2005 + * + ******************************************************************************/ + +typedef struct acpi_table_mcfg +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Reserved[8]; + +} ACPI_TABLE_MCFG; + + +/* Subtable */ + +typedef struct acpi_mcfg_allocation +{ + UINT64 Address; /* Base address, processor-relative */ + UINT16 PciSegment; /* PCI segment group number */ + UINT8 StartBusNumber; /* Starting PCI Bus number */ + UINT8 EndBusNumber; /* Final PCI Bus number */ + UINT32 Reserved; + +} ACPI_MCFG_ALLOCATION; + + +/******************************************************************************* + * + * MCHI - Management Controller Host Interface Table + * Version 1 + * + * Conforms to "Management Component Transport Protocol (MCTP) Host + * Interface Specification", Revision 1.0.0a, October 13, 2009 + * + ******************************************************************************/ + +typedef struct acpi_table_mchi +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 InterfaceType; + UINT8 Protocol; + UINT64 ProtocolData; + UINT8 InterruptType; + UINT8 Gpe; + UINT8 PciDeviceFlag; + UINT32 GlobalInterrupt; + ACPI_GENERIC_ADDRESS ControlRegister; + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + +} ACPI_TABLE_MCHI; + + +/******************************************************************************* + * + * SLIC - Software Licensing Description Table + * Version 1 + * + * Conforms to "OEM Activation 2.0 for Windows Vista Operating Systems", + * Copyright 2006 + * + ******************************************************************************/ + +/* Basic SLIC table is only the common ACPI header */ + +typedef struct acpi_table_slic +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_SLIC; + + +/* Common SLIC subtable header */ + +typedef struct acpi_slic_header +{ + UINT32 Type; + UINT32 Length; + +} ACPI_SLIC_HEADER; + +/* Values for Type field above */ + +enum AcpiSlicType +{ + ACPI_SLIC_TYPE_PUBLIC_KEY = 0, + ACPI_SLIC_TYPE_WINDOWS_MARKER = 1, + ACPI_SLIC_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + + +/* + * SLIC Sub-tables, correspond to Type in ACPI_SLIC_HEADER + */ + +/* 0: Public Key Structure */ + +typedef struct acpi_slic_key +{ + ACPI_SLIC_HEADER Header; + UINT8 KeyType; + UINT8 Version; + UINT16 Reserved; + UINT32 Algorithm; + char Magic[4]; + UINT32 BitLength; + UINT32 Exponent; + UINT8 Modulus[128]; + +} ACPI_SLIC_KEY; + + +/* 1: Windows Marker Structure */ + +typedef struct acpi_slic_marker +{ + ACPI_SLIC_HEADER Header; + UINT32 Version; + char OemId[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ + char OemTableId[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ + char WindowsFlag[8]; + UINT32 SlicVersion; + UINT8 Reserved[16]; + UINT8 Signature[128]; + +} ACPI_SLIC_MARKER; + + +/******************************************************************************* + * + * SPCR - Serial Port Console Redirection table + * Version 1 + * + * Conforms to "Serial Port Console Redirection Table", + * Version 1.00, January 11, 2002 + * + ******************************************************************************/ + +typedef struct acpi_table_spcr +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 InterfaceType; /* 0=full 16550, 1=subset of 16550 */ + UINT8 Reserved[3]; + ACPI_GENERIC_ADDRESS SerialPort; + UINT8 InterruptType; + UINT8 PcInterrupt; + UINT32 Interrupt; + UINT8 BaudRate; + UINT8 Parity; + UINT8 StopBits; + UINT8 FlowControl; + UINT8 TerminalType; + UINT8 Reserved1; + UINT16 PciDeviceId; + UINT16 PciVendorId; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT32 PciFlags; + UINT8 PciSegment; + UINT32 Reserved2; + +} ACPI_TABLE_SPCR; + +/* Masks for PciFlags field above */ + +#define ACPI_SPCR_DO_NOT_DISABLE (1) + + +/******************************************************************************* + * + * SPMI - Server Platform Management Interface table + * Version 5 + * + * Conforms to "Intelligent Platform Management Interface Specification + * Second Generation v2.0", Document Revision 1.0, February 12, 2004 with + * June 12, 2009 markup. + * + ******************************************************************************/ + +typedef struct acpi_table_spmi +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 InterfaceType; + UINT8 Reserved; /* Must be 1 */ + UINT16 SpecRevision; /* Version of IPMI */ + UINT8 InterruptType; + UINT8 GpeNumber; /* GPE assigned */ + UINT8 Reserved1; + UINT8 PciDeviceFlag; + UINT32 Interrupt; + ACPI_GENERIC_ADDRESS IpmiRegister; + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT8 Reserved2; + +} ACPI_TABLE_SPMI; + +/* Values for InterfaceType above */ + +enum AcpiSpmiInterfaceTypes +{ + ACPI_SPMI_NOT_USED = 0, + ACPI_SPMI_KEYBOARD = 1, + ACPI_SPMI_SMI = 2, + ACPI_SPMI_BLOCK_TRANSFER = 3, + ACPI_SPMI_SMBUS = 4, + ACPI_SPMI_RESERVED = 5 /* 5 and above are reserved */ +}; + + +/******************************************************************************* + * + * TCPA - Trusted Computing Platform Alliance table + * Version 1 + * + * Conforms to "TCG PC Specific Implementation Specification", + * Version 1.1, August 18, 2003 + * + ******************************************************************************/ + +typedef struct acpi_table_tcpa +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 Reserved; + UINT32 MaxLogLength; /* Maximum length for the event log area */ + UINT64 LogAddress; /* Address of the event log area */ + +} ACPI_TABLE_TCPA; + + +/******************************************************************************* + * + * UEFI - UEFI Boot optimization Table + * Version 1 + * + * Conforms to "Unified Extensible Firmware Interface Specification", + * Version 2.3, May 8, 2009 + * + ******************************************************************************/ + +typedef struct acpi_table_uefi +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Identifier[16]; /* UUID identifier */ + UINT16 DataOffset; /* Offset of remaining data in table */ + +} ACPI_TABLE_UEFI; + + +/******************************************************************************* + * + * WAET - Windows ACPI Emulated devices Table + * Version 1 + * + * Conforms to "Windows ACPI Emulated Devices Table", version 1.0, April 6, 2009 + * + ******************************************************************************/ + +typedef struct acpi_table_waet +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Flags; + +} ACPI_TABLE_WAET; + +/* Masks for Flags field above */ + +#define ACPI_WAET_RTC_NO_ACK (1) /* RTC requires no int acknowledge */ +#define ACPI_WAET_TIMER_ONE_READ (1<<1) /* PM timer requires only one read */ + + +/******************************************************************************* + * + * WDAT - Watchdog Action Table + * Version 1 + * + * Conforms to "Hardware Watchdog Timers Design Specification", + * Copyright 2006 Microsoft Corporation. + * + ******************************************************************************/ + +typedef struct acpi_table_wdat +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 HeaderLength; /* Watchdog Header Length */ + UINT16 PciSegment; /* PCI Segment number */ + UINT8 PciBus; /* PCI Bus number */ + UINT8 PciDevice; /* PCI Device number */ + UINT8 PciFunction; /* PCI Function number */ + UINT8 Reserved[3]; + UINT32 TimerPeriod; /* Period of one timer count (msec) */ + UINT32 MaxCount; /* Maximum counter value supported */ + UINT32 MinCount; /* Minimum counter value */ + UINT8 Flags; + UINT8 Reserved2[3]; + UINT32 Entries; /* Number of watchdog entries that follow */ + +} ACPI_TABLE_WDAT; + +/* Masks for Flags field above */ + +#define ACPI_WDAT_ENABLED (1) +#define ACPI_WDAT_STOPPED 0x80 + + +/* WDAT Instruction Entries (actions) */ + +typedef struct acpi_wdat_entry +{ + UINT8 Action; + UINT8 Instruction; + UINT16 Reserved; + ACPI_GENERIC_ADDRESS RegisterRegion; + UINT32 Value; /* Value used with Read/Write register */ + UINT32 Mask; /* Bitmask required for this register instruction */ + +} ACPI_WDAT_ENTRY; + +/* Values for Action field above */ + +enum AcpiWdatActions +{ + ACPI_WDAT_RESET = 1, + ACPI_WDAT_GET_CURRENT_COUNTDOWN = 4, + ACPI_WDAT_GET_COUNTDOWN = 5, + ACPI_WDAT_SET_COUNTDOWN = 6, + ACPI_WDAT_GET_RUNNING_STATE = 8, + ACPI_WDAT_SET_RUNNING_STATE = 9, + ACPI_WDAT_GET_STOPPED_STATE = 10, + ACPI_WDAT_SET_STOPPED_STATE = 11, + ACPI_WDAT_GET_REBOOT = 16, + ACPI_WDAT_SET_REBOOT = 17, + ACPI_WDAT_GET_SHUTDOWN = 18, + ACPI_WDAT_SET_SHUTDOWN = 19, + ACPI_WDAT_GET_STATUS = 32, + ACPI_WDAT_SET_STATUS = 33, + ACPI_WDAT_ACTION_RESERVED = 34 /* 34 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum AcpiWdatInstructions +{ + ACPI_WDAT_READ_VALUE = 0, + ACPI_WDAT_READ_COUNTDOWN = 1, + ACPI_WDAT_WRITE_VALUE = 2, + ACPI_WDAT_WRITE_COUNTDOWN = 3, + ACPI_WDAT_INSTRUCTION_RESERVED = 4, /* 4 and greater are reserved */ + ACPI_WDAT_PRESERVE_REGISTER = 0x80 /* Except for this value */ +}; + + +/******************************************************************************* + * + * WDDT - Watchdog Descriptor Table + * Version 1 + * + * Conforms to "Using the Intel ICH Family Watchdog Timer (WDT)", + * Version 001, September 2002 + * + ******************************************************************************/ + +typedef struct acpi_table_wddt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 SpecVersion; + UINT16 TableVersion; + UINT16 PciVendorId; + ACPI_GENERIC_ADDRESS Address; + UINT16 MaxCount; /* Maximum counter value supported */ + UINT16 MinCount; /* Minimum counter value supported */ + UINT16 Period; + UINT16 Status; + UINT16 Capability; + +} ACPI_TABLE_WDDT; + +/* Flags for Status field above */ + +#define ACPI_WDDT_AVAILABLE (1) +#define ACPI_WDDT_ACTIVE (1<<1) +#define ACPI_WDDT_TCO_OS_OWNED (1<<2) +#define ACPI_WDDT_USER_RESET (1<<11) +#define ACPI_WDDT_WDT_RESET (1<<12) +#define ACPI_WDDT_POWER_FAIL (1<<13) +#define ACPI_WDDT_UNKNOWN_RESET (1<<14) + +/* Flags for Capability field above */ + +#define ACPI_WDDT_AUTO_RESET (1) +#define ACPI_WDDT_ALERT_SUPPORT (1<<1) + + +/******************************************************************************* + * + * WDRT - Watchdog Resource Table + * Version 1 + * + * Conforms to "Watchdog Timer Hardware Requirements for Windows Server 2003", + * Version 1.01, August 28, 2006 + * + ******************************************************************************/ + +typedef struct acpi_table_wdrt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + ACPI_GENERIC_ADDRESS ControlRegister; + ACPI_GENERIC_ADDRESS CountRegister; + UINT16 PciDeviceId; + UINT16 PciVendorId; + UINT8 PciBus; /* PCI Bus number */ + UINT8 PciDevice; /* PCI Device number */ + UINT8 PciFunction; /* PCI Function number */ + UINT8 PciSegment; /* PCI Segment number */ + UINT16 MaxCount; /* Maximum counter value supported */ + UINT8 Units; + +} ACPI_TABLE_WDRT; + + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL2_H__ */ + diff --git a/source/include/actbl3.h b/source/include/actbl3.h new file mode 100644 index 000000000000..c5dd4184dd51 --- /dev/null +++ b/source/include/actbl3.h @@ -0,0 +1,650 @@ +/****************************************************************************** + * + * Name: actbl3.h - ACPI Table Definitions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL3_H__ +#define __ACTBL3_H__ + + +/******************************************************************************* + * + * Additional ACPI Tables (3) + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + * The tables in this file are fully defined within the ACPI specification. + * + ******************************************************************************/ + + +/* + * Values for description table header signatures for tables defined in this + * file. Useful because they make it more difficult to inadvertently type in + * the wrong signature. + */ +#define ACPI_SIG_BGRT "BGRT" /* Boot Graphics Resource Table */ +#define ACPI_SIG_DRTM "DRTM" /* Dynamic Root of Trust for Measurement table */ +#define ACPI_SIG_FPDT "FPDT" /* Firmware Performance Data Table */ +#define ACPI_SIG_GTDT "GTDT" /* Generic Timer Description Table */ +#define ACPI_SIG_MPST "MPST" /* Memory Power State Table */ +#define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */ +#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ +#define ACPI_SIG_RASF "RASF" /* RAS Feature table */ + +#define ACPI_SIG_S3PT "S3PT" /* S3 Performance (sub)Table */ +#define ACPI_SIG_PCCS "PCC" /* PCC Shared Memory Region */ + +/* Reserved table signatures */ + +#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */ +#define ACPI_SIG_DBG2 "DBG2" /* Debug Port table 2 */ +#define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */ +#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ +#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ + +/* + * All tables must be byte-packed to match the ACPI specification, since + * the tables are provided by the system BIOS. + */ +#pragma pack(1) + +/* + * Note about bitfields: The UINT8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + + +/******************************************************************************* + * + * BGRT - Boot Graphics Resource Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_bgrt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 Version; + UINT8 Status; + UINT8 ImageType; + UINT64 ImageAddress; + UINT32 ImageOffsetX; + UINT32 ImageOffsetY; + +} ACPI_TABLE_BGRT; + + +/******************************************************************************* + * + * DRTM - Dynamic Root of Trust for Measurement table + * + ******************************************************************************/ + +typedef struct acpi_table_drtm +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 EntryBaseAddress; + UINT64 EntryLength; + UINT32 EntryAddress32; + UINT64 EntryAddress64; + UINT64 ExitAddress; + UINT64 LogAreaAddress; + UINT32 LogAreaLength; + UINT64 ArchDependentAddress; + UINT32 Flags; + +} ACPI_TABLE_DRTM; + +/* 1) Validated Tables List */ + +typedef struct acpi_drtm_vtl_list +{ + UINT32 ValidatedTableListCount; + +} ACPI_DRTM_VTL_LIST; + +/* 2) Resources List */ + +typedef struct acpi_drtm_resource_list +{ + UINT32 ResourceListCount; + +} ACPI_DRTM_RESOURCE_LIST; + +/* 3) Platform-specific Identifiers List */ + +typedef struct acpi_drtm_id_list +{ + UINT32 IdListCount; + +} ACPI_DRTM_ID_LIST; + + +/******************************************************************************* + * + * FPDT - Firmware Performance Data Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_fpdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_FPDT; + + +/* FPDT subtable header */ + +typedef struct acpi_fpdt_header +{ + UINT16 Type; + UINT8 Length; + UINT8 Revision; + +} ACPI_FPDT_HEADER; + +/* Values for Type field above */ + +enum AcpiFpdtType +{ + ACPI_FPDT_TYPE_BOOT = 0, + ACPI_FPDT_TYPE_S3PERF = 1, +}; + + +/* + * FPDT subtables + */ + +/* 0: Firmware Basic Boot Performance Record */ + +typedef struct acpi_fpdt_boot +{ + ACPI_FPDT_HEADER Header; + UINT8 Reserved[4]; + UINT64 ResetEnd; + UINT64 LoadStart; + UINT64 StartupStart; + UINT64 ExitServicesEntry; + UINT64 ExitServicesExit; + +} ACPI_FPDT_BOOT; + + +/* 1: S3 Performance Table Pointer Record */ + +typedef struct acpi_fpdt_s3pt_ptr +{ + ACPI_FPDT_HEADER Header; + UINT8 Reserved[4]; + UINT64 Address; + +} ACPI_FPDT_S3PT_PTR; + + +/* + * S3PT - S3 Performance Table. This table is pointed to by the + * FPDT S3 Pointer Record above. + */ +typedef struct acpi_table_s3pt +{ + UINT8 Signature[4]; /* "S3PT" */ + UINT32 Length; + +} ACPI_TABLE_S3PT; + + +/* + * S3PT Subtables + */ +typedef struct acpi_s3pt_header +{ + UINT16 Type; + UINT8 Length; + UINT8 Revision; + +} ACPI_S3PT_HEADER; + +/* Values for Type field above */ + +enum AcpiS3ptType +{ + ACPI_S3PT_TYPE_RESUME = 0, + ACPI_S3PT_TYPE_SUSPEND = 1, +}; + +typedef struct acpi_s3pt_resume +{ + ACPI_S3PT_HEADER Header; + UINT32 ResumeCount; + UINT64 FullResume; + UINT64 AverageResume; + +} ACPI_S3PT_RESUME; + +typedef struct acpi_s3pt_suspend +{ + ACPI_S3PT_HEADER Header; + UINT64 SuspendStart; + UINT64 SuspendEnd; + +} ACPI_S3PT_SUSPEND; + + +/******************************************************************************* + * + * GTDT - Generic Timer Description Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_gtdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 Address; + UINT32 Flags; + UINT32 SecurePl1Interrupt; + UINT32 SecurePl1Flags; + UINT32 NonSecurePl1Interrupt; + UINT32 NonSecurePl1Flags; + UINT32 VirtualTimerInterrupt; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePl2Interrupt; + UINT32 NonSecurePl2Flags; + +} ACPI_TABLE_GTDT; + +/* Values for Flags field above */ + +#define ACPI_GTDT_MAPPED_BLOCK_PRESENT 1 + +/* Values for all "TimerFlags" fields above */ + +#define ACPI_GTDT_INTERRUPT_MODE 1 +#define ACPI_GTDT_INTERRUPT_POLARITY 2 + + +/******************************************************************************* + * + * MPST - Memory Power State Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +#define ACPI_MPST_CHANNEL_INFO \ + UINT16 Reserved1; \ + UINT8 ChannelId; \ + UINT8 Reserved2; \ + UINT16 PowerNodeCount; + +/* Main table */ + +typedef struct acpi_table_mpst +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + ACPI_MPST_CHANNEL_INFO /* Platform Communication Channel */ + +} ACPI_TABLE_MPST; + + +/* Memory Platform Communication Channel Info */ + +typedef struct acpi_mpst_channel +{ + ACPI_MPST_CHANNEL_INFO /* Platform Communication Channel */ + +} ACPI_MPST_CHANNEL; + + +/* Memory Power Node Structure */ + +typedef struct acpi_mpst_power_node +{ + UINT8 Flags; + UINT8 Reserved1; + UINT16 NodeId; + UINT32 Length; + UINT64 RangeAddress; + UINT64 RangeLength; + UINT8 NumPowerStates; + UINT8 NumPhysicalComponents; + UINT16 Reserved2; + +} ACPI_MPST_POWER_NODE; + +/* Values for Flags field above */ + +#define ACPI_MPST_ENABLED 1 +#define ACPI_MPST_POWER_MANAGED 2 +#define ACPI_MPST_HOT_PLUG_CAPABLE 4 + + +/* Memory Power State Structure (follows POWER_NODE above) */ + +typedef struct acpi_mpst_power_state +{ + UINT8 PowerState; + UINT8 InfoIndex; + +} ACPI_MPST_POWER_STATE; + + +/* Physical Component ID Structure (follows POWER_STATE above) */ + +typedef struct acpi_mpst_component +{ + UINT16 ComponentId; + +} ACPI_MPST_COMPONENT; + + +/* Memory Power State Characteristics Structure (follows all POWER_NODEs) */ + +typedef struct acpi_mpst_data_hdr +{ + UINT16 CharacteristicsCount; + +} ACPI_MPST_DATA_HDR; + +typedef struct acpi_mpst_power_data +{ + UINT8 Revision; + UINT8 Flags; + UINT16 Reserved1; + UINT32 AveragePower; + UINT32 PowerSaving; + UINT64 ExitLatency; + UINT64 Reserved2; + +} ACPI_MPST_POWER_DATA; + +/* Values for Flags field above */ + +#define ACPI_MPST_PRESERVE 1 +#define ACPI_MPST_AUTOENTRY 2 +#define ACPI_MPST_AUTOEXIT 4 + + +/* Shared Memory Region (not part of an ACPI table) */ + +typedef struct acpi_mpst_shared +{ + UINT32 Signature; + UINT16 PccCommand; + UINT16 PccStatus; + UINT16 CommandRegister; + UINT16 StatusRegister; + UINT16 PowerStateId; + UINT16 PowerNodeId; + UINT64 EnergyConsumed; + UINT64 AveragePower; + +} ACPI_MPST_SHARED; + + +/******************************************************************************* + * + * PCCT - Platform Communications Channel Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_pcct +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Flags; + UINT32 Latency; + UINT32 Reserved; + +} ACPI_TABLE_PCCT; + +/* Values for Flags field above */ + +#define ACPI_PCCT_DOORBELL 1 + +/* + * PCCT subtables + */ + +/* 0: Generic Communications Subspace */ + +typedef struct acpi_pcct_subspace +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 PreserveMask; + UINT64 WriteMask; + +} ACPI_PCCT_SUBSPACE; + + +/* + * PCC memory structures (not part of the ACPI table) + */ + +/* Shared Memory Region */ + +typedef struct acpi_pcct_shared_memory +{ + UINT32 Signature; + UINT16 Command; + UINT16 Status; + +} ACPI_PCCT_SHARED_MEMORY; + + +/******************************************************************************* + * + * PMTT - Platform Memory Topology Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_pmtt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; + +} ACPI_TABLE_PMTT; + + +/* Common header for PMTT subtables that follow main table */ + +typedef struct acpi_pmtt_header +{ + UINT8 Type; + UINT8 Reserved1; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved2; + +} ACPI_PMTT_HEADER; + +/* Values for Type field above */ + +#define ACPI_PMTT_TYPE_SOCKET 0 +#define ACPI_PMTT_TYPE_CONTROLLER 1 +#define ACPI_PMTT_TYPE_DIMM 2 +#define ACPI_PMTT_TYPE_RESERVED 3 /* 0x03-0xFF are reserved */ + +/* Values for Flags field above */ + +#define ACPI_PMTT_TOP_LEVEL 0x0001 +#define ACPI_PMTT_PHYSICAL 0x0002 +#define ACPI_PMTT_MEMORY_TYPE 0x000C + + +/* + * PMTT subtables, correspond to Type in acpi_pmtt_header + */ + + +/* 0: Socket Structure */ + +typedef struct acpi_pmtt_socket +{ + ACPI_PMTT_HEADER Header; + UINT16 SocketId; + UINT16 Reserved; + +} ACPI_PMTT_SOCKET; + + +/* 1: Memory Controller subtable */ + +typedef struct acpi_pmtt_controller +{ + ACPI_PMTT_HEADER Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 AccessWidth; + UINT16 Alignment; + UINT16 Reserved; + UINT16 DomainCount; + +} ACPI_PMTT_CONTROLLER; + +/* 1a: Proximity Domain substructure */ + +typedef struct acpi_pmtt_domain +{ + UINT32 ProximityDomain; + +} ACPI_PMTT_DOMAIN; + + +/* 2: Physical Component Identifier (DIMM) */ + +typedef struct acpi_pmtt_physical_component +{ + ACPI_PMTT_HEADER Header; + UINT16 ComponentId; + UINT16 Reserved; + UINT32 MemorySize; + UINT32 BiosHandle; + +} ACPI_PMTT_PHYSICAL_COMPONENT; + + +/******************************************************************************* + * + * RASF - RAS Feature Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_rasf +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 ChannelId[12]; + +} ACPI_TABLE_RASF; + +/* RASF Platform Communication Channel Shared Memory Region */ + +typedef struct acpi_rasf_shared_memory +{ + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT64 RequestedAddress; + UINT64 RequestedLength; + UINT64 ActualAddress; + UINT64 ActualLength; + UINT16 Flags; + UINT8 Speed; + +} ACPI_RASF_SHARED_MEMORY; + +/* Masks for Flags and Speed fields above */ + +#define ACPI_RASF_SCRUBBER_RUNNING 1 +#define ACPI_RASF_SPEED (7<<1) + +/* Channel Commands */ + +enum AcpiRasfCommands +{ + ACPI_RASF_GET_RAS_CAPABILITIES = 1, + ACPI_RASF_GET_PATROL_PARAMETERS = 2, + ACPI_RASF_START_PATROL_SCRUBBER = 3, + ACPI_RASF_STOP_PATROL_SCRUBBER = 4 +}; + +/* Channel Command flags */ + +#define ACPI_RASF_GENERATE_SCI (1<<15) + +/* Status values */ + +enum AcpiRasfStatus +{ + ACPI_RASF_SUCCESS = 0, + ACPI_RASF_NOT_VALID = 1, + ACPI_RASF_NOT_SUPPORTED = 2, + ACPI_RASF_BUSY = 3, + ACPI_RASF_FAILED = 4, + ACPI_RASF_ABORTED = 5, + ACPI_RASF_INVALID_DATA = 6 +}; + +/* Status flags */ + +#define ACPI_RASF_COMMAND_COMPLETE (1) +#define ACPI_RASF_SCI_DOORBELL (1<<1) +#define ACPI_RASF_ERROR (1<<2) +#define ACPI_RASF_STATUS (0x1F<<3) + + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL3_H__ */ diff --git a/source/include/actypes.h b/source/include/actypes.h new file mode 100644 index 000000000000..30d9088b8eb4 --- /dev/null +++ b/source/include/actypes.h @@ -0,0 +1,1216 @@ +/****************************************************************************** + * + * Name: actypes.h - Common data types for the entire ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTYPES_H__ +#define __ACTYPES_H__ + +/* acpisrc:StructDefs -- for acpisrc conversion */ + +/* + * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header + * and must be either 32 or 64. 16-bit ACPICA is no longer supported, as of + * 12/2006. + */ +#ifndef ACPI_MACHINE_WIDTH +#error ACPI_MACHINE_WIDTH not defined +#endif + +/*! [Begin] no source code translation */ + +/* + * Data type ranges + * Note: These macros are designed to be compiler independent as well as + * working around problems that some 32-bit compilers have with 64-bit + * constants. + */ +#define ACPI_UINT8_MAX (UINT8) (~((UINT8) 0)) /* 0xFF */ +#define ACPI_UINT16_MAX (UINT16)(~((UINT16) 0)) /* 0xFFFF */ +#define ACPI_UINT32_MAX (UINT32)(~((UINT32) 0)) /* 0xFFFFFFFF */ +#define ACPI_UINT64_MAX (UINT64)(~((UINT64) 0)) /* 0xFFFFFFFFFFFFFFFF */ +#define ACPI_ASCII_MAX 0x7F + + +/* + * Architecture-specific ACPICA Subsystem Data Types + * + * The goal of these types is to provide source code portability across + * 16-bit, 32-bit, and 64-bit targets. + * + * 1) The following types are of fixed size for all targets (16/32/64): + * + * BOOLEAN Logical boolean + * + * UINT8 8-bit (1 byte) unsigned value + * UINT16 16-bit (2 byte) unsigned value + * UINT32 32-bit (4 byte) unsigned value + * UINT64 64-bit (8 byte) unsigned value + * + * INT16 16-bit (2 byte) signed value + * INT32 32-bit (4 byte) signed value + * INT64 64-bit (8 byte) signed value + * + * COMPILER_DEPENDENT_UINT64/INT64 - These types are defined in the + * compiler-dependent header(s) and were introduced because there is no common + * 64-bit integer type across the various compilation models, as shown in + * the table below. + * + * Datatype LP64 ILP64 LLP64 ILP32 LP32 16bit + * char 8 8 8 8 8 8 + * short 16 16 16 16 16 16 + * _int32 32 + * int 32 64 32 32 16 16 + * long 64 64 32 32 32 32 + * long long 64 64 + * pointer 64 64 64 32 32 32 + * + * Note: ILP64 and LP32 are currently not supported. + * + * + * 2) These types represent the native word size of the target mode of the + * processor, and may be 16-bit, 32-bit, or 64-bit as required. They are + * usually used for memory allocation, efficient loop counters, and array + * indexes. The types are similar to the size_t type in the C library and are + * required because there is no C type that consistently represents the native + * data width. ACPI_SIZE is needed because there is no guarantee that a + * kernel-level C library is present. + * + * ACPI_SIZE 16/32/64-bit unsigned value + * ACPI_NATIVE_INT 16/32/64-bit signed value + */ + +/******************************************************************************* + * + * Common types for all compilers, all targets + * + ******************************************************************************/ + +typedef unsigned char BOOLEAN; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef COMPILER_DEPENDENT_UINT64 UINT64; +typedef COMPILER_DEPENDENT_INT64 INT64; + +/*! [End] no source code translation !*/ + +/* + * Value returned by AcpiOsGetThreadId. There is no standard "thread_id" + * across operating systems or even the various UNIX systems. Since ACPICA + * only needs the thread ID as a unique thread identifier, we use a UINT64 + * as the only common data type - it will accommodate any type of pointer or + * any type of integer. It is up to the host-dependent OSL to cast the + * native thread ID type to a UINT64 (in AcpiOsGetThreadId). + */ +#define ACPI_THREAD_ID UINT64 + + +/******************************************************************************* + * + * Types specific to 64-bit targets + * + ******************************************************************************/ + +#if ACPI_MACHINE_WIDTH == 64 + +/*! [Begin] no source code translation (keep the typedefs as-is) */ + +typedef unsigned int UINT32; +typedef int INT32; + +/*! [End] no source code translation !*/ + + +typedef INT64 ACPI_NATIVE_INT; +typedef UINT64 ACPI_SIZE; +typedef UINT64 ACPI_IO_ADDRESS; +typedef UINT64 ACPI_PHYSICAL_ADDRESS; + +#define ACPI_MAX_PTR ACPI_UINT64_MAX +#define ACPI_SIZE_MAX ACPI_UINT64_MAX +#define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */ + +/* + * In the case of the Itanium Processor Family (IPF), the hardware does not + * support misaligned memory transfers. Set the MISALIGNMENT_NOT_SUPPORTED flag + * to indicate that special precautions must be taken to avoid alignment faults. + * (IA64 or ia64 is currently used by existing compilers to indicate IPF.) + * + * Note: EM64T and other X86-64 processors support misaligned transfers, + * so there is no need to define this flag. + */ +#if defined (__IA64__) || defined (__ia64__) +#define ACPI_MISALIGNMENT_NOT_SUPPORTED +#endif + + +/******************************************************************************* + * + * Types specific to 32-bit targets + * + ******************************************************************************/ + +#elif ACPI_MACHINE_WIDTH == 32 + +/*! [Begin] no source code translation (keep the typedefs as-is) */ + +typedef unsigned int UINT32; +typedef int INT32; + +/*! [End] no source code translation !*/ + + +typedef INT32 ACPI_NATIVE_INT; +typedef UINT32 ACPI_SIZE; +typedef UINT32 ACPI_IO_ADDRESS; +typedef UINT32 ACPI_PHYSICAL_ADDRESS; + +#define ACPI_MAX_PTR ACPI_UINT32_MAX +#define ACPI_SIZE_MAX ACPI_UINT32_MAX + +#else + +/* ACPI_MACHINE_WIDTH must be either 64 or 32 */ + +#error unknown ACPI_MACHINE_WIDTH +#endif + + +/******************************************************************************* + * + * OS-dependent types + * + * If the defaults below are not appropriate for the host system, they can + * be defined in the OS-specific header, and this will take precedence. + * + ******************************************************************************/ + +/* Flags for AcpiOsAcquireLock/AcpiOsReleaseLock */ + +#ifndef ACPI_CPU_FLAGS +#define ACPI_CPU_FLAGS ACPI_SIZE +#endif + +/* Object returned from AcpiOsCreateCache */ + +#ifndef ACPI_CACHE_T +#ifdef ACPI_USE_LOCAL_CACHE +#define ACPI_CACHE_T ACPI_MEMORY_LIST +#else +#define ACPI_CACHE_T void * +#endif +#endif + +/* + * Synchronization objects - Mutexes, Semaphores, and SpinLocks + */ +#if (ACPI_MUTEX_TYPE == ACPI_BINARY_SEMAPHORE) +/* + * These macros are used if the host OS does not support a mutex object. + * Map the OSL Mutex interfaces to binary semaphores. + */ +#define ACPI_MUTEX ACPI_SEMAPHORE +#define AcpiOsCreateMutex(OutHandle) AcpiOsCreateSemaphore (1, 1, OutHandle) +#define AcpiOsDeleteMutex(Handle) (void) AcpiOsDeleteSemaphore (Handle) +#define AcpiOsAcquireMutex(Handle,Time) AcpiOsWaitSemaphore (Handle, 1, Time) +#define AcpiOsReleaseMutex(Handle) (void) AcpiOsSignalSemaphore (Handle, 1) +#endif + +/* Configurable types for synchronization objects */ + +#ifndef ACPI_SPINLOCK +#define ACPI_SPINLOCK void * +#endif + +#ifndef ACPI_SEMAPHORE +#define ACPI_SEMAPHORE void * +#endif + +#ifndef ACPI_MUTEX +#define ACPI_MUTEX void * +#endif + + +/******************************************************************************* + * + * Compiler-dependent types + * + * If the defaults below are not appropriate for the host compiler, they can + * be defined in the compiler-specific header, and this will take precedence. + * + ******************************************************************************/ + +/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */ + +#ifndef ACPI_UINTPTR_T +#define ACPI_UINTPTR_T void * +#endif + +/* + * ACPI_PRINTF_LIKE is used to tag functions as "printf-like" because + * some compilers can catch printf format string problems + */ +#ifndef ACPI_PRINTF_LIKE +#define ACPI_PRINTF_LIKE(c) +#endif + +/* + * Some compilers complain about unused variables. Sometimes we don't want to + * use all the variables (for example, _AcpiModuleName). This allows us + * to to tell the compiler in a per-variable manner that a variable + * is unused + */ +#ifndef ACPI_UNUSED_VAR +#define ACPI_UNUSED_VAR +#endif + +/* + * All ACPICA functions that are available to the rest of the kernel are + * tagged with this macro which can be defined as appropriate for the host. + */ +#ifndef ACPI_EXPORT_SYMBOL +#define ACPI_EXPORT_SYMBOL(Symbol) +#endif + + +/****************************************************************************** + * + * ACPI Specification constants (Do not change unless the specification changes) + * + *****************************************************************************/ + +/* Number of distinct FADT-based GPE register blocks (GPE0 and GPE1) */ + +#define ACPI_MAX_GPE_BLOCKS 2 + +/* Default ACPI register widths */ + +#define ACPI_GPE_REGISTER_WIDTH 8 +#define ACPI_PM1_REGISTER_WIDTH 16 +#define ACPI_PM2_REGISTER_WIDTH 8 +#define ACPI_PM_TIMER_WIDTH 32 + +/* Names within the namespace are 4 bytes long */ + +#define ACPI_NAME_SIZE 4 +#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ +#define ACPI_PATH_SEPARATOR '.' + +/* Sizes for ACPI table headers */ + +#define ACPI_OEM_ID_SIZE 6 +#define ACPI_OEM_TABLE_ID_SIZE 8 + +/* ACPI/PNP hardware IDs */ + +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08" + +/* PM Timer ticks per second (HZ) */ + +#define PM_TIMER_FREQUENCY 3579545 + + +/******************************************************************************* + * + * Independent types + * + ******************************************************************************/ + +/* Logical defines and NULL */ + +#ifdef FALSE +#undef FALSE +#endif +#define FALSE (1 == 0) + +#ifdef TRUE +#undef TRUE +#endif +#define TRUE (1 == 1) + +#ifndef NULL +#define NULL (void *) 0 +#endif + + +/* + * Miscellaneous types + */ +typedef UINT32 ACPI_STATUS; /* All ACPI Exceptions */ +typedef UINT32 ACPI_NAME; /* 4-byte ACPI name */ +typedef char * ACPI_STRING; /* Null terminated ASCII string */ +typedef void * ACPI_HANDLE; /* Actually a ptr to a NS Node */ + + +/* Owner IDs are used to track namespace nodes for selective deletion */ + +typedef UINT8 ACPI_OWNER_ID; +#define ACPI_OWNER_ID_MAX 0xFF + + +#define ACPI_INTEGER_BIT_SIZE 64 +#define ACPI_MAX_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */ +#define ACPI_MAX64_DECIMAL_DIGITS 20 +#define ACPI_MAX32_DECIMAL_DIGITS 10 +#define ACPI_MAX16_DECIMAL_DIGITS 5 +#define ACPI_MAX8_DECIMAL_DIGITS 3 + +/* + * Constants with special meanings + */ +#define ACPI_ROOT_OBJECT ACPI_ADD_PTR (ACPI_HANDLE, NULL, ACPI_MAX_PTR) +#define ACPI_WAIT_FOREVER 0xFFFF /* UINT16, as per ACPI spec */ +#define ACPI_DO_NOT_WAIT 0 + +/* + * Obsolete: Acpi integer width. In ACPI version 1 (1996), integers are 32 bits. + * In ACPI version 2 (2000) and later, integers are 64 bits. Note that this + * pertains to the ACPI integer type only, not to other integers used in the + * implementation of the ACPICA subsystem. + * + * 01/2010: This type is obsolete and has been removed from the entire ACPICA + * code base. It remains here for compatibility with device drivers that use + * the type. However, it will be removed in the future. + */ +typedef UINT64 ACPI_INTEGER; +#define ACPI_INTEGER_MAX ACPI_UINT64_MAX + + +/******************************************************************************* + * + * Commonly used macros + * + ******************************************************************************/ + +/* Data manipulation */ + +#define ACPI_LOBYTE(Integer) ((UINT8) (UINT16)(Integer)) +#define ACPI_HIBYTE(Integer) ((UINT8) (((UINT16)(Integer)) >> 8)) +#define ACPI_LOWORD(Integer) ((UINT16) (UINT32)(Integer)) +#define ACPI_HIWORD(Integer) ((UINT16)(((UINT32)(Integer)) >> 16)) +#define ACPI_LODWORD(Integer64) ((UINT32) (UINT64)(Integer64)) +#define ACPI_HIDWORD(Integer64) ((UINT32)(((UINT64)(Integer64)) >> 32)) + +#define ACPI_SET_BIT(target,bit) ((target) |= (bit)) +#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit)) +#define ACPI_MIN(a,b) (((a)<(b))?(a):(b)) +#define ACPI_MAX(a,b) (((a)>(b))?(a):(b)) + +/* Size calculation */ + +#define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) + +/* Pointer manipulation */ + +#define ACPI_CAST_PTR(t, p) ((t *) (ACPI_UINTPTR_T) (p)) +#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (ACPI_UINTPTR_T) (p)) +#define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (UINT8, (a)) + (ACPI_SIZE)(b))) +#define ACPI_PTR_DIFF(a, b) (ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b))) + +/* Pointer/Integer type conversions */ + +#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL,(ACPI_SIZE) i) +#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) NULL) +#define ACPI_OFFSET(d, f) (ACPI_SIZE) ACPI_PTR_DIFF (&(((d *)0)->f), (void *) NULL) +#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) +#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) + +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (UINT32, (a)) == *ACPI_CAST_PTR (UINT32, (b))) +#else +#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE)) +#endif + + +/******************************************************************************* + * + * Miscellaneous constants + * + ******************************************************************************/ + +/* + * Initialization sequence + */ +#define ACPI_FULL_INITIALIZATION 0x00 +#define ACPI_NO_ADDRESS_SPACE_INIT 0x01 +#define ACPI_NO_HARDWARE_INIT 0x02 +#define ACPI_NO_EVENT_INIT 0x04 +#define ACPI_NO_HANDLER_INIT 0x08 +#define ACPI_NO_ACPI_ENABLE 0x10 +#define ACPI_NO_DEVICE_INIT 0x20 +#define ACPI_NO_OBJECT_INIT 0x40 + +/* + * Initialization state + */ +#define ACPI_SUBSYSTEM_INITIALIZE 0x01 +#define ACPI_INITIALIZED_OK 0x02 + +/* + * Power state values + */ +#define ACPI_STATE_UNKNOWN (UINT8) 0xFF + +#define ACPI_STATE_S0 (UINT8) 0 +#define ACPI_STATE_S1 (UINT8) 1 +#define ACPI_STATE_S2 (UINT8) 2 +#define ACPI_STATE_S3 (UINT8) 3 +#define ACPI_STATE_S4 (UINT8) 4 +#define ACPI_STATE_S5 (UINT8) 5 +#define ACPI_S_STATES_MAX ACPI_STATE_S5 +#define ACPI_S_STATE_COUNT 6 + +#define ACPI_STATE_D0 (UINT8) 0 +#define ACPI_STATE_D1 (UINT8) 1 +#define ACPI_STATE_D2 (UINT8) 2 +#define ACPI_STATE_D3 (UINT8) 3 +#define ACPI_D_STATES_MAX ACPI_STATE_D3 +#define ACPI_D_STATE_COUNT 4 + +#define ACPI_STATE_C0 (UINT8) 0 +#define ACPI_STATE_C1 (UINT8) 1 +#define ACPI_STATE_C2 (UINT8) 2 +#define ACPI_STATE_C3 (UINT8) 3 +#define ACPI_C_STATES_MAX ACPI_STATE_C3 +#define ACPI_C_STATE_COUNT 4 + +/* + * Sleep type invalid value + */ +#define ACPI_SLEEP_TYPE_MAX 0x7 +#define ACPI_SLEEP_TYPE_INVALID 0xFF + +/* + * Standard notify values + */ +#define ACPI_NOTIFY_BUS_CHECK (UINT8) 0x00 +#define ACPI_NOTIFY_DEVICE_CHECK (UINT8) 0x01 +#define ACPI_NOTIFY_DEVICE_WAKE (UINT8) 0x02 +#define ACPI_NOTIFY_EJECT_REQUEST (UINT8) 0x03 +#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (UINT8) 0x04 +#define ACPI_NOTIFY_FREQUENCY_MISMATCH (UINT8) 0x05 +#define ACPI_NOTIFY_BUS_MODE_MISMATCH (UINT8) 0x06 +#define ACPI_NOTIFY_POWER_FAULT (UINT8) 0x07 +#define ACPI_NOTIFY_CAPABILITIES_CHECK (UINT8) 0x08 +#define ACPI_NOTIFY_DEVICE_PLD_CHECK (UINT8) 0x09 +#define ACPI_NOTIFY_RESERVED (UINT8) 0x0A +#define ACPI_NOTIFY_LOCALITY_UPDATE (UINT8) 0x0B +#define ACPI_NOTIFY_SHUTDOWN_REQUEST (UINT8) 0x0C + +#define ACPI_NOTIFY_MAX 0x0C + +/* + * Types associated with ACPI names and objects. The first group of + * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition + * of the ACPI ObjectType() operator (See the ACPI Spec). Therefore, + * only add to the first group if the spec changes. + * + * NOTE: Types must be kept in sync with the global AcpiNsProperties + * and AcpiNsTypeNames arrays. + */ +typedef UINT32 ACPI_OBJECT_TYPE; + +#define ACPI_TYPE_ANY 0x00 +#define ACPI_TYPE_INTEGER 0x01 /* Byte/Word/Dword/Zero/One/Ones */ +#define ACPI_TYPE_STRING 0x02 +#define ACPI_TYPE_BUFFER 0x03 +#define ACPI_TYPE_PACKAGE 0x04 /* ByteConst, multiple DataTerm/Constant/SuperName */ +#define ACPI_TYPE_FIELD_UNIT 0x05 +#define ACPI_TYPE_DEVICE 0x06 /* Name, multiple Node */ +#define ACPI_TYPE_EVENT 0x07 +#define ACPI_TYPE_METHOD 0x08 /* Name, ByteConst, multiple Code */ +#define ACPI_TYPE_MUTEX 0x09 +#define ACPI_TYPE_REGION 0x0A +#define ACPI_TYPE_POWER 0x0B /* Name,ByteConst,WordConst,multi Node */ +#define ACPI_TYPE_PROCESSOR 0x0C /* Name,ByteConst,DWordConst,ByteConst,multi NmO */ +#define ACPI_TYPE_THERMAL 0x0D /* Name, multiple Node */ +#define ACPI_TYPE_BUFFER_FIELD 0x0E +#define ACPI_TYPE_DDB_HANDLE 0x0F +#define ACPI_TYPE_DEBUG_OBJECT 0x10 + +#define ACPI_TYPE_EXTERNAL_MAX 0x10 + +/* + * These are object types that do not map directly to the ACPI + * ObjectType() operator. They are used for various internal purposes only. + * If new predefined ACPI_TYPEs are added (via the ACPI specification), these + * internal types must move upwards. (There is code that depends on these + * values being contiguous with the external types above.) + */ +#define ACPI_TYPE_LOCAL_REGION_FIELD 0x11 +#define ACPI_TYPE_LOCAL_BANK_FIELD 0x12 +#define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13 +#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, RefOf, Index */ +#define ACPI_TYPE_LOCAL_ALIAS 0x15 +#define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16 +#define ACPI_TYPE_LOCAL_NOTIFY 0x17 +#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18 +#define ACPI_TYPE_LOCAL_RESOURCE 0x19 +#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A +#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple ObjectList Nodes */ + +#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */ + +/* + * These are special object types that never appear in + * a Namespace node, only in an ACPI_OPERAND_OBJECT + */ +#define ACPI_TYPE_LOCAL_EXTRA 0x1C +#define ACPI_TYPE_LOCAL_DATA 0x1D + +#define ACPI_TYPE_LOCAL_MAX 0x1D + +/* All types above here are invalid */ + +#define ACPI_TYPE_INVALID 0x1E +#define ACPI_TYPE_NOT_FOUND 0xFF + +#define ACPI_NUM_NS_TYPES (ACPI_TYPE_INVALID + 1) + + +/* + * All I/O + */ +#define ACPI_READ 0 +#define ACPI_WRITE 1 +#define ACPI_IO_MASK 1 + +/* + * Event Types: Fixed & General Purpose + */ +typedef UINT32 ACPI_EVENT_TYPE; + +/* + * Fixed events + */ +#define ACPI_EVENT_PMTIMER 0 +#define ACPI_EVENT_GLOBAL 1 +#define ACPI_EVENT_POWER_BUTTON 2 +#define ACPI_EVENT_SLEEP_BUTTON 3 +#define ACPI_EVENT_RTC 4 +#define ACPI_EVENT_MAX 4 +#define ACPI_NUM_FIXED_EVENTS ACPI_EVENT_MAX + 1 + +/* + * Event Status - Per event + * ------------- + * The encoding of ACPI_EVENT_STATUS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the event is enabled). + * +-------------+-+-+-+ + * | Bits 31:3 |2|1|0| + * +-------------+-+-+-+ + * | | | | + * | | | +- Enabled? + * | | +--- Enabled for wake? + * | +----- Set? + * +----------- + */ +typedef UINT32 ACPI_EVENT_STATUS; + +#define ACPI_EVENT_FLAG_DISABLED (ACPI_EVENT_STATUS) 0x00 +#define ACPI_EVENT_FLAG_ENABLED (ACPI_EVENT_STATUS) 0x01 +#define ACPI_EVENT_FLAG_WAKE_ENABLED (ACPI_EVENT_STATUS) 0x02 +#define ACPI_EVENT_FLAG_SET (ACPI_EVENT_STATUS) 0x04 + +/* + * General Purpose Events (GPE) + */ +#define ACPI_GPE_INVALID 0xFF +#define ACPI_GPE_MAX 0xFF +#define ACPI_NUM_GPE 256 + +/* Actions for AcpiSetGpe, AcpiGpeWakeup, AcpiHwLowSetGpe */ + +#define ACPI_GPE_ENABLE 0 +#define ACPI_GPE_DISABLE 1 +#define ACPI_GPE_CONDITIONAL_ENABLE 2 + +/* + * GPE info flags - Per GPE + * +-------+-+-+---+ + * | 7:4 |3|2|1:0| + * +-------+-+-+---+ + * | | | | + * | | | +-- Type of dispatch:to method, handler, notify, or none + * | | +----- Interrupt type: edge or level triggered + * | +------- Is a Wake GPE + * +------------ + */ +#define ACPI_GPE_DISPATCH_NONE (UINT8) 0x00 +#define ACPI_GPE_DISPATCH_METHOD (UINT8) 0x01 +#define ACPI_GPE_DISPATCH_HANDLER (UINT8) 0x02 +#define ACPI_GPE_DISPATCH_NOTIFY (UINT8) 0x03 +#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x03 + +#define ACPI_GPE_LEVEL_TRIGGERED (UINT8) 0x04 +#define ACPI_GPE_EDGE_TRIGGERED (UINT8) 0x00 +#define ACPI_GPE_XRUPT_TYPE_MASK (UINT8) 0x04 + +#define ACPI_GPE_CAN_WAKE (UINT8) 0x08 + +/* + * Flags for GPE and Lock interfaces + */ +#define ACPI_NOT_ISR 0x1 +#define ACPI_ISR 0x0 + + +/* Notify types */ + +#define ACPI_SYSTEM_NOTIFY 0x1 +#define ACPI_DEVICE_NOTIFY 0x2 +#define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY) +#define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 + +#define ACPI_MAX_SYS_NOTIFY 0x7F +#define ACPI_MAX_DEVICE_SPECIFIC_NOTIFY 0xBF + + +/* Address Space (Operation Region) Types */ + +typedef UINT8 ACPI_ADR_SPACE_TYPE; + +#define ACPI_ADR_SPACE_SYSTEM_MEMORY (ACPI_ADR_SPACE_TYPE) 0 +#define ACPI_ADR_SPACE_SYSTEM_IO (ACPI_ADR_SPACE_TYPE) 1 +#define ACPI_ADR_SPACE_PCI_CONFIG (ACPI_ADR_SPACE_TYPE) 2 +#define ACPI_ADR_SPACE_EC (ACPI_ADR_SPACE_TYPE) 3 +#define ACPI_ADR_SPACE_SMBUS (ACPI_ADR_SPACE_TYPE) 4 +#define ACPI_ADR_SPACE_CMOS (ACPI_ADR_SPACE_TYPE) 5 +#define ACPI_ADR_SPACE_PCI_BAR_TARGET (ACPI_ADR_SPACE_TYPE) 6 +#define ACPI_ADR_SPACE_IPMI (ACPI_ADR_SPACE_TYPE) 7 +#define ACPI_ADR_SPACE_GPIO (ACPI_ADR_SPACE_TYPE) 8 +#define ACPI_ADR_SPACE_GSBUS (ACPI_ADR_SPACE_TYPE) 9 + +#define ACPI_NUM_PREDEFINED_REGIONS 10 + +/* + * Special Address Spaces + * + * Note: A Data Table region is a special type of operation region + * that has its own AML opcode. However, internally, the AML + * interpreter simply creates an operation region with an an address + * space type of ACPI_ADR_SPACE_DATA_TABLE. + */ +#define ACPI_ADR_SPACE_DATA_TABLE (ACPI_ADR_SPACE_TYPE) 0x7E /* Internal to ACPICA only */ +#define ACPI_ADR_SPACE_FIXED_HARDWARE (ACPI_ADR_SPACE_TYPE) 0x7F + +/* Values for _REG connection code */ + +#define ACPI_REG_DISCONNECT 0 +#define ACPI_REG_CONNECT 1 + +/* + * BitRegister IDs + * + * These values are intended to be used by the hardware interfaces + * and are mapped to individual bitfields defined within the ACPI + * registers. See the AcpiGbl_BitRegisterInfo global table in utglobal.c + * for this mapping. + */ + +/* PM1 Status register */ + +#define ACPI_BITREG_TIMER_STATUS 0x00 +#define ACPI_BITREG_BUS_MASTER_STATUS 0x01 +#define ACPI_BITREG_GLOBAL_LOCK_STATUS 0x02 +#define ACPI_BITREG_POWER_BUTTON_STATUS 0x03 +#define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04 +#define ACPI_BITREG_RT_CLOCK_STATUS 0x05 +#define ACPI_BITREG_WAKE_STATUS 0x06 +#define ACPI_BITREG_PCIEXP_WAKE_STATUS 0x07 + +/* PM1 Enable register */ + +#define ACPI_BITREG_TIMER_ENABLE 0x08 +#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x09 +#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x0A +#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0B +#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0C +#define ACPI_BITREG_PCIEXP_WAKE_DISABLE 0x0D + +/* PM1 Control register */ + +#define ACPI_BITREG_SCI_ENABLE 0x0E +#define ACPI_BITREG_BUS_MASTER_RLD 0x0F +#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x10 +#define ACPI_BITREG_SLEEP_TYPE 0x11 +#define ACPI_BITREG_SLEEP_ENABLE 0x12 + +/* PM2 Control register */ + +#define ACPI_BITREG_ARB_DISABLE 0x13 + +#define ACPI_BITREG_MAX 0x13 +#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 + + +/* Status register values. A 1 clears a status bit. 0 = no effect */ + +#define ACPI_CLEAR_STATUS 1 + +/* Enable and Control register values */ + +#define ACPI_ENABLE_EVENT 1 +#define ACPI_DISABLE_EVENT 0 + + +/* Sleep function dispatch */ + +typedef ACPI_STATUS (*ACPI_SLEEP_FUNCTION) ( + UINT8 SleepState); + +typedef struct acpi_sleep_functions +{ + ACPI_SLEEP_FUNCTION LegacyFunction; + ACPI_SLEEP_FUNCTION ExtendedFunction; + +} ACPI_SLEEP_FUNCTIONS; + + +/* + * External ACPI object definition + */ + +/* + * Note: Type == ACPI_TYPE_ANY (0) is used to indicate a NULL package element + * or an unresolved named reference. + */ +typedef union acpi_object +{ + ACPI_OBJECT_TYPE Type; /* See definition of AcpiNsType for values */ + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_INTEGER */ + UINT64 Value; /* The actual number */ + } Integer; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_STRING */ + UINT32 Length; /* # of bytes in string, excluding trailing null */ + char *Pointer; /* points to the string value */ + } String; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_BUFFER */ + UINT32 Length; /* # of bytes in buffer */ + UINT8 *Pointer; /* points to the buffer */ + } Buffer; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_PACKAGE */ + UINT32 Count; /* # of elements in package */ + union acpi_object *Elements; /* Pointer to an array of ACPI_OBJECTs */ + } Package; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_LOCAL_REFERENCE */ + ACPI_OBJECT_TYPE ActualType; /* Type associated with the Handle */ + ACPI_HANDLE Handle; /* object reference */ + } Reference; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_PROCESSOR */ + UINT32 ProcId; + ACPI_IO_ADDRESS PblkAddress; + UINT32 PblkLength; + } Processor; + + struct + { + ACPI_OBJECT_TYPE Type; /* ACPI_TYPE_POWER */ + UINT32 SystemLevel; + UINT32 ResourceOrder; + } PowerResource; + +} ACPI_OBJECT; + + +/* + * List of objects, used as a parameter list for control method evaluation + */ +typedef struct acpi_object_list +{ + UINT32 Count; + ACPI_OBJECT *Pointer; + +} ACPI_OBJECT_LIST; + + +/* + * Miscellaneous common Data Structures used by the interfaces + */ +#define ACPI_NO_BUFFER 0 +#define ACPI_ALLOCATE_BUFFER (ACPI_SIZE) (-1) +#define ACPI_ALLOCATE_LOCAL_BUFFER (ACPI_SIZE) (-2) + +typedef struct acpi_buffer +{ + ACPI_SIZE Length; /* Length in bytes of the buffer */ + void *Pointer; /* pointer to buffer */ + +} ACPI_BUFFER; + + +/* + * NameType for AcpiGetName + */ +#define ACPI_FULL_PATHNAME 0 +#define ACPI_SINGLE_NAME 1 +#define ACPI_NAME_TYPE_MAX 1 + + +/* + * Predefined Namespace items + */ +typedef struct acpi_predefined_names +{ + char *Name; + UINT8 Type; + char *Val; + +} ACPI_PREDEFINED_NAMES; + + +/* + * Structure and flags for AcpiGetSystemInfo + */ +#define ACPI_SYS_MODE_UNKNOWN 0x0000 +#define ACPI_SYS_MODE_ACPI 0x0001 +#define ACPI_SYS_MODE_LEGACY 0x0002 +#define ACPI_SYS_MODES_MASK 0x0003 + + +/* + * System info returned by AcpiGetSystemInfo() + */ +typedef struct acpi_system_info +{ + UINT32 AcpiCaVersion; + UINT32 Flags; + UINT32 TimerResolution; + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 DebugLevel; + UINT32 DebugLayer; + +} ACPI_SYSTEM_INFO; + + +/* + * System statistics returned by AcpiGetStatistics() + */ +typedef struct acpi_statistics +{ + UINT32 SciCount; + UINT32 GpeCount; + UINT32 FixedEventCount[ACPI_NUM_FIXED_EVENTS]; + UINT32 MethodCount; + +} ACPI_STATISTICS; + + +/* Table Event Types */ + +#define ACPI_TABLE_EVENT_LOAD 0x0 +#define ACPI_TABLE_EVENT_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 + + +/* + * Types specific to the OS service interfaces + */ +typedef UINT32 +(ACPI_SYSTEM_XFACE *ACPI_OSD_HANDLER) ( + void *Context); + +typedef void +(ACPI_SYSTEM_XFACE *ACPI_OSD_EXEC_CALLBACK) ( + void *Context); + +/* + * Various handlers and callback procedures + */ +typedef +void (*ACPI_GBL_EVENT_HANDLER) ( + UINT32 EventType, + ACPI_HANDLE Device, + UINT32 EventNumber, + void *Context); + +#define ACPI_EVENT_TYPE_GPE 0 +#define ACPI_EVENT_TYPE_FIXED 1 + +typedef +UINT32 (*ACPI_EVENT_HANDLER) ( + void *Context); + +typedef +UINT32 (*ACPI_GPE_HANDLER) ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + void *Context); + +typedef +void (*ACPI_NOTIFY_HANDLER) ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context); + +typedef +void (*ACPI_OBJECT_HANDLER) ( + ACPI_HANDLE Object, + void *Data); + +typedef +ACPI_STATUS (*ACPI_INIT_HANDLER) ( + ACPI_HANDLE Object, + UINT32 Function); + +#define ACPI_INIT_DEVICE_INI 1 + +typedef +ACPI_STATUS (*ACPI_EXCEPTION_HANDLER) ( + ACPI_STATUS AmlStatus, + ACPI_NAME Name, + UINT16 Opcode, + UINT32 AmlOffset, + void *Context); + +/* Table Event handler (Load, LoadTable, etc.) and types */ + +typedef +ACPI_STATUS (*ACPI_TABLE_HANDLER) ( + UINT32 Event, + void *Table, + void *Context); + +#define ACPI_TABLE_LOAD 0x0 +#define ACPI_TABLE_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 + + +/* Address Spaces (For Operation Regions) */ + +typedef +ACPI_STATUS (*ACPI_ADR_SPACE_HANDLER) ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +#define ACPI_DEFAULT_HANDLER NULL + +/* Special Context data for GenericSerialBus/GeneralPurposeIo (ACPI 5.0) */ + +typedef struct acpi_connection_info +{ + UINT8 *Connection; + UINT16 Length; + UINT8 AccessLength; + +} ACPI_CONNECTION_INFO; + + +typedef +ACPI_STATUS (*ACPI_ADR_SPACE_SETUP) ( + ACPI_HANDLE RegionHandle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +#define ACPI_REGION_ACTIVATE 0 +#define ACPI_REGION_DEACTIVATE 1 + +typedef +ACPI_STATUS (*ACPI_WALK_CALLBACK) ( + ACPI_HANDLE Object, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +typedef +UINT32 (*ACPI_INTERFACE_HANDLER) ( + ACPI_STRING InterfaceName, + UINT32 Supported); + + +/* Interrupt handler return values */ + +#define ACPI_INTERRUPT_NOT_HANDLED 0x00 +#define ACPI_INTERRUPT_HANDLED 0x01 + +/* GPE handler return values */ + +#define ACPI_REENABLE_GPE 0x80 + + +/* Length of 32-bit EISAID values when converted back to a string */ + +#define ACPI_EISAID_STRING_SIZE 8 /* Includes null terminator */ + +/* Length of UUID (string) values */ + +#define ACPI_UUID_LENGTH 16 + + +/* Structures used for device/processor HID, UID, CID */ + +typedef struct acpi_device_id +{ + UINT32 Length; /* Length of string + null */ + char *String; + +} ACPI_DEVICE_ID; + +typedef struct acpi_device_id_list +{ + UINT32 Count; /* Number of IDs in Ids array */ + UINT32 ListSize; /* Size of list, including ID strings */ + ACPI_DEVICE_ID Ids[1]; /* ID array */ + +} ACPI_DEVICE_ID_LIST; + +/* + * Structure returned from AcpiGetObjectInfo. + * Optimized for both 32- and 64-bit builds + */ +typedef struct acpi_device_info +{ + UINT32 InfoSize; /* Size of info, including ID strings */ + UINT32 Name; /* ACPI object Name */ + ACPI_OBJECT_TYPE Type; /* ACPI object Type */ + UINT8 ParamCount; /* If a method, required parameter count */ + UINT8 Valid; /* Indicates which optional fields are valid */ + UINT8 Flags; /* Miscellaneous info */ + UINT8 HighestDstates[4]; /* _SxD values: 0xFF indicates not valid */ + UINT8 LowestDstates[5]; /* _SxW values: 0xFF indicates not valid */ + UINT32 CurrentStatus; /* _STA value */ + UINT64 Address; /* _ADR value */ + ACPI_DEVICE_ID HardwareId; /* _HID value */ + ACPI_DEVICE_ID UniqueId; /* _UID value */ + ACPI_DEVICE_ID_LIST CompatibleIdList; /* _CID list */ + +} ACPI_DEVICE_INFO; + +/* Values for Flags field above (AcpiGetObjectInfo) */ + +#define ACPI_PCI_ROOT_BRIDGE 0x01 + +/* Flags for Valid field above (AcpiGetObjectInfo) */ + +#define ACPI_VALID_STA 0x01 +#define ACPI_VALID_ADR 0x02 +#define ACPI_VALID_HID 0x04 +#define ACPI_VALID_UID 0x08 +#define ACPI_VALID_CID 0x10 +#define ACPI_VALID_SXDS 0x20 +#define ACPI_VALID_SXWS 0x40 + +/* Flags for _STA method */ + +#define ACPI_STA_DEVICE_PRESENT 0x01 +#define ACPI_STA_DEVICE_ENABLED 0x02 +#define ACPI_STA_DEVICE_UI 0x04 +#define ACPI_STA_DEVICE_FUNCTIONING 0x08 +#define ACPI_STA_DEVICE_OK 0x08 /* Synonym */ +#define ACPI_STA_BATTERY_PRESENT 0x10 + + +/* Context structs for address space handlers */ + +typedef struct acpi_pci_id +{ + UINT16 Segment; + UINT16 Bus; + UINT16 Device; + UINT16 Function; + +} ACPI_PCI_ID; + +typedef struct acpi_mem_space_context +{ + UINT32 Length; + ACPI_PHYSICAL_ADDRESS Address; + ACPI_PHYSICAL_ADDRESS MappedPhysicalAddress; + UINT8 *MappedLogicalAddress; + ACPI_SIZE MappedLength; + +} ACPI_MEM_SPACE_CONTEXT; + + +/* + * ACPI_MEMORY_LIST is used only if the ACPICA local cache is enabled + */ +typedef struct acpi_memory_list +{ + char *ListName; + void *ListHead; + UINT16 ObjectSize; + UINT16 MaxDepth; + UINT16 CurrentDepth; + UINT16 LinkOffset; + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Statistics for debug memory tracking only */ + + UINT32 TotalAllocated; + UINT32 TotalFreed; + UINT32 MaxOccupied; + UINT32 TotalSize; + UINT32 CurrentTotalSize; + UINT32 Requests; + UINT32 Hits; +#endif + +} ACPI_MEMORY_LIST; + + +#endif /* __ACTYPES_H__ */ diff --git a/source/include/acutils.h b/source/include/acutils.h new file mode 100644 index 000000000000..e9c9b95dda1d --- /dev/null +++ b/source/include/acutils.h @@ -0,0 +1,984 @@ +/****************************************************************************** + * + * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACUTILS_H +#define _ACUTILS_H + + +extern const UINT8 AcpiGbl_ResourceAmlSizes[]; +extern const UINT8 AcpiGbl_ResourceAmlSerialBusSizes[]; + +/* Strings used by the disassembler and debugger resource dump routines */ + +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +extern const char *AcpiGbl_BmDecode[]; +extern const char *AcpiGbl_ConfigDecode[]; +extern const char *AcpiGbl_ConsumeDecode[]; +extern const char *AcpiGbl_DecDecode[]; +extern const char *AcpiGbl_HeDecode[]; +extern const char *AcpiGbl_IoDecode[]; +extern const char *AcpiGbl_LlDecode[]; +extern const char *AcpiGbl_MaxDecode[]; +extern const char *AcpiGbl_MemDecode[]; +extern const char *AcpiGbl_MinDecode[]; +extern const char *AcpiGbl_MtpDecode[]; +extern const char *AcpiGbl_RngDecode[]; +extern const char *AcpiGbl_RwDecode[]; +extern const char *AcpiGbl_ShrDecode[]; +extern const char *AcpiGbl_SizDecode[]; +extern const char *AcpiGbl_TrsDecode[]; +extern const char *AcpiGbl_TtpDecode[]; +extern const char *AcpiGbl_TypDecode[]; +extern const char *AcpiGbl_PpcDecode[]; +extern const char *AcpiGbl_IorDecode[]; +extern const char *AcpiGbl_DtsDecode[]; +extern const char *AcpiGbl_CtDecode[]; +extern const char *AcpiGbl_SbtDecode[]; +extern const char *AcpiGbl_AmDecode[]; +extern const char *AcpiGbl_SmDecode[]; +extern const char *AcpiGbl_WmDecode[]; +extern const char *AcpiGbl_CphDecode[]; +extern const char *AcpiGbl_CpoDecode[]; +extern const char *AcpiGbl_DpDecode[]; +extern const char *AcpiGbl_EdDecode[]; +extern const char *AcpiGbl_BpbDecode[]; +extern const char *AcpiGbl_SbDecode[]; +extern const char *AcpiGbl_FcDecode[]; +extern const char *AcpiGbl_PtDecode[]; +#endif + +/* Types for Resource descriptor entries */ + +#define ACPI_INVALID_RESOURCE 0 +#define ACPI_FIXED_LENGTH 1 +#define ACPI_VARIABLE_LENGTH 2 +#define ACPI_SMALL_VARIABLE_LENGTH 3 + +typedef +ACPI_STATUS (*ACPI_WALK_AML_CALLBACK) ( + UINT8 *Aml, + UINT32 Length, + UINT32 Offset, + UINT8 ResourceIndex, + void *Context); + +typedef +ACPI_STATUS (*ACPI_PKG_CALLBACK) ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + +typedef struct acpi_pkg_info +{ + UINT8 *FreeSpace; + ACPI_SIZE Length; + UINT32 ObjectSpace; + UINT32 NumPackages; + +} ACPI_PKG_INFO; + +#define REF_INCREMENT (UINT16) 0 +#define REF_DECREMENT (UINT16) 1 +#define REF_FORCE_DELETE (UINT16) 2 + +/* AcpiUtDumpBuffer */ + +#define DB_BYTE_DISPLAY 1 +#define DB_WORD_DISPLAY 2 +#define DB_DWORD_DISPLAY 4 +#define DB_QWORD_DISPLAY 8 + +/* + * utglobal - Global data structures and procedures + */ +ACPI_STATUS +AcpiUtInitGlobals ( + void); + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +char * +AcpiUtGetMutexName ( + UINT32 MutexId); + +const char * +AcpiUtGetNotifyName ( + UINT32 NotifyValue); + +#endif + +char * +AcpiUtGetTypeName ( + ACPI_OBJECT_TYPE Type); + +char * +AcpiUtGetNodeName ( + void *Object); + +char * +AcpiUtGetDescriptorName ( + void *Object); + +const char * +AcpiUtGetReferenceName ( + ACPI_OPERAND_OBJECT *Object); + +char * +AcpiUtGetObjectTypeName ( + ACPI_OPERAND_OBJECT *ObjDesc); + +char * +AcpiUtGetRegionName ( + UINT8 SpaceId); + +char * +AcpiUtGetEventName ( + UINT32 EventId); + +char +AcpiUtHexToAsciiChar ( + UINT64 Integer, + UINT32 Position); + +BOOLEAN +AcpiUtValidObjectType ( + ACPI_OBJECT_TYPE Type); + + +/* + * utinit - miscellaneous initialization and shutdown + */ +ACPI_STATUS +AcpiUtHardwareInitialize ( + void); + +void +AcpiUtSubsystemShutdown ( + void); + + +/* + * utclib - Local implementations of C library functions + */ +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +ACPI_SIZE +AcpiUtStrlen ( + const char *String); + +char * +AcpiUtStrcpy ( + char *DstString, + const char *SrcString); + +char * +AcpiUtStrncpy ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +int +AcpiUtMemcmp ( + const char *Buffer1, + const char *Buffer2, + ACPI_SIZE Count); + +int +AcpiUtStrncmp ( + const char *String1, + const char *String2, + ACPI_SIZE Count); + +int +AcpiUtStrcmp ( + const char *String1, + const char *String2); + +char * +AcpiUtStrcat ( + char *DstString, + const char *SrcString); + +char * +AcpiUtStrncat ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +UINT32 +AcpiUtStrtoul ( + const char *String, + char **Terminator, + UINT32 Base); + +char * +AcpiUtStrstr ( + char *String1, + char *String2); + +void * +AcpiUtMemcpy ( + void *Dest, + const void *Src, + ACPI_SIZE Count); + +void * +AcpiUtMemset ( + void *Dest, + UINT8 Value, + ACPI_SIZE Count); + +int +AcpiUtToUpper ( + int c); + +int +AcpiUtToLower ( + int c); + +extern const UINT8 _acpi_ctype[]; + +#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ +#define _ACPI_XS 0x40 /* extra space */ +#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ +#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ +#define _ACPI_DI 0x04 /* '0'-'9' */ +#define _ACPI_LO 0x02 /* 'a'-'z' */ +#define _ACPI_PU 0x10 /* punctuation */ +#define _ACPI_SP 0x08 /* space */ +#define _ACPI_UP 0x01 /* 'A'-'Z' */ +#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ + +#define ACPI_IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) +#define ACPI_IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) +#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) +#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) +#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) +#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) +#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) + +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) + + +/* + * utcopy - Object construction and conversion interfaces + */ +ACPI_STATUS +AcpiUtBuildSimpleObject( + ACPI_OPERAND_OBJECT *Obj, + ACPI_OBJECT *UserObj, + UINT8 *DataSpace, + UINT32 *BufferSpaceUsed); + +ACPI_STATUS +AcpiUtBuildPackageObject ( + ACPI_OPERAND_OBJECT *Obj, + UINT8 *Buffer, + UINT32 *SpaceUsed); + +ACPI_STATUS +AcpiUtCopyIobjectToEobject ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_BUFFER *RetBuffer); + +ACPI_STATUS +AcpiUtCopyEobjectToIobject ( + ACPI_OBJECT *Obj, + ACPI_OPERAND_OBJECT **InternalObj); + +ACPI_STATUS +AcpiUtCopyISimpleToIsimple ( + ACPI_OPERAND_OBJECT *SourceObj, + ACPI_OPERAND_OBJECT *DestObj); + +ACPI_STATUS +AcpiUtCopyIobjectToIobject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **DestDesc, + ACPI_WALK_STATE *WalkState); + + +/* + * utcreate - Object creation + */ +ACPI_STATUS +AcpiUtUpdateObjectReference ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action); + + +/* + * utdebug - Debug interfaces + */ +void +AcpiUtInitStackPtrTrace ( + void); + +void +AcpiUtTrackStackPtr ( + void); + +void +AcpiUtTrace ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId); + +void +AcpiUtTracePtr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + void *Pointer); + +void +AcpiUtTraceU32 ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT32 Integer); + +void +AcpiUtTraceStr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + char *String); + +void +AcpiUtExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId); + +void +AcpiUtStatusExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + ACPI_STATUS Status); + +void +AcpiUtValueExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT64 Value); + +void +AcpiUtPtrExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT8 *Ptr); + +void +AcpiUtDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 componentId); + +void +AcpiUtDumpBuffer2 ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display); + +void +AcpiUtReportError ( + char *ModuleName, + UINT32 LineNumber); + +void +AcpiUtReportInfo ( + char *ModuleName, + UINT32 LineNumber); + +void +AcpiUtReportWarning ( + char *ModuleName, + UINT32 LineNumber); + +/* + * utdelete - Object deletion and reference counts + */ +void +AcpiUtAddReference ( + ACPI_OPERAND_OBJECT *Object); + +void +AcpiUtRemoveReference ( + ACPI_OPERAND_OBJECT *Object); + +void +AcpiUtDeleteInternalPackageObject ( + ACPI_OPERAND_OBJECT *Object); + +void +AcpiUtDeleteInternalSimpleObject ( + ACPI_OPERAND_OBJECT *Object); + +void +AcpiUtDeleteInternalObjectList ( + ACPI_OPERAND_OBJECT **ObjList); + + +/* + * uteval - object evaluation + */ +ACPI_STATUS +AcpiUtEvaluateObject ( + ACPI_NAMESPACE_NODE *PrefixNode, + char *Path, + UINT32 ExpectedReturnBtypes, + ACPI_OPERAND_OBJECT **ReturnDesc); + +ACPI_STATUS +AcpiUtEvaluateNumericObject ( + char *ObjectName, + ACPI_NAMESPACE_NODE *DeviceNode, + UINT64 *Value); + +ACPI_STATUS +AcpiUtExecute_STA ( + ACPI_NAMESPACE_NODE *DeviceNode, + UINT32 *StatusFlags); + +ACPI_STATUS +AcpiUtExecutePowerMethods ( + ACPI_NAMESPACE_NODE *DeviceNode, + const char **MethodNames, + UINT8 MethodCount, + UINT8 *OutValues); + + +/* + * utids - device ID support + */ +ACPI_STATUS +AcpiUtExecute_HID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId); + +ACPI_STATUS +AcpiUtExecute_UID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId); + +ACPI_STATUS +AcpiUtExecute_CID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID_LIST **ReturnCidList); + + +/* + * utlock - reader/writer locks + */ +ACPI_STATUS +AcpiUtCreateRwLock ( + ACPI_RW_LOCK *Lock); + +void +AcpiUtDeleteRwLock ( + ACPI_RW_LOCK *Lock); + +ACPI_STATUS +AcpiUtAcquireReadLock ( + ACPI_RW_LOCK *Lock); + +ACPI_STATUS +AcpiUtReleaseReadLock ( + ACPI_RW_LOCK *Lock); + +ACPI_STATUS +AcpiUtAcquireWriteLock ( + ACPI_RW_LOCK *Lock); + +void +AcpiUtReleaseWriteLock ( + ACPI_RW_LOCK *Lock); + + +/* + * utobject - internal object create/delete/cache routines + */ +ACPI_OPERAND_OBJECT * +AcpiUtCreateInternalObjectDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId, + ACPI_OBJECT_TYPE Type); + +void * +AcpiUtAllocateObjectDescDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId); + +#define AcpiUtCreateInternalObject(t) AcpiUtCreateInternalObjectDbg (_AcpiModuleName,__LINE__,_COMPONENT,t) +#define AcpiUtAllocateObjectDesc() AcpiUtAllocateObjectDescDbg (_AcpiModuleName,__LINE__,_COMPONENT) + +void +AcpiUtDeleteObjectDesc ( + ACPI_OPERAND_OBJECT *Object); + +BOOLEAN +AcpiUtValidInternalObject ( + void *Object); + +ACPI_OPERAND_OBJECT * +AcpiUtCreatePackageObject ( + UINT32 Count); + +ACPI_OPERAND_OBJECT * +AcpiUtCreateIntegerObject ( + UINT64 Value); + +ACPI_OPERAND_OBJECT * +AcpiUtCreateBufferObject ( + ACPI_SIZE BufferSize); + +ACPI_OPERAND_OBJECT * +AcpiUtCreateStringObject ( + ACPI_SIZE StringSize); + +ACPI_STATUS +AcpiUtGetObjectSize( + ACPI_OPERAND_OBJECT *Obj, + ACPI_SIZE *ObjLength); + + +/* + * utosi - Support for the _OSI predefined control method + */ +ACPI_STATUS +AcpiUtInitializeInterfaces ( + void); + +void +AcpiUtInterfaceTerminate ( + void); + +ACPI_STATUS +AcpiUtInstallInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiUtRemoveInterface ( + ACPI_STRING InterfaceName); + +ACPI_INTERFACE_INFO * +AcpiUtGetInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiUtOsiImplementation ( + ACPI_WALK_STATE *WalkState); + + +/* + * utstate - Generic state creation/cache routines + */ +void +AcpiUtPushGenericState ( + ACPI_GENERIC_STATE **ListHead, + ACPI_GENERIC_STATE *State); + +ACPI_GENERIC_STATE * +AcpiUtPopGenericState ( + ACPI_GENERIC_STATE **ListHead); + + +ACPI_GENERIC_STATE * +AcpiUtCreateGenericState ( + void); + +ACPI_THREAD_STATE * +AcpiUtCreateThreadState ( + void); + +ACPI_GENERIC_STATE * +AcpiUtCreateUpdateState ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action); + +ACPI_GENERIC_STATE * +AcpiUtCreatePkgState ( + void *InternalObject, + void *ExternalObject, + UINT16 Index); + +ACPI_STATUS +AcpiUtCreateUpdateStateAndPush ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action, + ACPI_GENERIC_STATE **StateList); + +ACPI_STATUS +AcpiUtCreatePkgStateAndPush ( + void *InternalObject, + void *ExternalObject, + UINT16 Index, + ACPI_GENERIC_STATE **StateList); + +ACPI_GENERIC_STATE * +AcpiUtCreateControlState ( + void); + +void +AcpiUtDeleteGenericState ( + ACPI_GENERIC_STATE *State); + + +/* + * utmath + */ +ACPI_STATUS +AcpiUtDivide ( + UINT64 InDividend, + UINT64 InDivisor, + UINT64 *OutQuotient, + UINT64 *OutRemainder); + +ACPI_STATUS +AcpiUtShortDivide ( + UINT64 InDividend, + UINT32 Divisor, + UINT64 *OutQuotient, + UINT32 *OutRemainder); + +/* + * utmisc + */ +const char * +AcpiUtValidateException ( + ACPI_STATUS Status); + +BOOLEAN +AcpiUtIsPciRootBridge ( + char *Id); + +BOOLEAN +AcpiUtIsAmlTable ( + ACPI_TABLE_HEADER *Table); + +ACPI_STATUS +AcpiUtAllocateOwnerId ( + ACPI_OWNER_ID *OwnerId); + +void +AcpiUtReleaseOwnerId ( + ACPI_OWNER_ID *OwnerId); + +ACPI_STATUS +AcpiUtWalkPackageTree ( + ACPI_OPERAND_OBJECT *SourceObject, + void *TargetObject, + ACPI_PKG_CALLBACK WalkCallback, + void *Context); + +void +AcpiUtStrupr ( + char *SrcString); + +void +AcpiUtStrlwr ( + char *SrcString); + +int +AcpiUtStricmp ( + char *String1, + char *String2); + +void +AcpiUtPrintString ( + char *String, + UINT8 MaxLength); + +BOOLEAN +AcpiUtValidAcpiName ( + UINT32 Name); + +void +AcpiUtRepairName ( + char *Name); + +BOOLEAN +AcpiUtValidAcpiChar ( + char Character, + UINT32 Position); + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger); + +/* Values for Base above (16=Hex, 10=Decimal) */ + +#define ACPI_ANY_BASE 0 + +UINT32 +AcpiUtDwordByteSwap ( + UINT32 Value); + +void +AcpiUtSetIntegerWidth ( + UINT8 Revision); + +#ifdef ACPI_DEBUG_OUTPUT +void +AcpiUtDisplayInitPathname ( + UINT8 Type, + ACPI_NAMESPACE_NODE *ObjHandle, + char *Path); +#endif + + +/* + * utresrc + */ +ACPI_STATUS +AcpiUtWalkAmlResources ( + UINT8 *Aml, + ACPI_SIZE AmlLength, + ACPI_WALK_AML_CALLBACK UserFunction, + void *Context); + +ACPI_STATUS +AcpiUtValidateResource ( + void *Aml, + UINT8 *ReturnIndex); + +UINT32 +AcpiUtGetDescriptorLength ( + void *Aml); + +UINT16 +AcpiUtGetResourceLength ( + void *Aml); + +UINT8 +AcpiUtGetResourceHeaderLength ( + void *Aml); + +UINT8 +AcpiUtGetResourceType ( + void *Aml); + +ACPI_STATUS +AcpiUtGetResourceEndTag ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 **EndTag); + + +/* + * utmutex - mutex support + */ +ACPI_STATUS +AcpiUtMutexInitialize ( + void); + +void +AcpiUtMutexTerminate ( + void); + +ACPI_STATUS +AcpiUtAcquireMutex ( + ACPI_MUTEX_HANDLE MutexId); + +ACPI_STATUS +AcpiUtReleaseMutex ( + ACPI_MUTEX_HANDLE MutexId); + + +/* + * utalloc - memory allocation and object caching + */ +ACPI_STATUS +AcpiUtCreateCaches ( + void); + +ACPI_STATUS +AcpiUtDeleteCaches ( + void); + +ACPI_STATUS +AcpiUtValidateBuffer ( + ACPI_BUFFER *Buffer); + +ACPI_STATUS +AcpiUtInitializeBuffer ( + ACPI_BUFFER *Buffer, + ACPI_SIZE RequiredLength); + +void * +AcpiUtAllocate ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line); + +void * +AcpiUtAllocateZeroed ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +void * +AcpiUtAllocateAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line); + +void * +AcpiUtAllocateZeroedAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line); + +void +AcpiUtFreeAndTrack ( + void *Address, + UINT32 Component, + const char *Module, + UINT32 Line); + +void +AcpiUtDumpAllocationInfo ( + void); + +void +AcpiUtDumpAllocations ( + UINT32 Component, + const char *Module); + +ACPI_STATUS +AcpiUtCreateList ( + char *ListName, + UINT16 ObjectSize, + ACPI_MEMORY_LIST **ReturnCache); + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + +/* + * utaddress - address range check + */ +ACPI_STATUS +AcpiUtAddAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + ACPI_NAMESPACE_NODE *RegionNode); + +void +AcpiUtRemoveAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_NAMESPACE_NODE *RegionNode); + +UINT32 +AcpiUtCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + BOOLEAN Warn); + +void +AcpiUtDeleteAddressLists ( + void); + +/* + * utxferror - various error/warning output functions + */ +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedWarning ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...); + +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedInfo ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...); + +void +AcpiUtNamespaceError ( + const char *ModuleName, + UINT32 LineNumber, + const char *InternalName, + ACPI_STATUS LookupStatus); + +void +AcpiUtMethodError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Message, + ACPI_NAMESPACE_NODE *Node, + const char *Path, + ACPI_STATUS LookupStatus); + +#endif /* _ACUTILS_H */ diff --git a/source/include/amlcode.h b/source/include/amlcode.h new file mode 100644 index 000000000000..f778bb07805b --- /dev/null +++ b/source/include/amlcode.h @@ -0,0 +1,512 @@ +/****************************************************************************** + * + * Name: amlcode.h - Definitions for AML, as included in "definition blocks" + * Declarations and definitions contained herein are derived + * directly from the ACPI specification. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __AMLCODE_H__ +#define __AMLCODE_H__ + +/* primary opcodes */ + +#define AML_NULL_CHAR (UINT16) 0x00 + +#define AML_ZERO_OP (UINT16) 0x00 +#define AML_ONE_OP (UINT16) 0x01 +#define AML_UNASSIGNED (UINT16) 0x02 +#define AML_ALIAS_OP (UINT16) 0x06 +#define AML_NAME_OP (UINT16) 0x08 +#define AML_BYTE_OP (UINT16) 0x0a +#define AML_WORD_OP (UINT16) 0x0b +#define AML_DWORD_OP (UINT16) 0x0c +#define AML_STRING_OP (UINT16) 0x0d +#define AML_QWORD_OP (UINT16) 0x0e /* ACPI 2.0 */ +#define AML_SCOPE_OP (UINT16) 0x10 +#define AML_BUFFER_OP (UINT16) 0x11 +#define AML_PACKAGE_OP (UINT16) 0x12 +#define AML_VAR_PACKAGE_OP (UINT16) 0x13 /* ACPI 2.0 */ +#define AML_METHOD_OP (UINT16) 0x14 +#define AML_DUAL_NAME_PREFIX (UINT16) 0x2e +#define AML_MULTI_NAME_PREFIX_OP (UINT16) 0x2f +#define AML_NAME_CHAR_SUBSEQ (UINT16) 0x30 +#define AML_NAME_CHAR_FIRST (UINT16) 0x41 +#define AML_EXTENDED_OP_PREFIX (UINT16) 0x5b +#define AML_ROOT_PREFIX (UINT16) 0x5c +#define AML_PARENT_PREFIX (UINT16) 0x5e +#define AML_LOCAL_OP (UINT16) 0x60 +#define AML_LOCAL0 (UINT16) 0x60 +#define AML_LOCAL1 (UINT16) 0x61 +#define AML_LOCAL2 (UINT16) 0x62 +#define AML_LOCAL3 (UINT16) 0x63 +#define AML_LOCAL4 (UINT16) 0x64 +#define AML_LOCAL5 (UINT16) 0x65 +#define AML_LOCAL6 (UINT16) 0x66 +#define AML_LOCAL7 (UINT16) 0x67 +#define AML_ARG_OP (UINT16) 0x68 +#define AML_ARG0 (UINT16) 0x68 +#define AML_ARG1 (UINT16) 0x69 +#define AML_ARG2 (UINT16) 0x6a +#define AML_ARG3 (UINT16) 0x6b +#define AML_ARG4 (UINT16) 0x6c +#define AML_ARG5 (UINT16) 0x6d +#define AML_ARG6 (UINT16) 0x6e +#define AML_STORE_OP (UINT16) 0x70 +#define AML_REF_OF_OP (UINT16) 0x71 +#define AML_ADD_OP (UINT16) 0x72 +#define AML_CONCAT_OP (UINT16) 0x73 +#define AML_SUBTRACT_OP (UINT16) 0x74 +#define AML_INCREMENT_OP (UINT16) 0x75 +#define AML_DECREMENT_OP (UINT16) 0x76 +#define AML_MULTIPLY_OP (UINT16) 0x77 +#define AML_DIVIDE_OP (UINT16) 0x78 +#define AML_SHIFT_LEFT_OP (UINT16) 0x79 +#define AML_SHIFT_RIGHT_OP (UINT16) 0x7a +#define AML_BIT_AND_OP (UINT16) 0x7b +#define AML_BIT_NAND_OP (UINT16) 0x7c +#define AML_BIT_OR_OP (UINT16) 0x7d +#define AML_BIT_NOR_OP (UINT16) 0x7e +#define AML_BIT_XOR_OP (UINT16) 0x7f +#define AML_BIT_NOT_OP (UINT16) 0x80 +#define AML_FIND_SET_LEFT_BIT_OP (UINT16) 0x81 +#define AML_FIND_SET_RIGHT_BIT_OP (UINT16) 0x82 +#define AML_DEREF_OF_OP (UINT16) 0x83 +#define AML_CONCAT_RES_OP (UINT16) 0x84 /* ACPI 2.0 */ +#define AML_MOD_OP (UINT16) 0x85 /* ACPI 2.0 */ +#define AML_NOTIFY_OP (UINT16) 0x86 +#define AML_SIZE_OF_OP (UINT16) 0x87 +#define AML_INDEX_OP (UINT16) 0x88 +#define AML_MATCH_OP (UINT16) 0x89 +#define AML_CREATE_DWORD_FIELD_OP (UINT16) 0x8a +#define AML_CREATE_WORD_FIELD_OP (UINT16) 0x8b +#define AML_CREATE_BYTE_FIELD_OP (UINT16) 0x8c +#define AML_CREATE_BIT_FIELD_OP (UINT16) 0x8d +#define AML_TYPE_OP (UINT16) 0x8e +#define AML_CREATE_QWORD_FIELD_OP (UINT16) 0x8f /* ACPI 2.0 */ +#define AML_LAND_OP (UINT16) 0x90 +#define AML_LOR_OP (UINT16) 0x91 +#define AML_LNOT_OP (UINT16) 0x92 +#define AML_LEQUAL_OP (UINT16) 0x93 +#define AML_LGREATER_OP (UINT16) 0x94 +#define AML_LLESS_OP (UINT16) 0x95 +#define AML_TO_BUFFER_OP (UINT16) 0x96 /* ACPI 2.0 */ +#define AML_TO_DECSTRING_OP (UINT16) 0x97 /* ACPI 2.0 */ +#define AML_TO_HEXSTRING_OP (UINT16) 0x98 /* ACPI 2.0 */ +#define AML_TO_INTEGER_OP (UINT16) 0x99 /* ACPI 2.0 */ +#define AML_TO_STRING_OP (UINT16) 0x9c /* ACPI 2.0 */ +#define AML_COPY_OP (UINT16) 0x9d /* ACPI 2.0 */ +#define AML_MID_OP (UINT16) 0x9e /* ACPI 2.0 */ +#define AML_CONTINUE_OP (UINT16) 0x9f /* ACPI 2.0 */ +#define AML_IF_OP (UINT16) 0xa0 +#define AML_ELSE_OP (UINT16) 0xa1 +#define AML_WHILE_OP (UINT16) 0xa2 +#define AML_NOOP_OP (UINT16) 0xa3 +#define AML_RETURN_OP (UINT16) 0xa4 +#define AML_BREAK_OP (UINT16) 0xa5 +#define AML_BREAK_POINT_OP (UINT16) 0xcc +#define AML_ONES_OP (UINT16) 0xff + +/* prefixed opcodes */ + +#define AML_EXTENDED_OPCODE (UINT16) 0x5b00 /* prefix for 2-byte opcodes */ + +#define AML_MUTEX_OP (UINT16) 0x5b01 +#define AML_EVENT_OP (UINT16) 0x5b02 +#define AML_SHIFT_RIGHT_BIT_OP (UINT16) 0x5b10 +#define AML_SHIFT_LEFT_BIT_OP (UINT16) 0x5b11 +#define AML_COND_REF_OF_OP (UINT16) 0x5b12 +#define AML_CREATE_FIELD_OP (UINT16) 0x5b13 +#define AML_LOAD_TABLE_OP (UINT16) 0x5b1f /* ACPI 2.0 */ +#define AML_LOAD_OP (UINT16) 0x5b20 +#define AML_STALL_OP (UINT16) 0x5b21 +#define AML_SLEEP_OP (UINT16) 0x5b22 +#define AML_ACQUIRE_OP (UINT16) 0x5b23 +#define AML_SIGNAL_OP (UINT16) 0x5b24 +#define AML_WAIT_OP (UINT16) 0x5b25 +#define AML_RESET_OP (UINT16) 0x5b26 +#define AML_RELEASE_OP (UINT16) 0x5b27 +#define AML_FROM_BCD_OP (UINT16) 0x5b28 +#define AML_TO_BCD_OP (UINT16) 0x5b29 +#define AML_UNLOAD_OP (UINT16) 0x5b2a +#define AML_REVISION_OP (UINT16) 0x5b30 +#define AML_DEBUG_OP (UINT16) 0x5b31 +#define AML_FATAL_OP (UINT16) 0x5b32 +#define AML_TIMER_OP (UINT16) 0x5b33 /* ACPI 3.0 */ +#define AML_REGION_OP (UINT16) 0x5b80 +#define AML_FIELD_OP (UINT16) 0x5b81 +#define AML_DEVICE_OP (UINT16) 0x5b82 +#define AML_PROCESSOR_OP (UINT16) 0x5b83 +#define AML_POWER_RES_OP (UINT16) 0x5b84 +#define AML_THERMAL_ZONE_OP (UINT16) 0x5b85 +#define AML_INDEX_FIELD_OP (UINT16) 0x5b86 +#define AML_BANK_FIELD_OP (UINT16) 0x5b87 +#define AML_DATA_REGION_OP (UINT16) 0x5b88 /* ACPI 2.0 */ + + +/* + * Combination opcodes (actually two one-byte opcodes) + * Used by the disassembler and iASL compiler + */ +#define AML_LGREATEREQUAL_OP (UINT16) 0x9295 +#define AML_LLESSEQUAL_OP (UINT16) 0x9294 +#define AML_LNOTEQUAL_OP (UINT16) 0x9293 + + +/* + * Opcodes for "Field" operators + */ +#define AML_FIELD_OFFSET_OP (UINT8) 0x00 +#define AML_FIELD_ACCESS_OP (UINT8) 0x01 +#define AML_FIELD_CONNECTION_OP (UINT8) 0x02 /* ACPI 5.0 */ +#define AML_FIELD_EXT_ACCESS_OP (UINT8) 0x03 /* ACPI 5.0 */ + + +/* + * Internal opcodes + * Use only "Unknown" AML opcodes, don't attempt to use + * any valid ACPI ASCII values (A-Z, 0-9, '-') + */ +#define AML_INT_NAMEPATH_OP (UINT16) 0x002d +#define AML_INT_NAMEDFIELD_OP (UINT16) 0x0030 +#define AML_INT_RESERVEDFIELD_OP (UINT16) 0x0031 +#define AML_INT_ACCESSFIELD_OP (UINT16) 0x0032 +#define AML_INT_BYTELIST_OP (UINT16) 0x0033 +#define AML_INT_STATICSTRING_OP (UINT16) 0x0034 +#define AML_INT_METHODCALL_OP (UINT16) 0x0035 +#define AML_INT_RETURN_VALUE_OP (UINT16) 0x0036 +#define AML_INT_EVAL_SUBTREE_OP (UINT16) 0x0037 +#define AML_INT_CONNECTION_OP (UINT16) 0x0038 +#define AML_INT_EXTACCESSFIELD_OP (UINT16) 0x0039 + +#define ARG_NONE 0x0 + +/* + * Argument types for the AML Parser + * Each field in the ArgTypes UINT32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types + * Zero is reserved as end-of-list indicator + */ +#define ARGP_BYTEDATA 0x01 +#define ARGP_BYTELIST 0x02 +#define ARGP_CHARLIST 0x03 +#define ARGP_DATAOBJ 0x04 +#define ARGP_DATAOBJLIST 0x05 +#define ARGP_DWORDDATA 0x06 +#define ARGP_FIELDLIST 0x07 +#define ARGP_NAME 0x08 +#define ARGP_NAMESTRING 0x09 +#define ARGP_OBJLIST 0x0A +#define ARGP_PKGLENGTH 0x0B +#define ARGP_SUPERNAME 0x0C +#define ARGP_TARGET 0x0D +#define ARGP_TERMARG 0x0E +#define ARGP_TERMLIST 0x0F +#define ARGP_WORDDATA 0x10 +#define ARGP_QWORDDATA 0x11 +#define ARGP_SIMPLENAME 0x12 + +/* + * Resolved argument types for the AML Interpreter + * Each field in the ArgTypes UINT32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types (0 is end-of-arg-list indicator) + * + * Note1: These values are completely independent from the ACPI_TYPEs + * i.e., ARGI_INTEGER != ACPI_TYPE_INTEGER + * + * Note2: If and when 5 bits becomes insufficient, it would probably be best + * to convert to a 6-byte array of argument types, allowing 8 bits per argument. + */ + +/* Single, simple types */ + +#define ARGI_ANYTYPE 0x01 /* Don't care */ +#define ARGI_PACKAGE 0x02 +#define ARGI_EVENT 0x03 +#define ARGI_MUTEX 0x04 +#define ARGI_DDBHANDLE 0x05 + +/* Interchangeable types (via implicit conversion) */ + +#define ARGI_INTEGER 0x06 +#define ARGI_STRING 0x07 +#define ARGI_BUFFER 0x08 +#define ARGI_BUFFER_OR_STRING 0x09 /* Used by MID op only */ +#define ARGI_COMPUTEDATA 0x0A /* Buffer, String, or Integer */ + +/* Reference objects */ + +#define ARGI_INTEGER_REF 0x0B +#define ARGI_OBJECT_REF 0x0C +#define ARGI_DEVICE_REF 0x0D +#define ARGI_REFERENCE 0x0E +#define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */ +#define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */ +#define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */ + +/* Multiple/complex types */ + +#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a Node - Used only by SizeOf operator*/ +#define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */ +#define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */ +#define ARGI_REGION_OR_BUFFER 0x15 /* Used by LOAD op only */ +#define ARGI_DATAREFOBJ 0x16 + +/* Note: types above can expand to 0x1F maximum */ + +#define ARGI_INVALID_OPCODE 0xFFFFFFFF + + +/* + * hash offsets + */ +#define AML_EXTOP_HASH_OFFSET 22 +#define AML_LNOT_HASH_OFFSET 19 + + +/* + * opcode groups and types + */ +#define OPGRP_NAMED 0x01 +#define OPGRP_FIELD 0x02 +#define OPGRP_BYTELIST 0x04 + + +/* + * Opcode information + */ + +/* Opcode flags */ + +#define AML_LOGICAL 0x0001 +#define AML_LOGICAL_NUMERIC 0x0002 +#define AML_MATH 0x0004 +#define AML_CREATE 0x0008 +#define AML_FIELD 0x0010 +#define AML_DEFER 0x0020 +#define AML_NAMED 0x0040 +#define AML_NSNODE 0x0080 +#define AML_NSOPCODE 0x0100 +#define AML_NSOBJECT 0x0200 +#define AML_HAS_RETVAL 0x0400 +#define AML_HAS_TARGET 0x0800 +#define AML_HAS_ARGS 0x1000 +#define AML_CONSTANT 0x2000 +#define AML_NO_OPERAND_RESOLVE 0x4000 + +/* Convenient flag groupings */ + +#define AML_FLAGS_EXEC_0A_0T_1R AML_HAS_RETVAL +#define AML_FLAGS_EXEC_1A_0T_0R AML_HAS_ARGS /* Monadic1 */ +#define AML_FLAGS_EXEC_1A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Monadic2 */ +#define AML_FLAGS_EXEC_1A_1T_0R AML_HAS_ARGS | AML_HAS_TARGET +#define AML_FLAGS_EXEC_1A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* Monadic2R */ +#define AML_FLAGS_EXEC_2A_0T_0R AML_HAS_ARGS /* Dyadic1 */ +#define AML_FLAGS_EXEC_2A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Dyadic2 */ +#define AML_FLAGS_EXEC_2A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* Dyadic2R */ +#define AML_FLAGS_EXEC_2A_2T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL +#define AML_FLAGS_EXEC_3A_0T_0R AML_HAS_ARGS +#define AML_FLAGS_EXEC_3A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL +#define AML_FLAGS_EXEC_6A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL + + +/* + * The opcode Type is used in a dispatch table, do not change + * without updating the table. + */ +#define AML_TYPE_EXEC_0A_0T_1R 0x00 +#define AML_TYPE_EXEC_1A_0T_0R 0x01 /* Monadic1 */ +#define AML_TYPE_EXEC_1A_0T_1R 0x02 /* Monadic2 */ +#define AML_TYPE_EXEC_1A_1T_0R 0x03 +#define AML_TYPE_EXEC_1A_1T_1R 0x04 /* Monadic2R */ +#define AML_TYPE_EXEC_2A_0T_0R 0x05 /* Dyadic1 */ +#define AML_TYPE_EXEC_2A_0T_1R 0x06 /* Dyadic2 */ +#define AML_TYPE_EXEC_2A_1T_1R 0x07 /* Dyadic2R */ +#define AML_TYPE_EXEC_2A_2T_1R 0x08 +#define AML_TYPE_EXEC_3A_0T_0R 0x09 +#define AML_TYPE_EXEC_3A_1T_1R 0x0A +#define AML_TYPE_EXEC_6A_0T_1R 0x0B +/* End of types used in dispatch table */ + +#define AML_TYPE_LITERAL 0x0B +#define AML_TYPE_CONSTANT 0x0C +#define AML_TYPE_METHOD_ARGUMENT 0x0D +#define AML_TYPE_LOCAL_VARIABLE 0x0E +#define AML_TYPE_DATA_TERM 0x0F + +/* Generic for an op that returns a value */ + +#define AML_TYPE_METHOD_CALL 0x10 + +/* Misc */ + +#define AML_TYPE_CREATE_FIELD 0x11 +#define AML_TYPE_CREATE_OBJECT 0x12 +#define AML_TYPE_CONTROL 0x13 +#define AML_TYPE_NAMED_NO_OBJ 0x14 +#define AML_TYPE_NAMED_FIELD 0x15 +#define AML_TYPE_NAMED_SIMPLE 0x16 +#define AML_TYPE_NAMED_COMPLEX 0x17 +#define AML_TYPE_RETURN 0x18 + +#define AML_TYPE_UNDEFINED 0x19 +#define AML_TYPE_BOGUS 0x1A + +/* AML Package Length encodings */ + +#define ACPI_AML_PACKAGE_TYPE1 0x40 +#define ACPI_AML_PACKAGE_TYPE2 0x4000 +#define ACPI_AML_PACKAGE_TYPE3 0x400000 +#define ACPI_AML_PACKAGE_TYPE4 0x40000000 + +/* + * Opcode classes + */ +#define AML_CLASS_EXECUTE 0x00 +#define AML_CLASS_CREATE 0x01 +#define AML_CLASS_ARGUMENT 0x02 +#define AML_CLASS_NAMED_OBJECT 0x03 +#define AML_CLASS_CONTROL 0x04 +#define AML_CLASS_ASCII 0x05 +#define AML_CLASS_PREFIX 0x06 +#define AML_CLASS_INTERNAL 0x07 +#define AML_CLASS_RETURN_VALUE 0x08 +#define AML_CLASS_METHOD_CALL 0x09 +#define AML_CLASS_UNKNOWN 0x0A + + +/* Comparison operation codes for MatchOp operator */ + +typedef enum +{ + MATCH_MTR = 0, + MATCH_MEQ = 1, + MATCH_MLE = 2, + MATCH_MLT = 3, + MATCH_MGE = 4, + MATCH_MGT = 5 + +} AML_MATCH_OPERATOR; + +#define MAX_MATCH_OPERATOR 5 + + +/* + * FieldFlags + * + * This byte is extracted from the AML and includes three separate + * pieces of information about the field: + * 1) The field access type + * 2) The field update rule + * 3) The lock rule for the field + * + * Bits 00 - 03 : AccessType (AnyAcc, ByteAcc, etc.) + * 04 : LockRule (1 == Lock) + * 05 - 06 : UpdateRule + */ +#define AML_FIELD_ACCESS_TYPE_MASK 0x0F +#define AML_FIELD_LOCK_RULE_MASK 0x10 +#define AML_FIELD_UPDATE_RULE_MASK 0x60 + + +/* 1) Field Access Types */ + +typedef enum +{ + AML_FIELD_ACCESS_ANY = 0x00, + AML_FIELD_ACCESS_BYTE = 0x01, + AML_FIELD_ACCESS_WORD = 0x02, + AML_FIELD_ACCESS_DWORD = 0x03, + AML_FIELD_ACCESS_QWORD = 0x04, /* ACPI 2.0 */ + AML_FIELD_ACCESS_BUFFER = 0x05 /* ACPI 2.0 */ + +} AML_ACCESS_TYPE; + + +/* 2) Field Lock Rules */ + +typedef enum +{ + AML_FIELD_LOCK_NEVER = 0x00, + AML_FIELD_LOCK_ALWAYS = 0x10 + +} AML_LOCK_RULE; + + +/* 3) Field Update Rules */ + +typedef enum +{ + AML_FIELD_UPDATE_PRESERVE = 0x00, + AML_FIELD_UPDATE_WRITE_AS_ONES = 0x20, + AML_FIELD_UPDATE_WRITE_AS_ZEROS = 0x40 + +} AML_UPDATE_RULE; + + +/* + * Field Access Attributes. + * This byte is extracted from the AML via the + * AccessAs keyword + */ +typedef enum +{ + AML_FIELD_ATTRIB_QUICK = 0x02, + AML_FIELD_ATTRIB_SEND_RCV = 0x04, + AML_FIELD_ATTRIB_BYTE = 0x06, + AML_FIELD_ATTRIB_WORD = 0x08, + AML_FIELD_ATTRIB_BLOCK = 0x0A, + AML_FIELD_ATTRIB_MULTIBYTE = 0x0B, + AML_FIELD_ATTRIB_WORD_CALL = 0x0C, + AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D, + AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, + AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F + +} AML_ACCESS_ATTRIBUTE; + + +/* Bit fields in the AML MethodFlags byte */ + +#define AML_METHOD_ARG_COUNT 0x07 +#define AML_METHOD_SERIALIZED 0x08 +#define AML_METHOD_SYNC_LEVEL 0xF0 + + +#endif /* __AMLCODE_H__ */ diff --git a/source/include/amlresrc.h b/source/include/amlresrc.h new file mode 100644 index 000000000000..6d85b8a2d05b --- /dev/null +++ b/source/include/amlresrc.h @@ -0,0 +1,579 @@ + +/****************************************************************************** + * + * Module Name: amlresrc.h - AML resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* acpisrc:StructDefs -- for acpisrc conversion */ + +#ifndef __AMLRESRC_H +#define __AMLRESRC_H + + +/* + * Resource descriptor tags, as defined in the ACPI specification. + * Used to symbolically reference fields within a descriptor. + */ +#define ACPI_RESTAG_ADDRESS "_ADR" +#define ACPI_RESTAG_ALIGNMENT "_ALN" +#define ACPI_RESTAG_ADDRESSSPACE "_ASI" +#define ACPI_RESTAG_ACCESSSIZE "_ASZ" +#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES "_ATT" +#define ACPI_RESTAG_BASEADDRESS "_BAS" +#define ACPI_RESTAG_BUSMASTER "_BM_" /* Master(1), Slave(0) */ +#define ACPI_RESTAG_DEBOUNCETIME "_DBT" +#define ACPI_RESTAG_DECODE "_DEC" +#define ACPI_RESTAG_DEVICEPOLARITY "_DPL" +#define ACPI_RESTAG_DMA "_DMA" +#define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ +#define ACPI_RESTAG_DRIVESTRENGTH "_DRS" +#define ACPI_RESTAG_ENDIANNESS "_END" +#define ACPI_RESTAG_FLOWCONTROL "_FLC" +#define ACPI_RESTAG_GRANULARITY "_GRA" +#define ACPI_RESTAG_INTERRUPT "_INT" +#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* ActiveLo(1), ActiveHi(0) */ +#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), NoShare(0) */ +#define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ +#define ACPI_RESTAG_IORESTRICTION "_IOR" +#define ACPI_RESTAG_LENGTH "_LEN" +#define ACPI_RESTAG_LINE "_LIN" +#define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ +#define ACPI_RESTAG_MEMTYPE "_MEM" /* NonCache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ +#define ACPI_RESTAG_MAXADDR "_MAX" +#define ACPI_RESTAG_MINADDR "_MIN" +#define ACPI_RESTAG_MAXTYPE "_MAF" +#define ACPI_RESTAG_MINTYPE "_MIF" +#define ACPI_RESTAG_MODE "_MOD" +#define ACPI_RESTAG_PARITY "_PAR" +#define ACPI_RESTAG_PHASE "_PHA" +#define ACPI_RESTAG_PIN "_PIN" +#define ACPI_RESTAG_PINCONFIG "_PPI" +#define ACPI_RESTAG_POLARITY "_POL" +#define ACPI_RESTAG_REGISTERBITOFFSET "_RBO" +#define ACPI_RESTAG_REGISTERBITWIDTH "_RBW" +#define ACPI_RESTAG_RANGETYPE "_RNG" +#define ACPI_RESTAG_READWRITETYPE "_RW_" /* ReadOnly(0), Writeable (1) */ +#define ACPI_RESTAG_LENGTH_RX "_RXL" +#define ACPI_RESTAG_LENGTH_TX "_TXL" +#define ACPI_RESTAG_SLAVEMODE "_SLV" +#define ACPI_RESTAG_SPEED "_SPE" +#define ACPI_RESTAG_STOPBITS "_STB" +#define ACPI_RESTAG_TRANSLATION "_TRA" +#define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ +#define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */ +#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8And16(1), 16(2) */ +#define ACPI_RESTAG_VENDORDATA "_VEN" + + +/* Default sizes for "small" resource descriptors */ + +#define ASL_RDESC_IRQ_SIZE 0x02 +#define ASL_RDESC_DMA_SIZE 0x02 +#define ASL_RDESC_ST_DEPEND_SIZE 0x00 +#define ASL_RDESC_END_DEPEND_SIZE 0x00 +#define ASL_RDESC_IO_SIZE 0x07 +#define ASL_RDESC_FIXED_IO_SIZE 0x03 +#define ASL_RDESC_FIXED_DMA_SIZE 0x05 +#define ASL_RDESC_END_TAG_SIZE 0x01 + + +typedef struct asl_resource_node +{ + UINT32 BufferLength; + void *Buffer; + struct asl_resource_node *Next; + +} ASL_RESOURCE_NODE; + + +/* Macros used to generate AML resource length fields */ + +#define ACPI_AML_SIZE_LARGE(r) (sizeof (r) - sizeof (AML_RESOURCE_LARGE_HEADER)) +#define ACPI_AML_SIZE_SMALL(r) (sizeof (r) - sizeof (AML_RESOURCE_SMALL_HEADER)) + +/* + * Resource descriptors defined in the ACPI specification. + * + * Packing/alignment must be BYTE because these descriptors + * are used to overlay the raw AML byte stream. + */ +#pragma pack(1) + +/* + * SMALL descriptors + */ +#define AML_RESOURCE_SMALL_HEADER_COMMON \ + UINT8 DescriptorType; + +typedef struct aml_resource_small_header +{ + AML_RESOURCE_SMALL_HEADER_COMMON + +} AML_RESOURCE_SMALL_HEADER; + + +typedef struct aml_resource_irq +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT16 IrqMask; + UINT8 Flags; + +} AML_RESOURCE_IRQ; + + +typedef struct aml_resource_irq_noflags +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT16 IrqMask; + +} AML_RESOURCE_IRQ_NOFLAGS; + + +typedef struct aml_resource_dma +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT8 DmaChannelMask; + UINT8 Flags; + +} AML_RESOURCE_DMA; + + +typedef struct aml_resource_start_dependent +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT8 Flags; + +} AML_RESOURCE_START_DEPENDENT; + + +typedef struct aml_resource_start_dependent_noprio +{ + AML_RESOURCE_SMALL_HEADER_COMMON + +} AML_RESOURCE_START_DEPENDENT_NOPRIO; + + +typedef struct aml_resource_end_dependent +{ + AML_RESOURCE_SMALL_HEADER_COMMON + +} AML_RESOURCE_END_DEPENDENT; + + +typedef struct aml_resource_io +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT8 Flags; + UINT16 Minimum; + UINT16 Maximum; + UINT8 Alignment; + UINT8 AddressLength; + +} AML_RESOURCE_IO; + + +typedef struct aml_resource_fixed_io +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT16 Address; + UINT8 AddressLength; + +} AML_RESOURCE_FIXED_IO; + + +typedef struct aml_resource_vendor_small +{ + AML_RESOURCE_SMALL_HEADER_COMMON + +} AML_RESOURCE_VENDOR_SMALL; + + +typedef struct aml_resource_end_tag +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT8 Checksum; + +} AML_RESOURCE_END_TAG; + + +typedef struct aml_resource_fixed_dma +{ + AML_RESOURCE_SMALL_HEADER_COMMON + UINT16 RequestLines; + UINT16 Channels; + UINT8 Width; + +} AML_RESOURCE_FIXED_DMA; + + +/* + * LARGE descriptors + */ +#define AML_RESOURCE_LARGE_HEADER_COMMON \ + UINT8 DescriptorType;\ + UINT16 ResourceLength; + +typedef struct aml_resource_large_header +{ + AML_RESOURCE_LARGE_HEADER_COMMON + +} AML_RESOURCE_LARGE_HEADER; + + +/* General Flags for address space resource descriptors */ + +#define ACPI_RESOURCE_FLAG_DEC 2 +#define ACPI_RESOURCE_FLAG_MIF 4 +#define ACPI_RESOURCE_FLAG_MAF 8 + +typedef struct aml_resource_memory24 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 Flags; + UINT16 Minimum; + UINT16 Maximum; + UINT16 Alignment; + UINT16 AddressLength; + +} AML_RESOURCE_MEMORY24; + + +typedef struct aml_resource_vendor_large +{ + AML_RESOURCE_LARGE_HEADER_COMMON + +} AML_RESOURCE_VENDOR_LARGE; + + +typedef struct aml_resource_memory32 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 Flags; + UINT32 Minimum; + UINT32 Maximum; + UINT32 Alignment; + UINT32 AddressLength; + +} AML_RESOURCE_MEMORY32; + + +typedef struct aml_resource_fixed_memory32 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 Flags; + UINT32 Address; + UINT32 AddressLength; + +} AML_RESOURCE_FIXED_MEMORY32; + + +#define AML_RESOURCE_ADDRESS_COMMON \ + UINT8 ResourceType; \ + UINT8 Flags; \ + UINT8 SpecificFlags; + + +typedef struct aml_resource_address +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON + +} AML_RESOURCE_ADDRESS; + + +typedef struct aml_resource_extended_address64 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON + UINT8 RevisionID; + UINT8 Reserved; + UINT64 Granularity; + UINT64 Minimum; + UINT64 Maximum; + UINT64 TranslationOffset; + UINT64 AddressLength; + UINT64 TypeSpecific; + +} AML_RESOURCE_EXTENDED_ADDRESS64; + +#define AML_RESOURCE_EXTENDED_ADDRESS_REVISION 1 /* ACPI 3.0 */ + + +typedef struct aml_resource_address64 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON + UINT64 Granularity; + UINT64 Minimum; + UINT64 Maximum; + UINT64 TranslationOffset; + UINT64 AddressLength; + +} AML_RESOURCE_ADDRESS64; + + +typedef struct aml_resource_address32 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON + UINT32 Granularity; + UINT32 Minimum; + UINT32 Maximum; + UINT32 TranslationOffset; + UINT32 AddressLength; + +} AML_RESOURCE_ADDRESS32; + + +typedef struct aml_resource_address16 +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON + UINT16 Granularity; + UINT16 Minimum; + UINT16 Maximum; + UINT16 TranslationOffset; + UINT16 AddressLength; + +} AML_RESOURCE_ADDRESS16; + + +typedef struct aml_resource_extended_irq +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 Flags; + UINT8 InterruptCount; + UINT32 Interrupts[1]; + /* ResSourceIndex, ResSource optional fields follow */ + +} AML_RESOURCE_EXTENDED_IRQ; + + +typedef struct aml_resource_generic_register +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 AddressSpaceId; + UINT8 BitWidth; + UINT8 BitOffset; + UINT8 AccessSize; /* ACPI 3.0, was previously Reserved */ + UINT64 Address; + +} AML_RESOURCE_GENERIC_REGISTER; + + +/* Common descriptor for GpioInt and GpioIo (ACPI 5.0) */ + +typedef struct aml_resource_gpio +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT8 ConnectionType; + UINT16 Flags; + UINT16 IntFlags; + UINT8 PinConfig; + UINT16 DriveStrength; + UINT16 DebounceTimeout; + UINT16 PinTableOffset; + UINT8 ResSourceIndex; + UINT16 ResSourceOffset; + UINT16 VendorOffset; + UINT16 VendorLength; + /* + * Optional fields follow immediately: + * 1) PIN list (Words) + * 2) Resource Source String + * 3) Vendor Data bytes + */ + +} AML_RESOURCE_GPIO; + +#define AML_RESOURCE_GPIO_REVISION 1 /* ACPI 5.0 */ + +/* Values for ConnectionType above */ + +#define AML_RESOURCE_GPIO_TYPE_INT 0 +#define AML_RESOURCE_GPIO_TYPE_IO 1 +#define AML_RESOURCE_MAX_GPIOTYPE 1 + + +/* Common preamble for all serial descriptors (ACPI 5.0) */ + +#define AML_RESOURCE_SERIAL_COMMON \ + UINT8 RevisionId; \ + UINT8 ResSourceIndex; \ + UINT8 Type; \ + UINT8 Flags; \ + UINT16 TypeSpecificFlags; \ + UINT8 TypeRevisionId; \ + UINT16 TypeDataLength; \ + +/* Values for the type field above */ + +#define AML_RESOURCE_I2C_SERIALBUSTYPE 1 +#define AML_RESOURCE_SPI_SERIALBUSTYPE 2 +#define AML_RESOURCE_UART_SERIALBUSTYPE 3 +#define AML_RESOURCE_MAX_SERIALBUSTYPE 3 +#define AML_RESOURCE_VENDOR_SERIALBUSTYPE 192 /* Vendor defined is 0xC0-0xFF (NOT SUPPORTED) */ + +typedef struct aml_resource_common_serialbus +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_SERIAL_COMMON + +} AML_RESOURCE_COMMON_SERIALBUS; + +typedef struct aml_resource_i2c_serialbus +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_SERIAL_COMMON + UINT32 ConnectionSpeed; + UINT16 SlaveAddress; + /* + * Optional fields follow immediately: + * 1) Vendor Data bytes + * 2) Resource Source String + */ + +} AML_RESOURCE_I2C_SERIALBUS; + +#define AML_RESOURCE_I2C_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_I2C_TYPE_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_I2C_MIN_DATA_LEN 6 + +typedef struct aml_resource_spi_serialbus +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_SERIAL_COMMON + UINT32 ConnectionSpeed; + UINT8 DataBitLength; + UINT8 ClockPhase; + UINT8 ClockPolarity; + UINT16 DeviceSelection; + /* + * Optional fields follow immediately: + * 1) Vendor Data bytes + * 2) Resource Source String + */ + +} AML_RESOURCE_SPI_SERIALBUS; + +#define AML_RESOURCE_SPI_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_SPI_TYPE_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_SPI_MIN_DATA_LEN 9 + + +typedef struct aml_resource_uart_serialbus +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_SERIAL_COMMON + UINT32 DefaultBaudRate; + UINT16 RxFifoSize; + UINT16 TxFifoSize; + UINT8 Parity; + UINT8 LinesEnabled; + /* + * Optional fields follow immediately: + * 1) Vendor Data bytes + * 2) Resource Source String + */ + +} AML_RESOURCE_UART_SERIALBUS; + +#define AML_RESOURCE_UART_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_UART_TYPE_REVISION 1 /* ACPI 5.0 */ +#define AML_RESOURCE_UART_MIN_DATA_LEN 10 + + +/* restore default alignment */ + +#pragma pack() + +/* Union of all resource descriptors, so we can allocate the worst case */ + +typedef union aml_resource +{ + /* Descriptor headers */ + + UINT8 DescriptorType; + AML_RESOURCE_SMALL_HEADER SmallHeader; + AML_RESOURCE_LARGE_HEADER LargeHeader; + + /* Small resource descriptors */ + + AML_RESOURCE_IRQ Irq; + AML_RESOURCE_DMA Dma; + AML_RESOURCE_START_DEPENDENT StartDpf; + AML_RESOURCE_END_DEPENDENT EndDpf; + AML_RESOURCE_IO Io; + AML_RESOURCE_FIXED_IO FixedIo; + AML_RESOURCE_FIXED_DMA FixedDma; + AML_RESOURCE_VENDOR_SMALL VendorSmall; + AML_RESOURCE_END_TAG EndTag; + + /* Large resource descriptors */ + + AML_RESOURCE_MEMORY24 Memory24; + AML_RESOURCE_GENERIC_REGISTER GenericReg; + AML_RESOURCE_VENDOR_LARGE VendorLarge; + AML_RESOURCE_MEMORY32 Memory32; + AML_RESOURCE_FIXED_MEMORY32 FixedMemory32; + AML_RESOURCE_ADDRESS16 Address16; + AML_RESOURCE_ADDRESS32 Address32; + AML_RESOURCE_ADDRESS64 Address64; + AML_RESOURCE_EXTENDED_ADDRESS64 ExtAddress64; + AML_RESOURCE_EXTENDED_IRQ ExtendedIrq; + AML_RESOURCE_GPIO Gpio; + AML_RESOURCE_I2C_SERIALBUS I2cSerialBus; + AML_RESOURCE_SPI_SERIALBUS SpiSerialBus; + AML_RESOURCE_UART_SERIALBUS UartSerialBus; + AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus; + + /* Utility overlays */ + + AML_RESOURCE_ADDRESS Address; + UINT32 DwordItem; + UINT16 WordItem; + UINT8 ByteItem; + +} AML_RESOURCE; + +#endif + diff --git a/source/include/platform/accygwin.h b/source/include/platform/accygwin.h new file mode 100644 index 000000000000..831f31398792 --- /dev/null +++ b/source/include/platform/accygwin.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * Name: accygwin.h - OS specific defines, etc. for cygwin environment + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACCYGWIN_H__ +#define __ACCYGWIN_H__ + +/* + * ACPICA configuration + */ +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_DO_WHILE_0 +#define ACPI_FLUSH_CPU_CACHE() +/* + * This is needed since sem_timedwait does not appear to work properly + * on cygwin (always hangs forever). + */ +#define ACPI_USE_ALTERNATE_TIMEOUT + + +#include +#include +#include +#include +#include + +#if defined(__ia64__) || defined(__x86_64__) +#define ACPI_MACHINE_WIDTH 64 +#define COMPILER_DEPENDENT_INT64 long +#define COMPILER_DEPENDENT_UINT64 unsigned long +#else +#define ACPI_MACHINE_WIDTH 32 +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_USE_NATIVE_DIVIDE +#endif + +#ifndef __cdecl +#define __cdecl +#endif + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) if (GLptr) Acq=1; else Acq=0; +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pending) Pending = 1 + +/* On Cygwin, pthread_t is a pointer */ + +#define ACPI_CAST_PTHREAD_T(pthread) ((ACPI_THREAD_ID) ACPI_TO_INTEGER (pthread)) + +/* Cygwin uses GCC */ + +#include "acgcc.h" + +#endif /* __ACCYGWIN_H__ */ diff --git a/source/include/platform/acefi.h b/source/include/platform/acefi.h new file mode 100644 index 000000000000..bab6159381ac --- /dev/null +++ b/source/include/platform/acefi.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * Name: acefi.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACEFI_H__ +#define __ACEFI_H__ + +#include +#include +#include + + +/* _int64 works for both IA32 and IA64 */ + +#define COMPILER_DEPENDENT_INT64 __int64 +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 + +/* + * Calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE + +/* warn C4142: redefinition of type */ + +#pragma warning(disable:4142) + + +#endif /* __ACEFI_H__ */ diff --git a/source/include/platform/acenv.h b/source/include/platform/acenv.h new file mode 100644 index 000000000000..19ca03baacc6 --- /dev/null +++ b/source/include/platform/acenv.h @@ -0,0 +1,392 @@ +/****************************************************************************** + * + * Name: acenv.h - Host and compiler configuration + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACENV_H__ +#define __ACENV_H__ + +/* + * Environment configuration. The purpose of this file is to interface ACPICA + * to the local environment. This includes compiler-specific, OS-specific, + * and machine-specific configuration. + */ + +/* Types for ACPI_MUTEX_TYPE */ + +#define ACPI_BINARY_SEMAPHORE 0 +#define ACPI_OSL_MUTEX 1 + +/* Types for DEBUGGER_THREADING */ + +#define DEBUGGER_SINGLE_THREADED 0 +#define DEBUGGER_MULTI_THREADED 1 + + +/****************************************************************************** + * + * Configuration for ACPI tools and utilities + * + *****************************************************************************/ + +/* iASL configuration */ + +#ifdef ACPI_ASL_COMPILER +#define ACPI_APPLICATION +#define ACPI_DISASSEMBLER +#define ACPI_DEBUG_OUTPUT +#define ACPI_CONSTANT_EVAL_ONLY +#define ACPI_LARGE_NAMESPACE_NODE +#define ACPI_DATA_TABLE_DISASSEMBLY +#define ACPI_SINGLE_THREADED +#endif + +/* AcpiExec configuration. Multithreaded with full AML debugger */ + +#ifdef ACPI_EXEC_APP +#define ACPI_APPLICATION +#define ACPI_FULL_DEBUG +#define ACPI_MUTEX_DEBUG +#define ACPI_DBG_TRACK_ALLOCATIONS +#endif + +/* AcpiNames configuration. Single threaded with debugger output enabled. */ + +#ifdef ACPI_NAMES_APP +#define ACPI_DEBUGGER +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + +/* + * AcpiBin/AcpiHelp/AcpiSrc configuration. All single threaded, with + * no debug output. + */ +#if (defined ACPI_BIN_APP) || \ + (defined ACPI_SRC_APP) || \ + (defined ACPI_XTRACT_APP) +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + +#ifdef ACPI_HELP_APP +#define ACPI_DEBUG_OUTPUT +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + +/* Linkable ACPICA library */ + +#ifdef ACPI_LIBRARY +#define ACPI_USE_LOCAL_CACHE +#endif + +/* Common for all ACPICA applications */ + +#ifdef ACPI_APPLICATION +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_LOCAL_CACHE +#endif + +/* Common debug support */ + +#ifdef ACPI_FULL_DEBUG +#define ACPI_DEBUGGER +#define ACPI_DEBUG_OUTPUT +#define ACPI_DISASSEMBLER +#endif + + +/*! [Begin] no source code translation */ + +/****************************************************************************** + * + * Host configuration files. The compiler configuration files are included + * by the host files. + * + *****************************************************************************/ + +#if defined(_LINUX) || defined(__linux__) +#include "aclinux.h" + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include "acfreebsd.h" + +#elif defined(__NetBSD__) +#include "acnetbsd.h" + +#elif defined(__sun) +#include "acsolaris.h" + +#elif defined(MODESTO) +#include "acmodesto.h" + +#elif defined(NETWARE) +#include "acnetware.h" + +#elif defined(_CYGWIN) +#include "accygwin.h" + +#elif defined(WIN32) +#include "acwin.h" + +#elif defined(WIN64) +#include "acwin64.h" + +#elif defined(_WRS_LIB_BUILD) +#include "acvxworks.h" + +#elif defined(__OS2__) +#include "acos2.h" + +#elif defined(_AED_EFI) +#include "acefi.h" + +#else + +/* Unknown environment */ + +#error Unknown target environment +#endif + +/*! [End] no source code translation !*/ + + +/****************************************************************************** + * + * Setup defaults for the required symbols that were not defined in one of + * the host/compiler files above. + * + *****************************************************************************/ + +/* 64-bit data types */ + +#ifndef COMPILER_DEPENDENT_INT64 +#define COMPILER_DEPENDENT_INT64 long long +#endif + +#ifndef COMPILER_DEPENDENT_UINT64 +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#endif + +/* Type of mutex supported by host. Default is binary semaphores. */ + +#ifndef ACPI_MUTEX_TYPE +#define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE +#endif + +/* Global Lock acquire/release */ + +#ifndef ACPI_ACQUIRE_GLOBAL_LOCK +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acquired) Acquired = 1 +#endif + +#ifndef ACPI_RELEASE_GLOBAL_LOCK +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pending) Pending = 0 +#endif + +/* Flush CPU cache - used when going to sleep. Wbinvd or similar. */ + +#ifndef ACPI_FLUSH_CPU_CACHE +#define ACPI_FLUSH_CPU_CACHE() +#endif + +/* "inline" keywords - configurable since inline is not standardized */ + +#ifndef ACPI_INLINE +#define ACPI_INLINE +#endif + +/* + * Configurable calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#ifndef ACPI_SYSTEM_XFACE +#define ACPI_SYSTEM_XFACE +#endif + +#ifndef ACPI_EXTERNAL_XFACE +#define ACPI_EXTERNAL_XFACE +#endif + +#ifndef ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#endif + +#ifndef ACPI_INTERNAL_VAR_XFACE +#define ACPI_INTERNAL_VAR_XFACE +#endif + +/* + * Debugger threading model + * Use single threaded if the entire subsystem is contained in an application + * Use multiple threaded when the subsystem is running in the kernel. + * + * By default the model is single threaded if ACPI_APPLICATION is set, + * multi-threaded if ACPI_APPLICATION is not set. + */ +#ifndef DEBUGGER_THREADING +#ifdef ACPI_APPLICATION +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#else +#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED +#endif +#endif /* !DEBUGGER_THREADING */ + + +/****************************************************************************** + * + * C library configuration + * + *****************************************************************************/ + +/* + * ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. + * Otherwise, local versions of string/memory functions will be used. + * ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and + * the standard header files may be used. + * + * The ACPICA subsystem only uses low level C library functions that do not call + * operating system services and may therefore be inlined in the code. + * + * It may be necessary to tailor these include files to the target + * generation environment. + */ +#ifdef ACPI_USE_SYSTEM_CLIBRARY + +/* Use the standard C library headers. We want to keep these to a minimum */ + +#ifdef ACPI_USE_STANDARD_HEADERS + +/* Use the standard headers from the standard locations */ + +#include +#include +#include +#include + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* We will be linking to the standard Clib functions */ + +#define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) +#define ACPI_STRCHR(s1,c) strchr((s1), (c)) +#define ACPI_STRLEN(s) (ACPI_SIZE) strlen((s)) +#define ACPI_STRCPY(d,s) (void) strcpy((d), (s)) +#define ACPI_STRNCPY(d,s,n) (void) strncpy((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRNCMP(d,s,n) strncmp((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRCMP(d,s) strcmp((d), (s)) +#define ACPI_STRCAT(d,s) (void) strcat((d), (s)) +#define ACPI_STRNCAT(d,s,n) strncat((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMCMP(s1,s2,n) memcmp((const char *)(s1), (const char *)(s2), (ACPI_SIZE)(n)) +#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (ACPI_SIZE)(n)) +#define ACPI_TOUPPER(i) toupper((int) (i)) +#define ACPI_TOLOWER(i) tolower((int) (i)) +#define ACPI_IS_XDIGIT(i) isxdigit((int) (i)) +#define ACPI_IS_DIGIT(i) isdigit((int) (i)) +#define ACPI_IS_SPACE(i) isspace((int) (i)) +#define ACPI_IS_UPPER(i) isupper((int) (i)) +#define ACPI_IS_PRINT(i) isprint((int) (i)) +#define ACPI_IS_ALPHA(i) isalpha((int) (i)) + +#else + +/****************************************************************************** + * + * Not using native C library, use local implementations + * + *****************************************************************************/ + +/* + * Use local definitions of C library macros and functions. These function + * implementations may not be as efficient as an inline or assembly code + * implementation provided by a native C library, but they are functionally + * equivalent. + */ +#ifndef va_arg + +#ifndef _VALIST +#define _VALIST +typedef char *va_list; +#endif /* _VALIST */ + +/* Storage alignment properties */ + +#define _AUPBND (sizeof (ACPI_NATIVE_INT) - 1) +#define _ADNBND (sizeof (ACPI_NATIVE_INT) - 1) + +/* Variable argument list macro definitions */ + +#define _Bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) +#define va_arg(ap, T) (*(T *)(((ap) += (_Bnd (T, _AUPBND))) - (_Bnd (T,_ADNBND)))) +#define va_end(ap) (void) 0 +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_Bnd (A,_AUPBND)))) + +#endif /* va_arg */ + +/* Use the local (ACPICA) definitions of the clib functions */ + +#define ACPI_STRSTR(s1,s2) AcpiUtStrstr ((s1), (s2)) +#define ACPI_STRCHR(s1,c) AcpiUtStrchr ((s1), (c)) +#define ACPI_STRLEN(s) (ACPI_SIZE) AcpiUtStrlen ((s)) +#define ACPI_STRCPY(d,s) (void) AcpiUtStrcpy ((d), (s)) +#define ACPI_STRNCPY(d,s,n) (void) AcpiUtStrncpy ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRNCMP(d,s,n) AcpiUtStrncmp ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRCMP(d,s) AcpiUtStrcmp ((d), (s)) +#define ACPI_STRCAT(d,s) (void) AcpiUtStrcat ((d), (s)) +#define ACPI_STRNCAT(d,s,n) AcpiUtStrncat ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRTOUL(d,s,n) AcpiUtStrtoul ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMCMP(s1,s2,n) AcpiUtMemcmp((const char *)(s1), (const char *)(s2), (ACPI_SIZE)(n)) +#define ACPI_MEMCPY(d,s,n) (void) AcpiUtMemcpy ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMSET(d,v,n) (void) AcpiUtMemset ((d), (v), (ACPI_SIZE)(n)) +#define ACPI_TOUPPER(c) AcpiUtToUpper ((int) (c)) +#define ACPI_TOLOWER(c) AcpiUtToLower ((int) (c)) + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + +#endif /* __ACENV_H__ */ diff --git a/source/include/platform/acfreebsd.h b/source/include/platform/acfreebsd.h new file mode 100644 index 000000000000..98f972f373e1 --- /dev/null +++ b/source/include/platform/acfreebsd.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Name: acfreebsd.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACFREEBSD_H__ +#define __ACFREEBSD_H__ + + +/* FreeBSD uses GCC */ + +#include "acgcc.h" +#include +#include + +#define ACPI_UINTPTR_T uintptr_t + +#define ACPI_USE_DO_WHILE_0 +#define ACPI_USE_LOCAL_CACHE +#define ACPI_USE_SYSTEM_CLIBRARY + +#ifdef _KERNEL + +#include +#include +#include +#include +#include + +#include "opt_acpi.h" + +#define ACPI_MUTEX_TYPE ACPI_OSL_MUTEX + +#ifdef ACPI_DEBUG +#define ACPI_DEBUG_OUTPUT /* for backward compatibility */ +#define ACPI_DISASSEMBLER +#endif + +#ifdef ACPI_DEBUG_OUTPUT +#include "opt_ddb.h" +#ifdef DDB +#define ACPI_DEBUGGER +#endif /* DDB */ +#endif /* ACPI_DEBUG_OUTPUT */ + +#ifdef DEBUGGER_THREADING +#undef DEBUGGER_THREADING +#endif /* DEBUGGER_THREADING */ + +#define DEBUGGER_THREADING 0 /* integrated with DDB */ + +#else /* _KERNEL */ + +#if __STDC_HOSTED__ +#include +#endif + +#define ACPI_CAST_PTHREAD_T(pthread) ((ACPI_THREAD_ID) ACPI_TO_INTEGER (pthread)) + +#define ACPI_USE_STANDARD_HEADERS + +#define ACPI_FLUSH_CPU_CACHE() +#define __cdecl + +#endif /* _KERNEL */ + +#endif /* __ACFREEBSD_H__ */ diff --git a/source/include/platform/acgcc.h b/source/include/platform/acgcc.h new file mode 100644 index 000000000000..d2eafff39584 --- /dev/null +++ b/source/include/platform/acgcc.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * + * Name: acgcc.h - GCC specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACGCC_H__ +#define __ACGCC_H__ + +#define ACPI_INLINE __inline__ + +/* Function name is used for debug output. Non-ANSI, compiler-dependent */ + +#define ACPI_GET_FUNCTION_NAME __FUNCTION__ + +/* + * This macro is used to tag functions as "printf-like" because + * some compilers (like GCC) can catch printf format string problems. + */ +#define ACPI_PRINTF_LIKE(c) __attribute__ ((__format__ (__printf__, c, c+1))) + +/* + * Some compilers complain about unused variables. Sometimes we don't want to + * use all the variables (for example, _AcpiModuleName). This allows us + * to to tell the compiler warning in a per-variable manner that a variable + * is unused. + */ +#define ACPI_UNUSED_VAR __attribute__ ((unused)) + +#endif /* __ACGCC_H__ */ diff --git a/source/include/platform/acintel.h b/source/include/platform/acintel.h new file mode 100644 index 000000000000..46d238bedb86 --- /dev/null +++ b/source/include/platform/acintel.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * Name: acintel.h - VC specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACINTEL_H__ +#define __ACINTEL_H__ + +/* Configuration specific to Intel 64-bit C compiler */ + +#define COMPILER_DEPENDENT_INT64 __int64 +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 +#define ACPI_INLINE __inline + +/* + * Calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE + +/* remark 981 - operands evaluated in no particular order */ +#pragma warning(disable:981) + +/* warn C4100: unreferenced formal parameter */ +#pragma warning(disable:4100) + +/* warn C4127: conditional expression is constant */ +#pragma warning(disable:4127) + +/* warn C4706: assignment within conditional expression */ +#pragma warning(disable:4706) + +/* warn C4214: bit field types other than int */ +#pragma warning(disable:4214) + + +#endif /* __ACINTEL_H__ */ diff --git a/source/include/platform/aclinux.h b/source/include/platform/aclinux.h new file mode 100644 index 000000000000..edfff150ed58 --- /dev/null +++ b/source/include/platform/aclinux.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. for Linux + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACLINUX_H__ +#define __ACLINUX_H__ + +/* Common (in-kernel/user-space) ACPICA configuration */ + +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_DO_WHILE_0 +#define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE + + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Host-dependent types and defines for in-kernel ACPICA */ + +#define ACPI_MACHINE_WIDTH BITS_PER_LONG +#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol); +#define strtoul simple_strtoul + +#define ACPI_CACHE_T struct kmem_cache +#define ACPI_SPINLOCK spinlock_t * +#define ACPI_CPU_FLAGS unsigned long + +#else /* !__KERNEL__ */ + +#include +#include +#include +#include +#include + +/* Host-dependent types and defines for user-space ACPICA */ + +#define ACPI_FLUSH_CPU_CACHE() + +#if defined(__ia64__) || defined(__x86_64__) +#define ACPI_MACHINE_WIDTH 64 +#define COMPILER_DEPENDENT_INT64 long +#define COMPILER_DEPENDENT_UINT64 unsigned long +#define ACPI_CAST_PTHREAD_T(pthread) ((ACPI_THREAD_ID) (pthread)) +#else +#define ACPI_MACHINE_WIDTH 32 +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_CAST_PTHREAD_T(pthread) ((ACPI_THREAD_ID) (UINT32) (void *) (pthread)) +#endif + +#ifndef __cdecl +#define __cdecl +#endif + +#endif /* __KERNEL__ */ + +/* Linux uses GCC */ + +#include "acgcc.h" + + +#ifdef __KERNEL__ +/* + * Overrides for in-kernel ACPICA + */ +static inline acpi_thread_id acpi_os_get_thread_id(void) +{ + return current; +} + +/* + * The irqs_disabled() check is for resume from RAM. + * Interrupts are off during resume, just like they are for boot. + * However, boot has (system_state != SYSTEM_RUNNING) + * to quiet __might_sleep() in kmalloc() and resume does not. + */ +#include +static inline void *acpi_os_allocate(acpi_size size) +{ + return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); +} + +static inline void *acpi_os_allocate_zeroed(acpi_size size) +{ + return kzalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); +} + +static inline void *acpi_os_acquire_object(acpi_cache_t * cache) +{ + return kmem_cache_zalloc(cache, + irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); +} + +#define ACPI_ALLOCATE(a) acpi_os_allocate(a) +#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) +#define ACPI_FREE(a) kfree(a) + +/* Used within ACPICA to show where it is safe to preempt execution */ + +#define ACPI_PREEMPTION_POINT() \ + do { \ + if (!irqs_disabled()) \ + cond_resched(); \ + } while (0) + +#endif /* __KERNEL__ */ + +#endif /* __ACLINUX_H__ */ diff --git a/source/include/platform/acmsvc.h b/source/include/platform/acmsvc.h new file mode 100644 index 000000000000..b73a62caf1d5 --- /dev/null +++ b/source/include/platform/acmsvc.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Name: acmsvc.h - VC specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACMSVC_H__ +#define __ACMSVC_H__ + + +/* + * Map low I/O functions for MS. This allows us to disable MS language + * extensions for maximum portability. + */ +#define open _open +#define read _read +#define write _write +#define close _close +#define stat _stat +#define fstat _fstat +#define mkdir _mkdir +#define strlwr _strlwr +#define O_RDONLY _O_RDONLY +#define O_BINARY _O_BINARY +#define O_CREAT _O_CREAT +#define O_WRONLY _O_WRONLY +#define O_TRUNC _O_TRUNC +#define S_IREAD _S_IREAD +#define S_IWRITE _S_IWRITE +#define S_IFDIR _S_IFDIR + +/* Eliminate warnings for "old" (non-secure) versions of clib functions */ + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +/* Eliminate warnings for POSIX clib function names (open, write, etc.) */ + +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE +#endif + +#define COMPILER_DEPENDENT_INT64 __int64 +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 +#define ACPI_INLINE __inline + +/* + * Calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#define ACPI_SYSTEM_XFACE __cdecl +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE __cdecl + +#ifndef _LINT +/* + * Math helper functions + */ +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ +{ \ + __asm mov edx, n_hi \ + __asm mov eax, n_lo \ + __asm div d32 \ + __asm mov q32, eax \ + __asm mov r32, edx \ +} + +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ +{ \ + __asm shr n_hi, 1 \ + __asm rcr n_lo, 1 \ +} +#else + +/* Fake versions to make lint happy */ + +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ +{ \ + q32 = n_hi / d32; \ + r32 = n_lo / d32; \ +} + +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ +{ \ + n_hi >>= 1; \ + n_lo >>= 1; \ +} +#endif + +/* warn C4100: unreferenced formal parameter */ +#pragma warning(disable:4100) + +/* warn C4127: conditional expression is constant */ +#pragma warning(disable:4127) + +/* warn C4706: assignment within conditional expression */ +#pragma warning(disable:4706) + +/* warn C4131: uses old-style declarator (iASL compiler only) */ +#pragma warning(disable:4131) + +#if _MSC_VER > 1200 /* Versions above VC++ 6 */ +#pragma warning( disable : 4295 ) /* needed for acpredef.h array */ +#endif + +#endif /* __ACMSVC_H__ */ diff --git a/source/include/platform/acnetbsd.h b/source/include/platform/acnetbsd.h new file mode 100644 index 000000000000..23b0e8c4c3f1 --- /dev/null +++ b/source/include/platform/acnetbsd.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * Name: acnetbsd.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACNETBSD_H__ +#define __ACNETBSD_H__ + +/* NetBSD uses GCC */ + +#include "acgcc.h" + +#ifdef _LP64 +#define ACPI_MACHINE_WIDTH 64 +#else +#define ACPI_MACHINE_WIDTH 32 +#endif + +#define COMPILER_DEPENDENT_INT64 int64_t +#define COMPILER_DEPENDENT_UINT64 uint64_t + +#ifdef _KERNEL +#include "opt_acpi.h" /* collect build-time options here */ + +#include +#include +#include +#include + +#define asm __asm + +#define ACPI_USE_NATIVE_DIVIDE + +#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE + +#ifdef ACPI_DEBUG +#define ACPI_DEBUG_OUTPUT +#define ACPI_DBG_TRACK_ALLOCATIONS +#ifdef DEBUGGER_THREADING +#undef DEBUGGER_THREADING +#endif /* DEBUGGER_THREADING */ +#define DEBUGGER_THREADING 0 /* integrated with DDB */ +#include "opt_ddb.h" +#ifdef DDB +#define ACPI_DISASSEMBLER +#define ACPI_DEBUGGER +#endif /* DDB */ +#endif /* ACPI_DEBUG */ + +static __inline int +isprint(int ch) +{ + return(isspace(ch) || isascii(ch)); +} + +#else /* _KERNEL */ + +#include + +/* Not building kernel code, so use libc */ +#define ACPI_USE_STANDARD_HEADERS + +#define __cli() +#define __sti() + +/* XXX */ +#define __inline inline + +#endif /* _KERNEL */ + +/* Always use NetBSD code over our local versions */ +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_NATIVE_DIVIDE + +#endif /* __ACNETBSD_H__ */ diff --git a/source/include/platform/acos2.h b/source/include/platform/acos2.h new file mode 100644 index 000000000000..0704c50161f7 --- /dev/null +++ b/source/include/platform/acos2.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * + * Name: acos2.h - OS/2 specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACOS2_H__ +#define __ACOS2_H__ +#define INCL_LONGLONG +#include + + +#define ACPI_MACHINE_WIDTH 32 + +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_USE_NATIVE_DIVIDE + +#define ACPI_SYSTEM_XFACE APIENTRY +#define ACPI_EXTERNAL_XFACE APIENTRY +#define ACPI_INTERNAL_XFACE APIENTRY +#define ACPI_INTERNAL_VAR_XFACE APIENTRY + +/* + * Some compilers complain about unused variables. Sometimes we don't want to + * use all the variables (most specifically for _THIS_MODULE). This allow us + * to to tell the compiler warning in a per-variable manner that a variable + * is unused. + */ +#define ACPI_UNUSED_VAR + +#define ACPI_USE_STANDARD_HEADERS +#include + +#define ACPI_FLUSH_CPU_CACHE() Wbinvd() +void Wbinvd(void); + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) Acq = OSPMAcquireGlobalLock(GLptr) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pnd) Pnd = OSPMReleaseGlobalLock(GLptr) +unsigned short OSPMAcquireGlobalLock (void *); +unsigned short OSPMReleaseGlobalLock (void *); + +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ +{ \ + unsigned long long val = 0LL; \ + val = n_lo | ( ((unsigned long long)h_hi) << 32 ); \ + __llrotr (val,1); \ + n_hi = (unsigned long)((val >> 32 ) & 0xffffffff ); \ + n_lo = (unsigned long)(val & 0xffffffff); \ +} + +#ifndef ACPI_ASL_COMPILER +#define ACPI_USE_LOCAL_CACHE +#undef ACPI_DEBUGGER +#endif + +#endif /* __ACOS2_H__ */ diff --git a/source/include/platform/acwin.h b/source/include/platform/acwin.h new file mode 100644 index 000000000000..c7d4bcd3860e --- /dev/null +++ b/source/include/platform/acwin.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * Name: acwin.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACWIN_H__ +#define __ACWIN_H__ + +/*! [Begin] no source code translation (Keep the include) */ + +/* Windows uses VC */ +#ifdef _MSC_VER +#include "acmsvc.h" +#endif +/*! [End] no source code translation !*/ + +#define ACPI_MACHINE_WIDTH 32 + +#define ACPI_USE_STANDARD_HEADERS + +#ifdef ACPI_DEFINE_ALTERNATE_TYPES +/* + * Types used only in (Linux) translated source, defined here to enable + * cross-platform compilation (i.e., generate the Linux code on Windows, + * for test purposes only) + */ +typedef int s32; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef COMPILER_DEPENDENT_UINT64 u64; +#endif + + +/* + * Handle platform- and compiler-specific assembly language differences. + * + * Notes: + * 1) Interrupt 3 is used to break into a debugger + * 2) Interrupts are turned off during ACPI register setup + */ + +/*! [Begin] no source code translation */ + +#ifdef ACPI_APPLICATION +#define ACPI_FLUSH_CPU_CACHE() +#else +#define ACPI_FLUSH_CPU_CACHE() __asm {WBINVD} +#endif + +#ifdef _DEBUG +#define ACPI_SIMPLE_RETURN_MACROS +#endif + +/*! [End] no source code translation !*/ + +/* + * Global Lock acquire/release code + * + * Note: Handles case where the FACS pointer is null + */ +#define ACPI_ACQUIRE_GLOBAL_LOCK(FacsPtr, Acq) __asm \ +{ \ + __asm mov eax, 0xFF \ + __asm mov ecx, FacsPtr \ + __asm or ecx, ecx \ + __asm jz exit_acq \ + __asm lea ecx, [ecx].GlobalLock \ + \ + __asm acq10: \ + __asm mov eax, [ecx] \ + __asm mov edx, eax \ + __asm and edx, 0xFFFFFFFE \ + __asm bts edx, 1 \ + __asm adc edx, 0 \ + __asm lock cmpxchg dword ptr [ecx], edx \ + __asm jnz acq10 \ + \ + __asm cmp dl, 3 \ + __asm sbb eax, eax \ + \ + __asm exit_acq: \ + __asm mov Acq, al \ +} + +#define ACPI_RELEASE_GLOBAL_LOCK(FacsPtr, Pnd) __asm \ +{ \ + __asm xor eax, eax \ + __asm mov ecx, FacsPtr \ + __asm or ecx, ecx \ + __asm jz exit_rel \ + __asm lea ecx, [ecx].GlobalLock \ + \ + __asm Rel10: \ + __asm mov eax, [ecx] \ + __asm mov edx, eax \ + __asm and edx, 0xFFFFFFFC \ + __asm lock cmpxchg dword ptr [ecx], edx \ + __asm jnz Rel10 \ + \ + __asm cmp dl, 3 \ + __asm and eax, 1 \ + \ + __asm exit_rel: \ + __asm mov Pnd, al \ +} + +#endif /* __ACWIN_H__ */ diff --git a/source/include/platform/acwin64.h b/source/include/platform/acwin64.h new file mode 100644 index 000000000000..022baf050e71 --- /dev/null +++ b/source/include/platform/acwin64.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * Name: acwin64.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACWIN64_H__ +#define __ACWIN64_H__ + +/*! [Begin] no source code translation (Keep the include) */ + +#include "acintel.h" +/*! [End] no source code translation !*/ + +#define ACPI_MACHINE_WIDTH 64 + +#define ACPI_USE_STANDARD_HEADERS + +/* + * Handle platform- and compiler-specific assembly language differences. + * + * Notes: + * 1) Interrupt 3 is used to break into a debugger + * 2) Interrupts are turned off during ACPI register setup + */ + +/*! [Begin] no source code translation */ + +#define ACPI_FLUSH_CPU_CACHE() + +/* + * For Acpi applications, we don't want to try to access the global lock + */ +#ifdef ACPI_APPLICATION +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) if (AcpiGbl_GlobalLockPresent) {Acq = 0xFF;} else {Acq = 0;} +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pnd) if (AcpiGbl_GlobalLockPresent) {Pnd = 0xFF;} else {Pnd = 0;} +#else + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pnd) + +#endif + + +#endif /* __ACWIN_H__ */ diff --git a/source/os_specific/service_layers/osunixdir.c b/source/os_specific/service_layers/osunixdir.c new file mode 100644 index 000000000000..20b153c3d485 --- /dev/null +++ b/source/os_specific/service_layers/osunixdir.c @@ -0,0 +1,251 @@ + +/****************************************************************************** + * + * Module Name: osunixdir - Unix directory access interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "acpisrc.h" + +/* + * Allocated structure returned from OsOpenDirectory + */ +typedef struct ExternalFindInfo +{ + char *DirPathname; + DIR *DirPtr; + char temp_buffer[128]; + char *WildcardSpec; + char RequestedFileType; + +} EXTERNAL_FIND_INFO; + + +/******************************************************************************* + * + * FUNCTION: AcpiOsOpenDirectory + * + * PARAMETERS: DirPathname - Full pathname to the directory + * WildcardSpec - string of the form "*.c", etc. + * + * RETURN: A directory "handle" to be used in subsequent search operations. + * NULL returned on failure. + * + * DESCRIPTION: Open a directory in preparation for a wildcard search + * + ******************************************************************************/ + +void * +AcpiOsOpenDirectory ( + char *DirPathname, + char *WildcardSpec, + char RequestedFileType) +{ + EXTERNAL_FIND_INFO *ExternalInfo; + DIR *dir; + + + /* Allocate the info struct that will be returned to the caller */ + + ExternalInfo = calloc (sizeof (EXTERNAL_FIND_INFO), 1); + if (!ExternalInfo) + { + return (NULL); + } + + /* Get the directory stream */ + + dir = opendir (DirPathname); + if (!dir) + { + free (ExternalInfo); + return (NULL); + } + + /* Save the info in the return structure */ + + ExternalInfo->WildcardSpec = WildcardSpec; + ExternalInfo->RequestedFileType = RequestedFileType; + ExternalInfo->DirPathname = DirPathname; + ExternalInfo->DirPtr = dir; + return (ExternalInfo); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsGetNextFilename + * + * PARAMETERS: DirHandle - Created via AcpiOsOpenDirectory + * + * RETURN: Next filename matched. NULL if no more matches. + * + * DESCRIPTION: Get the next file in the directory that matches the wildcard + * specification. + * + ******************************************************************************/ + +char * +AcpiOsGetNextFilename ( + void *DirHandle) +{ + EXTERNAL_FIND_INFO *ExternalInfo = DirHandle; + struct dirent *dir_entry; + char *temp_str; + int str_len; + struct stat temp_stat; + int err; + + + while ((dir_entry = readdir (ExternalInfo->DirPtr))) + { + if (!fnmatch (ExternalInfo->WildcardSpec, dir_entry->d_name, 0)) + { + if (dir_entry->d_name[0] == '.') + { + continue; + } + + str_len = strlen (dir_entry->d_name) + + strlen (ExternalInfo->DirPathname) + 2; + + temp_str = calloc (str_len, 1); + if (!temp_str) + { + printf ("Could not allocate buffer for temporary string\n"); + return (NULL); + } + + strcpy (temp_str, ExternalInfo->DirPathname); + strcat (temp_str, "/"); + strcat (temp_str, dir_entry->d_name); + + err = stat (temp_str, &temp_stat); + free (temp_str); + if (err == -1) + { + printf ("stat() error - should not happen\n"); + return (NULL); + } + + if ((S_ISDIR (temp_stat.st_mode) + && (ExternalInfo->RequestedFileType == REQUEST_DIR_ONLY)) + || + ((!S_ISDIR (temp_stat.st_mode) + && ExternalInfo->RequestedFileType == REQUEST_FILE_ONLY))) + { + /* copy to a temp buffer because dir_entry struct is on the stack */ + + strcpy (ExternalInfo->temp_buffer, dir_entry->d_name); + return (ExternalInfo->temp_buffer); + } + } + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsCloseDirectory + * + * PARAMETERS: DirHandle - Created via AcpiOsOpenDirectory + * + * RETURN: None. + * + * DESCRIPTION: Close the open directory and cleanup. + * + ******************************************************************************/ + +void +AcpiOsCloseDirectory ( + void *DirHandle) +{ + EXTERNAL_FIND_INFO *ExternalInfo = DirHandle; + + + /* Close the directory and free allocations */ + + closedir (ExternalInfo->DirPtr); + free (DirHandle); +} + + +/* Other functions acpisrc uses but that aren't standard on Unix */ + +/******************************************************************************* + * + * FUNCTION: strlwr + * + * PARAMETERS: str - String to be lowercased. + * + * RETURN: str. + * + * DESCRIPTION: Lowercase a string in-place. + * + ******************************************************************************/ + +char * +strlwr ( + char *str) +{ + int length; + int i; + + + length = strlen (str); + + for (i = 0; i < length; i++) + { + str[i] = tolower ((int) str[i]); + } + + return (str); +} diff --git a/source/os_specific/service_layers/osunixxf.c b/source/os_specific/service_layers/osunixxf.c new file mode 100644 index 000000000000..a0899d208d2a --- /dev/null +++ b/source/os_specific/service_layers/osunixxf.c @@ -0,0 +1,1243 @@ +/****************************************************************************** + * + * Module Name: osunixxf - UNIX OSL interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* + * These interfaces are required in order to compile the ASL compiler and the + * various ACPICA tools under Linux or other Unix-like system. + * + * Note: Use #define __APPLE__ for OS X generation. + */ +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdebug.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_OS_SERVICES + ACPI_MODULE_NAME ("osunixxf") + + +extern FILE *AcpiGbl_DebugFile; +FILE *AcpiGbl_OutputFile; + + +/* Upcalls to AcpiExec */ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + +void +AeTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); + +typedef void* (*PTHREAD_CALLBACK) (void *); + +/* Apple-specific */ + +#ifdef __APPLE__ +#define sem_destroy sem_close +#endif + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInitialize, AcpiOsTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init and terminate. Nothing to do. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsInitialize ( + void) +{ + + AcpiGbl_OutputFile = stdout; + return (AE_OK); +} + + +ACPI_STATUS +AcpiOsTerminate ( + void) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetRootPointer + * + * PARAMETERS: None + * + * RETURN: RSDP physical address + * + * DESCRIPTION: Gets the ACPI root pointer (RSDP) + * + *****************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void) +{ + + return (AeLocalGetRootPointer ()); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPredefinedOverride + * + * PARAMETERS: InitVal - Initial value of the predefined object + * NewVal - The new value for the object + * + * RETURN: Status, pointer to value. Null pointer returned if not + * overriding. + * + * DESCRIPTION: Allow the OS to override predefined names + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal) +{ + + if (!InitVal || !NewVal) + { + return (AE_BAD_PARAMETER); + } + + *NewVal = NULL; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably + * firmware) + * NewTable - Where an entire new table is returned. + * + * RETURN: Status, pointer to new table. Null pointer returned if no + * table is available to override + * + * DESCRIPTION: Return a different version of a table if one is available + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable) +{ + + if (!ExistingTable || !NewTable) + { + return (AE_BAD_PARAMETER); + } + + *NewTable = NULL; + +#ifdef ACPI_EXEC_APP + + AeTableOverride (ExistingTable, NewTable); + return (AE_OK); +#else + + return (AE_NO_ACPI_TABLES); +#endif +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPhysicalTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably firmware) + * NewAddress - Where new table address is returned + * (Physical address) + * NewTableLength - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength) +{ + + return (AE_SUPPORT); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsRedirectOutput + * + * PARAMETERS: Destination - An open file handle/pointer + * + * RETURN: None + * + * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf + * + *****************************************************************************/ + +void +AcpiOsRedirectOutput ( + void *Destination) +{ + + AcpiGbl_OutputFile = Destination; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPrintf + * + * PARAMETERS: fmt, ... - Standard printf format + * + * RETURN: None + * + * DESCRIPTION: Formatted output + * + *****************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiOsPrintf ( + const char *Fmt, + ...) +{ + va_list Args; + + + va_start (Args, Fmt); + AcpiOsVprintf (Fmt, Args); + va_end (Args); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsVprintf + * + * PARAMETERS: fmt - Standard printf format + * args - Argument list + * + * RETURN: None + * + * DESCRIPTION: Formatted output with argument list pointer + * + *****************************************************************************/ + +void +AcpiOsVprintf ( + const char *Fmt, + va_list Args) +{ + UINT8 Flags; + + + Flags = AcpiGbl_DbOutputFlags; + if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT) + { + /* Output is directable to either a file (if open) or the console */ + + if (AcpiGbl_DebugFile) + { + /* Output file is open, send the output there */ + + vfprintf (AcpiGbl_DebugFile, Fmt, Args); + } + else + { + /* No redirection, send output to console (once only!) */ + + Flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (Flags & ACPI_DB_CONSOLE_OUTPUT) + { + vfprintf (AcpiGbl_OutputFile, Fmt, Args); + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetLine + * + * PARAMETERS: Buffer - Where to return the command line + * BufferLength - Maximum length of Buffer + * BytesRead - Where the actual byte count is returned + * + * RETURN: Status and actual bytes read + * + * DESCRIPTION: Formatted input with argument list pointer + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsGetLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead) +{ + UINT8 Temp; + UINT32 i; + + + for (i = 0; ; i++) + { + if (i >= BufferLength) + { + return (AE_BUFFER_OVERFLOW); + } + + scanf ("%1c", &Temp); + if (!Temp || Temp == '\n') + { + break; + } + + Buffer [i] = Temp; + } + + /* Null terminate the buffer */ + + Buffer [i] = 0; + + /* Return the number of bytes in the string */ + + if (BytesRead) + { + *BytesRead = i; + } + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsMapMemory + * + * PARAMETERS: where - Physical address of memory to be mapped + * length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into caller's address space + * + *****************************************************************************/ + +void * +AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS where, + ACPI_SIZE length) +{ + + return (ACPI_TO_POINTER ((ACPI_SIZE) where)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsUnmapMemory + * + * PARAMETERS: where - Logical address of memory to be unmapped + * length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void +AcpiOsUnmapMemory ( + void *where, + ACPI_SIZE length) +{ + + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsAllocate + * + * PARAMETERS: Size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void * +AcpiOsAllocate ( + ACPI_SIZE size) +{ + void *Mem; + + + Mem = (void *) malloc ((size_t) size); + return (Mem); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsFree + * + * PARAMETERS: mem - Pointer to previously allocated memory + * + * RETURN: None. + * + * DESCRIPTION: Free memory allocated via AcpiOsAllocate + * + *****************************************************************************/ + +void +AcpiOsFree ( + void *mem) +{ + + free (mem); +} + + +#ifdef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: Semaphore stub functions + * + * DESCRIPTION: Stub functions used for single-thread applications that do + * not require semaphore synchronization. Full implementations + * of these functions appear after the stubs. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_HANDLE *OutHandle) +{ + *OutHandle = (ACPI_HANDLE) 1; + return (AE_OK); +} + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_HANDLE Handle) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units, + UINT16 Timeout) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units) +{ + return (AE_OK); +} + +#else +/****************************************************************************** + * + * FUNCTION: AcpiOsCreateSemaphore + * + * PARAMETERS: InitialUnits - Units to be assigned to the new semaphore + * OutHandle - Where a handle will be returned + * + * RETURN: Status + * + * DESCRIPTION: Create an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_HANDLE *OutHandle) +{ + sem_t *Sem; + + + if (!OutHandle) + { + return (AE_BAD_PARAMETER); + } + +#ifdef __APPLE__ + { + char *SemaphoreName = tmpnam (NULL); + + Sem = sem_open (SemaphoreName, O_EXCL|O_CREAT, 0755, InitialUnits); + if (!Sem) + { + return (AE_NO_MEMORY); + } + sem_unlink (SemaphoreName); /* This just deletes the name */ + } + +#else + Sem = AcpiOsAllocate (sizeof (sem_t)); + if (!Sem) + { + return (AE_NO_MEMORY); + } + + if (sem_init (Sem, 0, InitialUnits) == -1) + { + AcpiOsFree (Sem); + return (AE_BAD_PARAMETER); + } +#endif + + *OutHandle = (ACPI_HANDLE) Sem; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsDeleteSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * + * RETURN: Status + * + * DESCRIPTION: Delete an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_HANDLE Handle) +{ + sem_t *Sem = (sem_t *) Handle; + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + + if (sem_destroy (Sem) == -1) + { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWaitSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - How many units to wait for + * Timeout - How long to wait + * + * RETURN: Status + * + * DESCRIPTION: Wait for units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units, + UINT16 Timeout) +{ + ACPI_STATUS Status = AE_OK; + sem_t *Sem = (sem_t *) Handle; + struct timespec T; + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + + switch (Timeout) + { + /* + * No Wait: + * -------- + * A zero timeout value indicates that we shouldn't wait - just + * acquire the semaphore if available otherwise return AE_TIME + * (a.k.a. 'would block'). + */ + case 0: + + if (sem_trywait(Sem) == -1) + { + Status = (AE_TIME); + } + break; + + /* Wait Indefinitely */ + + case ACPI_WAIT_FOREVER: + + if (sem_wait (Sem)) + { + Status = (AE_TIME); + } + break; + + /* Wait with Timeout */ + + default: + + T.tv_sec = Timeout / 1000; + T.tv_nsec = (Timeout - (T.tv_sec * 1000)) * 1000000; + +#ifdef ACPI_USE_ALTERNATE_TIMEOUT + /* + * Alternate timeout mechanism for environments where + * sem_timedwait is not available or does not work properly. + */ + while (Timeout) + { + if (sem_trywait (Sem) == 0) + { + /* Got the semaphore */ + return (AE_OK); + } + usleep (1000); /* one millisecond */ + Timeout--; + } + Status = (AE_TIME); +#else + + if (sem_timedwait (Sem, &T)) + { + Status = (AE_TIME); + } +#endif + + break; + } + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignalSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - Number of units to send + * + * RETURN: Status + * + * DESCRIPTION: Send units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units) +{ + sem_t *Sem = (sem_t *)Handle; + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + + if (sem_post (Sem) == -1) + { + return (AE_LIMIT); + } + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + + +/****************************************************************************** + * + * FUNCTION: Spinlock interfaces + * + * DESCRIPTION: Map these interfaces to semaphore interfaces + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateLock ( + ACPI_SPINLOCK *OutHandle) +{ + + return (AcpiOsCreateSemaphore (1, 1, OutHandle)); +} + + +void +AcpiOsDeleteLock ( + ACPI_SPINLOCK Handle) +{ + AcpiOsDeleteSemaphore (Handle); +} + + +ACPI_CPU_FLAGS +AcpiOsAcquireLock ( + ACPI_HANDLE Handle) +{ + AcpiOsWaitSemaphore (Handle, 1, 0xFFFF); + return (0); +} + + +void +AcpiOsReleaseLock ( + ACPI_SPINLOCK Handle, + ACPI_CPU_FLAGS Flags) +{ + AcpiOsSignalSemaphore (Handle, 1); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInstallInterruptHandler + * + * PARAMETERS: InterruptNumber - Level handler should respond to. + * Isr - Address of the ACPI interrupt handler + * ExceptPtr - Where status is returned + * + * RETURN: Handle to the newly installed handler. + * + * DESCRIPTION: Install an interrupt handler. Used to install the ACPI + * OS-independent handler. + * + *****************************************************************************/ + +UINT32 +AcpiOsInstallInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine, + void *Context) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsRemoveInterruptHandler + * + * PARAMETERS: Handle - Returned when handler was installed + * + * RETURN: Status + * + * DESCRIPTION: Uninstalls an interrupt handler. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsRemoveInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsStall + * + * PARAMETERS: microseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at microsecond granularity + * + *****************************************************************************/ + +void +AcpiOsStall ( + UINT32 microseconds) +{ + + if (microseconds) + { + usleep (microseconds); + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSleep + * + * PARAMETERS: milliseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at millisecond granularity + * + *****************************************************************************/ + +void +AcpiOsSleep ( + UINT64 milliseconds) +{ + + sleep (milliseconds / 1000); /* Sleep for whole seconds */ + + /* + * Arg to usleep() must be less than 1,000,000 (1 second) + */ + usleep ((milliseconds % 1000) * 1000); /* Sleep for remaining usecs */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetTimer + * + * PARAMETERS: None + * + * RETURN: Current time in 100 nanosecond units + * + * DESCRIPTION: Get the current system time + * + *****************************************************************************/ + +UINT64 +AcpiOsGetTimer ( + void) +{ + struct timeval time; + + + gettimeofday (&time, NULL); + + /* Seconds * 10^7 = 100ns(10^-7), Microseconds(10^-6) * 10^1 = 100ns */ + + return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * Register - Device Register + * Value - Buffer where value is placed + * Width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Read data from PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + UINT64 *Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * Register - Device Register + * Value - Value to be written + * Width - Number of bits + * + * RETURN: Status. + * + * DESCRIPTION: Write data to PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPort + * + * PARAMETERS: Address - Address of I/O port/register to read + * Value - Where value is placed + * Width - Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + + switch (Width) + { + case 8: + *Value = 0xFF; + break; + + case 16: + *Value = 0xFFFF; + break; + + case 32: + *Value = 0xFFFFFFFF; + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePort + * + * PARAMETERS: Address - Address of I/O port/register to write + * Value - Value to write + * Width - Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadMemory + * + * PARAMETERS: Address - Physical Memory Address to read + * Value - Where value is placed + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. + * + * DESCRIPTION: Read data from a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 *Value, + UINT32 Width) +{ + + switch (Width) + { + case 8: + case 16: + case 32: + case 64: + *Value = 0; + break; + + default: + return (AE_BAD_PARAMETER); + } + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWriteMemory + * + * PARAMETERS: Address - Physical Memory Address to write + * Value - Value to write + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: None + * + * DESCRIPTION: Write data to a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if readable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for reading + * + *****************************************************************************/ + +BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return (TRUE); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if writable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for writing + * + *****************************************************************************/ + +BOOLEAN +AcpiOsWritable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return (TRUE); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignal + * + * PARAMETERS: Function - ACPI CA signal function code + * Info - Pointer to function-dependent structure + * + * RETURN: Status + * + * DESCRIPTION: Miscellaneous functions. Example implementation only. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info) +{ + + switch (Function) + { + case ACPI_SIGNAL_FATAL: + break; + + case ACPI_SIGNAL_BREAKPOINT: + break; + + default: + break; + } + + return (AE_OK); +} + +/* Optional multi-thread support */ + +#ifndef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: AcpiOsGetThreadId + * + * PARAMETERS: None + * + * RETURN: Id of the running thread + * + * DESCRIPTION: Get the ID of the current (running) thread + * + *****************************************************************************/ + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + pthread_t thread; + + + thread = pthread_self(); + return (ACPI_CAST_PTHREAD_T (thread)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsExecute + * + * PARAMETERS: Type - Type of execution + * Function - Address of the function to execute + * Context - Passed as a parameter to the function + * + * RETURN: Status. + * + * DESCRIPTION: Execute a new thread + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + pthread_t thread; + int ret; + + + ret = pthread_create (&thread, NULL, (PTHREAD_CALLBACK) Function, Context); + if (ret) + { + AcpiOsPrintf("Create thread failed"); + } + return (0); +} + +#endif /* ACPI_SINGLE_THREADED */ diff --git a/source/os_specific/service_layers/oswindir.c b/source/os_specific/service_layers/oswindir.c new file mode 100644 index 000000000000..2cdcb945860b --- /dev/null +++ b/source/os_specific/service_layers/oswindir.c @@ -0,0 +1,251 @@ + +/****************************************************************************** + * + * Module Name: oswindir - Windows directory access interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include + +#include +#include +#include +#include + +typedef struct ExternalFindInfo +{ + struct _finddata_t DosInfo; + char *FullWildcardSpec; + long FindHandle; + char State; + char RequestedFileType; + +} EXTERNAL_FIND_INFO; + + +/******************************************************************************* + * + * FUNCTION: AcpiOsOpenDirectory + * + * PARAMETERS: DirPathname - Full pathname to the directory + * WildcardSpec - string of the form "*.c", etc. + * RequestedFileType - Either a directory or normal file + * + * RETURN: A directory "handle" to be used in subsequent search operations. + * NULL returned on failure. + * + * DESCRIPTION: Open a directory in preparation for a wildcard search + * + ******************************************************************************/ + +void * +AcpiOsOpenDirectory ( + char *DirPathname, + char *WildcardSpec, + char RequestedFileType) +{ + long FindHandle; + char *FullWildcardSpec; + EXTERNAL_FIND_INFO *SearchInfo; + + + /* No directory path means "use current directory" - use a dot */ + + if (!DirPathname || strlen (DirPathname) == 0) + { + DirPathname = "."; + } + + /* Allocate the info struct that will be returned to the caller */ + + SearchInfo = calloc (sizeof (EXTERNAL_FIND_INFO), 1); + if (!SearchInfo) + { + return (NULL); + } + + /* Allocate space for the full wildcard path */ + + FullWildcardSpec = calloc (strlen (DirPathname) + strlen (WildcardSpec) + 2, 1); + if (!FullWildcardSpec) + { + printf ("Could not allocate buffer for wildcard pathname\n"); + return (NULL); + } + + /* Create the full wildcard path */ + + strcpy (FullWildcardSpec, DirPathname); + strcat (FullWildcardSpec, "/"); + strcat (FullWildcardSpec, WildcardSpec); + + /* Initialize the find functions, get first match */ + + FindHandle = _findfirst (FullWildcardSpec, &SearchInfo->DosInfo); + if (FindHandle == -1) + { + /* Failure means that no match was found */ + + free (FullWildcardSpec); + free (SearchInfo); + return (NULL); + } + + /* Save the info in the return structure */ + + SearchInfo->RequestedFileType = RequestedFileType; + SearchInfo->FullWildcardSpec = FullWildcardSpec; + SearchInfo->FindHandle = FindHandle; + SearchInfo->State = 0; + return (SearchInfo); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsGetNextFilename + * + * PARAMETERS: DirHandle - Created via AcpiOsOpenDirectory + * + * RETURN: Next filename matched. NULL if no more matches. + * + * DESCRIPTION: Get the next file in the directory that matches the wildcard + * specification. + * + ******************************************************************************/ + +char * +AcpiOsGetNextFilename ( + void *DirHandle) +{ + EXTERNAL_FIND_INFO *SearchInfo = DirHandle; + int Status; + char FileTypeNotMatched = 1; + + + /* + * Loop while we have matched files but not found any files of + * the requested type. + */ + while (FileTypeNotMatched) + { + /* On the first call, we already have the first match */ + + if (SearchInfo->State == 0) + { + /* No longer the first match */ + + SearchInfo->State = 1; + } + else + { + /* Get the next match */ + + Status = _findnext (SearchInfo->FindHandle, &SearchInfo->DosInfo); + if (Status != 0) + { + return (NULL); + } + } + + /* + * Found a match, now check to make sure that the file type + * matches the requested file type (directory or normal file) + * + * NOTE: use of the attrib field saves us from doing a very + * expensive stat() on the file! + */ + switch (SearchInfo->RequestedFileType) + { + case REQUEST_FILE_ONLY: + + /* Anything other than A_SUBDIR is OK */ + + if (!(SearchInfo->DosInfo.attrib & _A_SUBDIR)) + { + FileTypeNotMatched = 0; + } + break; + + case REQUEST_DIR_ONLY: + + /* Must have A_SUBDIR bit set */ + + if (SearchInfo->DosInfo.attrib & _A_SUBDIR) + { + FileTypeNotMatched = 0; + } + break; + + default: + return (NULL); + } + } + + return (SearchInfo->DosInfo.name); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsCloseDirectory + * + * PARAMETERS: DirHandle - Created via AcpiOsOpenDirectory + * + * RETURN: None + * + * DESCRIPTION: Close the open directory and cleanup. + * + ******************************************************************************/ + +void +AcpiOsCloseDirectory ( + void *DirHandle) +{ + EXTERNAL_FIND_INFO *SearchInfo = DirHandle; + + + /* Close the directory and free allocations */ + + _findclose (SearchInfo->FindHandle); + free (SearchInfo->FullWildcardSpec); + free (DirHandle); +} + diff --git a/source/os_specific/service_layers/oswintbl.c b/source/os_specific/service_layers/oswintbl.c new file mode 100644 index 000000000000..db34966a0d9e --- /dev/null +++ b/source/os_specific/service_layers/oswintbl.c @@ -0,0 +1,222 @@ +/****************************************************************************** + * + * Module Name: oswintbl - Windows OSL for obtaining ACPI tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpi.h" + +#ifdef WIN32 +#pragma warning(disable:4115) /* warning C4115: (caused by rpcasync.h) */ +#include + +#elif WIN64 +#include +#endif + +#define _COMPONENT ACPI_OS_SERVICES + ACPI_MODULE_NAME ("oswintbl") + + +static char KeyBuffer[64]; +static char ErrorBuffer[64]; + + +/* Little front-end to win FormatMessage */ + +char * +OsFormatException ( + LONG Status) +{ + + ErrorBuffer[0] = 0; + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, Status, 0, + ErrorBuffer, 64, NULL); + + return (ErrorBuffer); +} + + +/****************************************************************************** + * + * FUNCTION: OsGetTable + * + * PARAMETERS: Signature - ACPI Signature for desired table. must be + * a null terminated string. + * + * RETURN: Pointer to the table. NULL if failure. + * + * DESCRIPTION: Get an ACPI table from the Windows registry. + * + *****************************************************************************/ + +ACPI_TABLE_HEADER * +OsGetTable ( + char *Signature) +{ + HKEY Handle = NULL; + ULONG i; + LONG Status; + ULONG Type; + ULONG NameSize; + ULONG DataSize; + HKEY SubKey; + ACPI_TABLE_HEADER *ReturnTable; + + + /* Get a handle to the table key */ + + while (1) + { + ACPI_STRCPY (KeyBuffer, "HARDWARE\\ACPI\\"); + ACPI_STRCAT (KeyBuffer, Signature); + + Status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyBuffer, + 0L, KEY_READ, &Handle); + + if (Status != ERROR_SUCCESS) + { + /* + * Somewhere along the way, MS changed the registry entry for + * the FADT from + * HARDWARE/ACPI/FACP to + * HARDWARE/ACPI/FADT. + * + * This code allows for both. + */ + if (ACPI_COMPARE_NAME (Signature, "FACP")) + { + Signature = "FADT"; + } + else + { + AcpiOsPrintf ( + "Could not find %s in registry at %s: %s (Status=0x%X)\n", + Signature, KeyBuffer, OsFormatException (Status), Status); + return (NULL); + } + } + else + { + break; + } + } + + /* Actual data for table is down a couple levels */ + + for (i = 0; ;) + { + Status = RegEnumKey (Handle, i, KeyBuffer, sizeof (KeyBuffer)); + i += 1; + if (Status == ERROR_NO_MORE_ITEMS) + { + break; + } + + Status = RegOpenKey (Handle, KeyBuffer, &SubKey); + if (Status != ERROR_SUCCESS) + { + AcpiOsPrintf ("Could not open %s entry: %s\n", + Signature, OsFormatException (Status)); + return (NULL); + } + + RegCloseKey (Handle); + Handle = SubKey; + i = 0; + } + + /* Find the (binary) table entry */ + + for (i = 0; ;) + { + NameSize = sizeof (KeyBuffer); + Status = RegEnumValue (Handle, i, KeyBuffer, &NameSize, + NULL, &Type, NULL, 0); + if (Status != ERROR_SUCCESS) + { + AcpiOsPrintf ("Could not get %s registry entry: %s\n", + Signature, OsFormatException (Status)); + return (NULL); + } + + if (Type == REG_BINARY) + { + break; + } + i += 1; + } + + /* Get the size of the table */ + + Status = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, NULL, &DataSize); + if (Status != ERROR_SUCCESS) + { + AcpiOsPrintf ("Could not read the %s table size: %s\n", + Signature, OsFormatException (Status)); + return (NULL); + } + + /* Allocate a new buffer for the table */ + + ReturnTable = AcpiOsAllocate (DataSize); + if (!ReturnTable) + { + goto Cleanup; + } + + /* Get the actual table from the registry */ + + Status = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, + (UCHAR *) ReturnTable, &DataSize); + if (Status != ERROR_SUCCESS) + { + AcpiOsPrintf ("Could not read %s data: %s\n", + Signature, OsFormatException (Status)); + AcpiOsFree (ReturnTable); + return (NULL); + } + +Cleanup: + RegCloseKey (Handle); + return (ReturnTable); +} + diff --git a/source/os_specific/service_layers/oswinxf.c b/source/os_specific/service_layers/oswinxf.c new file mode 100644 index 000000000000..008dcb30c536 --- /dev/null +++ b/source/os_specific/service_layers/oswinxf.c @@ -0,0 +1,1481 @@ +/****************************************************************************** + * + * Module Name: oswinxf - Windows OSL + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#ifdef WIN32 +#pragma warning(disable:4115) /* warning C4115: named type definition in parentheses (caused by rpcasync.h> */ + +#include +#include + +#elif WIN64 +#include +#endif + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_OS_SERVICES + ACPI_MODULE_NAME ("oswinxf") + + +extern FILE *AcpiGbl_DebugFile; +extern BOOLEAN AcpiGbl_DebugTimeout; + +FILE *AcpiGbl_OutputFile; +UINT64 TimerFrequency; +char TableName[ACPI_NAME_SIZE + 1]; + +#define ACPI_OS_DEBUG_TIMEOUT 30000 /* 30 seconds */ + + +/* Upcalls to application */ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + +void +AeTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); + +ACPI_TABLE_HEADER * +OsGetTable ( + char *Signature); + + +/* + * Real semaphores are only used for a multi-threaded application + */ +#ifndef ACPI_SINGLE_THREADED + +/* Semaphore information structure */ + +typedef struct acpi_os_semaphore_info +{ + UINT16 MaxUnits; + UINT16 CurrentUnits; + void *OsHandle; + +} ACPI_OS_SEMAPHORE_INFO; + +/* Need enough semaphores to run the large aslts suite */ + +#define ACPI_OS_MAX_SEMAPHORES 256 + +ACPI_OS_SEMAPHORE_INFO AcpiGbl_Semaphores[ACPI_OS_MAX_SEMAPHORES]; + +#endif /* ACPI_SINGLE_THREADED */ + + +/****************************************************************************** + * + * FUNCTION: AcpiOsTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Nothing to do for windows + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsTerminate ( + void) +{ + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init this OSL + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsInitialize ( + void) +{ + LARGE_INTEGER LocalTimerFrequency; + + +#ifndef ACPI_SINGLE_THREADED + /* Clear the semaphore info array */ + + memset (AcpiGbl_Semaphores, 0x00, sizeof (AcpiGbl_Semaphores)); +#endif + + AcpiGbl_OutputFile = stdout; + + /* Get the timer frequency for use in AcpiOsGetTimer */ + + TimerFrequency = 0; + if (QueryPerformanceFrequency (&LocalTimerFrequency)) + { + /* Frequency is in ticks per second */ + + TimerFrequency = LocalTimerFrequency.QuadPart; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetRootPointer + * + * PARAMETERS: None + * + * RETURN: RSDP physical address + * + * DESCRIPTION: Gets the root pointer (RSDP) + * + *****************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void) +{ + + return (AeLocalGetRootPointer ()); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPredefinedOverride + * + * PARAMETERS: InitVal - Initial value of the predefined object + * NewVal - The new value for the object + * + * RETURN: Status, pointer to value. Null pointer returned if not + * overriding. + * + * DESCRIPTION: Allow the OS to override predefined names + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal) +{ + + if (!InitVal || !NewVal) + { + return (AE_BAD_PARAMETER); + } + + *NewVal = NULL; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably firmware) + * NewTable - Where an entire new table is returned. + * + * RETURN: Status, pointer to new table. Null pointer returned if no + * table is available to override + * + * DESCRIPTION: Return a different version of a table if one is available + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable) +{ + + if (!ExistingTable || !NewTable) + { + return (AE_BAD_PARAMETER); + } + + *NewTable = NULL; + + +#ifdef ACPI_EXEC_APP + + /* Call back up to AcpiExec */ + + AeTableOverride (ExistingTable, NewTable); +#endif + + +#ifdef ACPI_ASL_COMPILER + + /* Attempt to get the table from the registry */ + + /* Construct a null-terminated string from table signature */ + + TableName[ACPI_NAME_SIZE] = 0; + ACPI_STRNCPY (TableName, ExistingTable->Signature, ACPI_NAME_SIZE); + + *NewTable = OsGetTable (TableName); + if (*NewTable) + { + AcpiOsPrintf ("Table [%s] obtained from registry, %u bytes\n", + TableName, (*NewTable)->Length); + } + else + { + AcpiOsPrintf ("Could not read table %s from registry\n", TableName); + } +#endif + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPhysicalTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably firmware) + * NewAddress - Where new table address is returned + * (Physical address) + * NewTableLength - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength) +{ + + return (AE_SUPPORT); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetTimer + * + * PARAMETERS: None + * + * RETURN: Current ticks in 100-nanosecond units + * + * DESCRIPTION: Get the value of a system timer + * + ******************************************************************************/ + +UINT64 +AcpiOsGetTimer ( + void) +{ + LARGE_INTEGER Timer; + + + /* Attempt to use hi-granularity timer first */ + + if (TimerFrequency && + QueryPerformanceCounter (&Timer)) + { + /* Convert to 100 nanosecond ticks */ + + return ((UINT64) ((Timer.QuadPart * (UINT64) 10000000) / TimerFrequency)); + } + + /* Fall back to the lo-granularity timer */ + + else + { + /* Convert milliseconds to 100 nanosecond ticks */ + + return ((UINT64) GetTickCount() * 10000); + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if readable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for reading + * + *****************************************************************************/ + +BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return ((BOOLEAN) !IsBadReadPtr (Pointer, Length)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if writable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for writing + * + *****************************************************************************/ + +BOOLEAN +AcpiOsWritable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return ((BOOLEAN) !IsBadWritePtr (Pointer, Length)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsRedirectOutput + * + * PARAMETERS: Destination - An open file handle/pointer + * + * RETURN: None + * + * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf + * + *****************************************************************************/ + +void +AcpiOsRedirectOutput ( + void *Destination) +{ + + AcpiGbl_OutputFile = Destination; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPrintf + * + * PARAMETERS: Fmt, ... - Standard printf format + * + * RETURN: None + * + * DESCRIPTION: Formatted output + * + *****************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiOsPrintf ( + const char *Fmt, + ...) +{ + va_list Args; + + + va_start (Args, Fmt); + + AcpiOsVprintf (Fmt, Args); + + va_end (Args); + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsVprintf + * + * PARAMETERS: Fmt - Standard printf format + * Args - Argument list + * + * RETURN: None + * + * DESCRIPTION: Formatted output with argument list pointer + * + *****************************************************************************/ + +void +AcpiOsVprintf ( + const char *Fmt, + va_list Args) +{ + INT32 Count = 0; + UINT8 Flags; + + + Flags = AcpiGbl_DbOutputFlags; + if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT) + { + /* Output is directable to either a file (if open) or the console */ + + if (AcpiGbl_DebugFile) + { + /* Output file is open, send the output there */ + + Count = vfprintf (AcpiGbl_DebugFile, Fmt, Args); + } + else + { + /* No redirection, send output to console (once only!) */ + + Flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (Flags & ACPI_DB_CONSOLE_OUTPUT) + { + Count = vfprintf (AcpiGbl_OutputFile, Fmt, Args); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetLine + * + * PARAMETERS: Buffer - Where to return the command line + * BufferLength - Maximum length of Buffer + * BytesRead - Where the actual byte count is returned + * + * RETURN: Status and actual bytes read + * + * DESCRIPTION: Formatted input with argument list pointer + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsGetLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead) +{ + char Temp; + UINT32 i; + + + for (i = 0; ; i++) + { + if (i >= BufferLength) + { + return (AE_BUFFER_OVERFLOW); + } + + scanf ("%1c", &Temp); + if (!Temp || Temp == '\n') + { + break; + } + + Buffer [i] = Temp; + } + + /* Null terminate the buffer */ + + Buffer [i] = 0; + + /* Return the number of bytes in the string */ + + if (BytesRead) + { + *BytesRead = i; + } + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsMapMemory + * + * PARAMETERS: Where - Physical address of memory to be mapped + * Length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into caller's address space + * + *****************************************************************************/ + +void * +AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS Where, + ACPI_SIZE Length) +{ + + return (ACPI_TO_POINTER ((ACPI_SIZE) Where)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsUnmapMemory + * + * PARAMETERS: Where - Logical address of memory to be unmapped + * Length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void +AcpiOsUnmapMemory ( + void *Where, + ACPI_SIZE Length) +{ + + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsAllocate + * + * PARAMETERS: Size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void * +AcpiOsAllocate ( + ACPI_SIZE Size) +{ + void *Mem; + + + Mem = (void *) malloc ((size_t) Size); + + return (Mem); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsFree + * + * PARAMETERS: Mem - Pointer to previously allocated memory + * + * RETURN: None. + * + * DESCRIPTION: Free memory allocated via AcpiOsAllocate + * + *****************************************************************************/ + +void +AcpiOsFree ( + void *Mem) +{ + + free (Mem); +} + + +#ifdef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: Semaphore stub functions + * + * DESCRIPTION: Stub functions used for single-thread applications that do + * not require semaphore synchronization. Full implementations + * of these functions appear after the stubs. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_HANDLE *OutHandle) +{ + *OutHandle = (ACPI_HANDLE) 1; + return (AE_OK); +} + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_HANDLE Handle) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units, + UINT16 Timeout) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units) +{ + return (AE_OK); +} + +#else +/****************************************************************************** + * + * FUNCTION: AcpiOsCreateSemaphore + * + * PARAMETERS: MaxUnits - Maximum units that can be sent + * InitialUnits - Units to be assigned to the new semaphore + * OutHandle - Where a handle will be returned + * + * RETURN: Status + * + * DESCRIPTION: Create an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_SEMAPHORE *OutHandle) +{ + void *Mutex; + UINT32 i; + + ACPI_FUNCTION_NAME (OsCreateSemaphore); + + + if (MaxUnits == ACPI_UINT32_MAX) + { + MaxUnits = 255; + } + + if (InitialUnits == ACPI_UINT32_MAX) + { + InitialUnits = MaxUnits; + } + + if (InitialUnits > MaxUnits) + { + return (AE_BAD_PARAMETER); + } + + /* Find an empty slot */ + + for (i = 0; i < ACPI_OS_MAX_SEMAPHORES; i++) + { + if (!AcpiGbl_Semaphores[i].OsHandle) + { + break; + } + } + if (i >= ACPI_OS_MAX_SEMAPHORES) + { + ACPI_EXCEPTION ((AE_INFO, AE_LIMIT, + "Reached max semaphores (%u), could not create", ACPI_OS_MAX_SEMAPHORES)); + return (AE_LIMIT); + } + + /* Create an OS semaphore */ + + Mutex = CreateSemaphore (NULL, InitialUnits, MaxUnits, NULL); + if (!Mutex) + { + ACPI_ERROR ((AE_INFO, "Could not create semaphore")); + return (AE_NO_MEMORY); + } + + AcpiGbl_Semaphores[i].MaxUnits = (UINT16) MaxUnits; + AcpiGbl_Semaphores[i].CurrentUnits = (UINT16) InitialUnits; + AcpiGbl_Semaphores[i].OsHandle = Mutex; + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Handle=%u, Max=%u, Current=%u, OsHandle=%p\n", + i, MaxUnits, InitialUnits, Mutex)); + + *OutHandle = (void *) i; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsDeleteSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * + * RETURN: Status + * + * DESCRIPTION: Delete an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_SEMAPHORE Handle) +{ + UINT32 Index = (UINT32) Handle; + + + if ((Index >= ACPI_OS_MAX_SEMAPHORES) || + !AcpiGbl_Semaphores[Index].OsHandle) + { + return (AE_BAD_PARAMETER); + } + + CloseHandle (AcpiGbl_Semaphores[Index].OsHandle); + AcpiGbl_Semaphores[Index].OsHandle = NULL; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWaitSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - How many units to wait for + * Timeout - How long to wait + * + * RETURN: Status + * + * DESCRIPTION: Wait for units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units, + UINT16 Timeout) +{ + UINT32 Index = (UINT32) Handle; + UINT32 WaitStatus; + UINT32 OsTimeout = Timeout; + + + ACPI_FUNCTION_ENTRY (); + + + if ((Index >= ACPI_OS_MAX_SEMAPHORES) || + !AcpiGbl_Semaphores[Index].OsHandle) + { + return (AE_BAD_PARAMETER); + } + + if (Units > 1) + { + printf ("WaitSemaphore: Attempt to receive %u units\n", Units); + return (AE_NOT_IMPLEMENTED); + } + + if (Timeout == ACPI_WAIT_FOREVER) + { + OsTimeout = INFINITE; + if (AcpiGbl_DebugTimeout) + { + /* The debug timeout will prevent hang conditions */ + + OsTimeout = ACPI_OS_DEBUG_TIMEOUT; + } + } + else + { + /* Add 10ms to account for clock tick granularity */ + + OsTimeout += 10; + } + + WaitStatus = WaitForSingleObject (AcpiGbl_Semaphores[Index].OsHandle, OsTimeout); + if (WaitStatus == WAIT_TIMEOUT) + { + if (AcpiGbl_DebugTimeout) + { + ACPI_EXCEPTION ((AE_INFO, AE_TIME, + "Debug timeout on semaphore 0x%04X (%ums)\n", + Index, ACPI_OS_DEBUG_TIMEOUT)); + } + return (AE_TIME); + } + + if (AcpiGbl_Semaphores[Index].CurrentUnits == 0) + { + ACPI_ERROR ((AE_INFO, "%s - No unit received. Timeout 0x%X, OS_Status 0x%X", + AcpiUtGetMutexName (Index), Timeout, WaitStatus)); + + return (AE_OK); + } + + AcpiGbl_Semaphores[Index].CurrentUnits--; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignalSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - Number of units to send + * + * RETURN: Status + * + * DESCRIPTION: Send units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units) +{ + UINT32 Index = (UINT32) Handle; + + + ACPI_FUNCTION_ENTRY (); + + + if (Index >= ACPI_OS_MAX_SEMAPHORES) + { + printf ("SignalSemaphore: Index/Handle out of range: %2.2X\n", Index); + return (AE_BAD_PARAMETER); + } + + if (!AcpiGbl_Semaphores[Index].OsHandle) + { + printf ("SignalSemaphore: Null OS handle, Index %2.2X\n", Index); + return (AE_BAD_PARAMETER); + } + + if (Units > 1) + { + printf ("SignalSemaphore: Attempt to signal %u units, Index %2.2X\n", Units, Index); + return (AE_NOT_IMPLEMENTED); + } + + if ((AcpiGbl_Semaphores[Index].CurrentUnits + 1) > + AcpiGbl_Semaphores[Index].MaxUnits) + { + ACPI_ERROR ((AE_INFO, + "Oversignalled semaphore[%u]! Current %u Max %u", + Index, AcpiGbl_Semaphores[Index].CurrentUnits, + AcpiGbl_Semaphores[Index].MaxUnits)); + + return (AE_LIMIT); + } + + AcpiGbl_Semaphores[Index].CurrentUnits++; + ReleaseSemaphore (AcpiGbl_Semaphores[Index].OsHandle, Units, NULL); + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + + +/****************************************************************************** + * + * FUNCTION: Spinlock interfaces + * + * DESCRIPTION: Map these interfaces to semaphore interfaces + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateLock ( + ACPI_SPINLOCK *OutHandle) +{ + return (AcpiOsCreateSemaphore (1, 1, OutHandle)); +} + +void +AcpiOsDeleteLock ( + ACPI_SPINLOCK Handle) +{ + AcpiOsDeleteSemaphore (Handle); +} + +ACPI_CPU_FLAGS +AcpiOsAcquireLock ( + ACPI_SPINLOCK Handle) +{ + AcpiOsWaitSemaphore (Handle, 1, 0xFFFF); + return (0); +} + +void +AcpiOsReleaseLock ( + ACPI_SPINLOCK Handle, + ACPI_CPU_FLAGS Flags) +{ + AcpiOsSignalSemaphore (Handle, 1); +} + + +#if ACPI_FUTURE_IMPLEMENTATION + +/* Mutex interfaces, just implement with a semaphore */ + +ACPI_STATUS +AcpiOsCreateMutex ( + ACPI_MUTEX *OutHandle) +{ + return (AcpiOsCreateSemaphore (1, 1, OutHandle)); +} + +void +AcpiOsDeleteMutex ( + ACPI_MUTEX Handle) +{ + AcpiOsDeleteSemaphore (Handle); +} + +ACPI_STATUS +AcpiOsAcquireMutex ( + ACPI_MUTEX Handle, + UINT16 Timeout) +{ + AcpiOsWaitSemaphore (Handle, 1, Timeout); + return (0); +} + +void +AcpiOsReleaseMutex ( + ACPI_MUTEX Handle) +{ + AcpiOsSignalSemaphore (Handle, 1); +} +#endif + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInstallInterruptHandler + * + * PARAMETERS: InterruptNumber - Level handler should respond to. + * ServiceRoutine - Address of the ACPI interrupt handler + * Context - User context + * + * RETURN: Handle to the newly installed handler. + * + * DESCRIPTION: Install an interrupt handler. Used to install the ACPI + * OS-independent handler. + * + *****************************************************************************/ + +UINT32 +AcpiOsInstallInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine, + void *Context) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsRemoveInterruptHandler + * + * PARAMETERS: Handle - Returned when handler was installed + * + * RETURN: Status + * + * DESCRIPTION: Uninstalls an interrupt handler. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsRemoveInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsStall + * + * PARAMETERS: Microseconds - Time to stall + * + * RETURN: None. Blocks until stall is completed. + * + * DESCRIPTION: Sleep at microsecond granularity + * + *****************************************************************************/ + +void +AcpiOsStall ( + UINT32 Microseconds) +{ + + Sleep ((Microseconds / 1000) + 1); + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSleep + * + * PARAMETERS: Milliseconds - Time to sleep + * + * RETURN: None. Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at millisecond granularity + * + *****************************************************************************/ + +void +AcpiOsSleep ( + UINT64 Milliseconds) +{ + + /* Add 10ms to account for clock tick granularity */ + + Sleep (((unsigned long) Milliseconds) + 10); + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * Register - Device Register + * Value - Buffer where value is placed + * Width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Read data from PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + UINT64 *Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * Register - Device Register + * Value - Value to be written + * Width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Write data to PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPort + * + * PARAMETERS: Address - Address of I/O port/register to read + * Value - Where value is placed + * Width - Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + ACPI_FUNCTION_NAME (OsReadPort); + + + switch (Width) + { + case 8: + *Value = 0xFF; + break; + + case 16: + *Value = 0xFFFF; + break; + + case 32: + *Value = 0xFFFFFFFF; + break; + + default: + ACPI_ERROR ((AE_INFO, "Bad width parameter: %X", Width)); + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePort + * + * PARAMETERS: Address - Address of I/O port/register to write + * Value - Value to write + * Width - Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + ACPI_FUNCTION_NAME (OsWritePort); + + + if ((Width == 8) || (Width == 16) || (Width == 32)) + { + return (AE_OK); + } + + ACPI_ERROR ((AE_INFO, "Bad width parameter: %X", Width)); + return (AE_BAD_PARAMETER); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadMemory + * + * PARAMETERS: Address - Physical Memory Address to read + * Value - Where value is placed + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. + * + * DESCRIPTION: Read data from a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 *Value, + UINT32 Width) +{ + + switch (Width) + { + case 8: + case 16: + case 32: + case 64: + *Value = 0; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWriteMemory + * + * PARAMETERS: Address - Physical Memory Address to write + * Value - Value to write + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: None + * + * DESCRIPTION: Write data to a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignal + * + * PARAMETERS: Function - ACPI CA signal function code + * Info - Pointer to function-dependent structure + * + * RETURN: Status + * + * DESCRIPTION: Miscellaneous functions. Example implementation only. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info) +{ + + switch (Function) + { + case ACPI_SIGNAL_FATAL: + break; + + case ACPI_SIGNAL_BREAKPOINT: + break; + + default: + break; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Local cache interfaces + * + * DESCRIPTION: Implements cache interfaces via malloc/free for testing + * purposes only. + * + *****************************************************************************/ + +#ifndef ACPI_USE_LOCAL_CACHE + +ACPI_STATUS +AcpiOsCreateCache ( + char *CacheName, + UINT16 ObjectSize, + UINT16 MaxDepth, + ACPI_CACHE_T **ReturnCache) +{ + ACPI_MEMORY_LIST *NewCache; + + + NewCache = malloc (sizeof (ACPI_MEMORY_LIST)); + if (!NewCache) + { + return (AE_NO_MEMORY); + } + + memset (NewCache, 0, sizeof (ACPI_MEMORY_LIST)); + NewCache->LinkOffset = 8; + NewCache->ListName = CacheName; + NewCache->ObjectSize = ObjectSize; + NewCache->MaxDepth = MaxDepth; + + *ReturnCache = (ACPI_CACHE_T) NewCache; + return (AE_OK); +} + +ACPI_STATUS +AcpiOsDeleteCache ( + ACPI_CACHE_T *Cache) +{ + free (Cache); + return (AE_OK); +} + +ACPI_STATUS +AcpiOsPurgeCache ( + ACPI_CACHE_T *Cache) +{ + return (AE_OK); +} + +void * +AcpiOsAcquireObject ( + ACPI_CACHE_T *Cache) +{ + void *NewObject; + + NewObject = malloc (((ACPI_MEMORY_LIST *) Cache)->ObjectSize); + memset (NewObject, 0, ((ACPI_MEMORY_LIST *) Cache)->ObjectSize); + + return (NewObject); +} + +ACPI_STATUS +AcpiOsReleaseObject ( + ACPI_CACHE_T *Cache, + void *Object) +{ + free (Object); + return (AE_OK); +} + +#endif /* ACPI_USE_LOCAL_CACHE */ + + +/* Optional multi-thread support */ + +#ifndef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: AcpiOsGetThreadId + * + * PARAMETERS: None + * + * RETURN: Id of the running thread + * + * DESCRIPTION: Get the Id of the current (running) thread + * + *****************************************************************************/ + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + DWORD ThreadId; + + /* Ensure ID is never 0 */ + + ThreadId = GetCurrentThreadId (); + return ((ACPI_THREAD_ID) (ThreadId + 1)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsExecute + * + * PARAMETERS: Type - Type of execution + * Function - Address of the function to execute + * Context - Passed as a parameter to the function + * + * RETURN: Status + * + * DESCRIPTION: Execute a new thread + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + + _beginthread (Function, (unsigned) 0, Context); + return (0); +} + +#endif /* ACPI_SINGLE_THREADED */ + diff --git a/source/tools/acpibin/Makefile b/source/tools/acpibin/Makefile new file mode 100644 index 000000000000..f15141bb2d78 --- /dev/null +++ b/source/tools/acpibin/Makefile @@ -0,0 +1,129 @@ +# +# acpibin - Binary ACPI table utility +# +# NOTE: This makefile is intended to be used within the native +# ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpibin + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPIBIN = $(ACPICA_TOOLS)/acpibin +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ACPIBIN) \ + $(ACPICA_UTILITIES) \ + $(ACPICA_COMMON) \ + $(ACPICA_OSL) + +HEADERS = \ + $(wildcard $(ACPIBIN)/*.h) + +OBJECTS = \ + abcompare.o \ + abmain.o \ + utalloc.o \ + utcache.o \ + utdebug.o \ + utdecode.o \ + utglobal.o \ + utlock.o \ + utmath.o \ + utmisc.o \ + utmutex.o \ + utstate.o \ + utxferror.o \ + osunixxf.o \ + getopt.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_BIN_APP \ + -I$(ACPICA_INCLUDE) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpibin/abcompare.c b/source/tools/acpibin/abcompare.c new file mode 100644 index 000000000000..46122274d4a9 --- /dev/null +++ b/source/tools/acpibin/abcompare.c @@ -0,0 +1,767 @@ + +/****************************************************************************** + * + * Module Name: abcompare - compare AML files + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpibin.h" + + +FILE *File1; +FILE *File2; +ACPI_TABLE_HEADER Header1; +ACPI_TABLE_HEADER Header2; +struct stat Gbl_StatBuf; + +#define BUFFER_SIZE 256 +char Buffer[BUFFER_SIZE]; + + +/* Local prototypes */ + +static BOOLEAN +AbValidateHeader ( + ACPI_TABLE_HEADER *Header); + +static UINT8 +AcpiTbSumTable ( + void *Buffer, + UINT32 Length); + +static char * +AbGetFile ( + char *Filename, + UINT32 *FileSize); + +static void +AbPrintHeaderInfo ( + ACPI_TABLE_HEADER *Header); + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + + +/******************************************************************************* + * + * FUNCTION: UtHexCharToValue + * + * PARAMETERS: HexChar - Hex character in Ascii + * + * RETURN: The binary value of the hex character + * + * DESCRIPTION: Perform ascii-to-hex translation + * + ******************************************************************************/ + +static UINT8 +UtHexCharToValue ( + int HexChar, + UINT8 *OutBinary) +{ + + if (HexChar >= 0x30 && HexChar <= 0x39) + { + *OutBinary = (UINT8) (HexChar - 0x30); + return (1); + } + + else if (HexChar >= 0x41 && HexChar <= 0x46) + { + *OutBinary = (UINT8) (HexChar - 0x37); + return (1); + } + + else if (HexChar >= 0x61 && HexChar <= 0x66) + { + *OutBinary = (UINT8) (HexChar - 0x57); + return (1); + } + return (0); +} + +static UINT8 +AbHexByteToBinary ( + char *HexString, + char *OutBinary) +{ + UINT8 Local1; + UINT8 Local2; + + + if (!UtHexCharToValue (HexString[0], &Local1)) + { + return (0); + } + if (!UtHexCharToValue (HexString[1], &Local2)) + { + return (0); + } + + *OutBinary = (UINT8) ((Local1 << 4) | Local2); + return (2); + +} + + +/****************************************************************************** + * + * FUNCTION: AbValidateHeader + * + * DESCRIPTION: Check for valid ACPI table header + * + ******************************************************************************/ + +static BOOLEAN +AbValidateHeader ( + ACPI_TABLE_HEADER *Header) +{ + + if (!AcpiUtValidAcpiName (* (UINT32 *) &Header->Signature)) + { + printf ("Header signature is invalid\n"); + return FALSE; + } + + return TRUE; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbSumTable + * + * PARAMETERS: Buffer - Buffer to checksum + * Length - Size of the buffer + * + * RETURNS 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * + ******************************************************************************/ + +static UINT8 +AcpiTbSumTable ( + void *Buffer, + UINT32 Length) +{ + const UINT8 *limit; + const UINT8 *rover; + UINT8 sum = 0; + + + if (Buffer && Length) + { + /* Buffer and Length are valid */ + + limit = (UINT8 *) Buffer + Length; + + for (rover = Buffer; rover < limit; rover++) + { + sum = (UINT8) (sum + *rover); + } + } + return (sum); +} + + +/******************************************************************************* + * + * FUNCTION: AbPrintHeaderInfo + * + * PARAMETERS: Header - An ACPI table header + * + * RETURNS None. + * + * DESCRIPTION: Format and display header contents. + * + ******************************************************************************/ + +static void +AbPrintHeaderInfo ( + ACPI_TABLE_HEADER *Header) +{ + + /* Display header information */ + + printf ("Signature : %4.4s\n", Header->Signature); + printf ("Length : %8.8X\n", Header->Length); + printf ("Revision : %2.2X\n", Header->Revision); + printf ("Checksum : %2.2X\n", Header->Checksum); + printf ("OEM ID : %6.6s\n", Header->OemId); + printf ("OEM Table ID : %8.8s\n", Header->OemTableId); + printf ("OEM Revision : %8.8X\n", Header->OemRevision); + printf ("ASL Compiler ID : %4.4s\n", Header->AslCompilerId); + printf ("Compiler Revision : %8.8X\n", Header->AslCompilerRevision); + printf ("\n"); +} + + +/****************************************************************************** + * + * FUNCTION: AbDisplayHeader + * + * DESCRIPTION: Display an ACPI table header + * + ******************************************************************************/ + +void +AbDisplayHeader ( + char *File1Path) +{ + UINT32 Actual1; + + + File1 = fopen (File1Path, "rb"); + if (!File1) + { + printf ("Could not open file %s\n", File1Path); + return; + } + + Actual1 = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1); + if (Actual1 < sizeof (ACPI_TABLE_HEADER)) + { + printf ("File %s does not contain an ACPI table header\n", File1Path); + return; + } + + if (!AbValidateHeader (&Header1)) + { + return; + } + + AbPrintHeaderInfo (&Header1); +} + + +/****************************************************************************** + * + * FUNCTION: AbComputeChecksum + * + * DESCRIPTION: Compute proper checksum for an ACPI table + * + ******************************************************************************/ + +void +AbComputeChecksum ( + char *File1Path) +{ + UINT32 Actual1; + ACPI_TABLE_HEADER *Table; + UINT8 Checksum; + + + File1 = fopen (File1Path, "rb"); + if (!File1) + { + printf ("Could not open file %s\n", File1Path); + return; + } + + Actual1 = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1); + if (Actual1 < sizeof (ACPI_TABLE_HEADER)) + { + printf ("File %s does not contain an ACPI table header\n", File1Path); + return; + } + + if (!AbValidateHeader (&Header1)) + { + return; + } + + if (!Gbl_TerseMode) + { + AbPrintHeaderInfo (&Header1); + } + + /* Allocate a buffer to hold the entire table */ + + Table = AcpiOsAllocate (Header1.Length); + if (!Table) + { + printf ("could not allocate\n"); + return; + } + + /* Read the entire table, including header */ + + fseek (File1, 0, SEEK_SET); + Actual1 = fread (Table, 1, Header1.Length, File1); + if (Actual1 < Header1.Length) + { + printf ("could not read table\n"); + return; + } + + /* Compute the checksum for the table */ + + Table->Checksum = 0; + + Checksum = (UINT8) (0 - AcpiTbSumTable (Table, Table->Length)); + printf ("Computed checksum: 0x%X\n\n", Checksum); + + if (Header1.Checksum == Checksum) + { + printf ("Checksum ok in AML file, not updating\n"); + return; + } + + /* Open the target file for writing, to update checksum */ + + fclose (File1); + File1 = fopen (File1Path, "r+b"); + if (!File1) + { + printf ("Could not open file %s for writing\n", File1Path); + return; + } + + /* Set the checksum, write the new header */ + + Header1.Checksum = Checksum; + + Actual1 = fwrite (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1); + if (Actual1 < sizeof (ACPI_TABLE_HEADER)) + { + printf ("Could not write updated table header\n"); + return; + } + + printf ("Wrote new checksum\n"); + return; +} + + +/****************************************************************************** + * + * FUNCTION: AbCompareAmlFiles + * + * DESCRIPTION: Compare two AML files + * + ******************************************************************************/ + +int +AbCompareAmlFiles ( + char *File1Path, + char *File2Path) +{ + UINT32 Actual1; + UINT32 Actual2; + UINT32 Offset; + UINT8 Char1; + UINT8 Char2; + UINT8 Mismatches = 0; + BOOLEAN HeaderMismatch = FALSE; + + + File1 = fopen (File1Path, "rb"); + if (!File1) + { + printf ("Could not open file %s\n", File1Path); + return -1; + } + + File2 = fopen (File2Path, "rb"); + if (!File2) + { + printf ("Could not open file %s\n", File2Path); + return -1; + } + + /* Read the ACPI header from each file */ + + Actual1 = fread (&Header1, 1, sizeof (ACPI_TABLE_HEADER), File1); + if (Actual1 < sizeof (ACPI_TABLE_HEADER)) + { + printf ("File %s does not contain an ACPI table header\n", File1Path); + return -1; + } + + Actual2 = fread (&Header2, 1, sizeof (ACPI_TABLE_HEADER), File2); + if (Actual2 < sizeof (ACPI_TABLE_HEADER)) + { + printf ("File %s does not contain an ACPI table header\n", File2Path); + return -1; + } + + if ((!AbValidateHeader (&Header1)) || + (!AbValidateHeader (&Header2))) + { + return -1; + } + + /* Table signatures must match */ + + if (*((UINT32 *) Header1.Signature) != *((UINT32 *) Header2.Signature)) + { + printf ("Table signatures do not match\n"); + return -1; + } + + if (!Gbl_TerseMode) + { + /* Display header information */ + + AbPrintHeaderInfo (&Header1); + AbPrintHeaderInfo (&Header2); + } + + if (memcmp (Header1.Signature, Header2.Signature, sizeof (ACPI_TABLE_HEADER))) + { + printf ("Headers do not match exactly\n"); + HeaderMismatch = TRUE; + } + + /* Do the byte-by-byte compare */ + + Actual1 = fread (&Char1, 1, 1, File1); + Actual2 = fread (&Char2, 1, 1, File2); + Offset = sizeof (ACPI_TABLE_HEADER); + + while (Actual1 && Actual2) + { + if (Char1 != Char2) + { + printf ("Error - Byte mismatch at offset %8.8X: 0x%2.2X 0x%2.2X\n", + Offset, Char1, Char2); + Mismatches++; + if (Mismatches > 100) + { + printf ("100 Mismatches: Too many mismatches\n"); + return -1; + } + } + + Offset++; + Actual1 = fread (&Char1, 1, 1, File1); + Actual2 = fread (&Char2, 1, 1, File2); + } + + if (Actual1) + { + printf ("Error - file %s is longer than file %s\n", File1Path, File2Path); + Mismatches++; + } + else if (Actual2) + { + printf ("Error - file %s is shorter than file %s\n", File1Path, File2Path); + Mismatches++; + } + else if (!Mismatches) + { + if (HeaderMismatch) + { + printf ("Files compare exactly after header\n"); + } + else + { + printf ("Files compare exactly\n"); + } + } + + printf ("%u Mismatches found\n", Mismatches); + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AsGetFile + * + * DESCRIPTION: Open a file and read it entirely into a new buffer + * + ******************************************************************************/ + +static char * +AbGetFile ( + char *Filename, + UINT32 *FileSize) +{ + int FileHandle; + UINT32 Size; + char *Buffer = NULL; + + + /* Binary mode does not alter CR/LF pairs */ + + FileHandle = open (Filename, O_BINARY | O_RDONLY); + if (!FileHandle) + { + printf ("Could not open %s\n", Filename); + return NULL; + } + + /* Need file size to allocate a buffer */ + + if (fstat (FileHandle, &Gbl_StatBuf)) + { + printf ("Could not get file status for %s\n", Filename); + goto ErrorExit; + } + + /* Allocate a buffer for the entire file */ + + Size = Gbl_StatBuf.st_size; + Buffer = calloc (Size, 1); + if (!Buffer) + { + printf ("Could not allocate buffer of size %u\n", Size); + goto ErrorExit; + } + + /* Read the entire file */ + + Size = read (FileHandle, Buffer, Size); + if (Size == -1) + { + printf ("Could not read the input file %s\n", Filename); + free (Buffer); + Buffer = NULL; + goto ErrorExit; + } + + *FileSize = Size; + +ErrorExit: + close (FileHandle); + + return (Buffer); +} + + +/****************************************************************************** + * + * FUNCTION: AbDumpAmlFile + * + * DESCRIPTION: Dump a binary AML file to a text file + * + ******************************************************************************/ + +int +AbDumpAmlFile ( + char *File1Path, + char *File2Path) +{ + char *FileBuffer; + UINT32 FileSize = 0; + FILE *FileOutHandle; + + + /* Get the entire AML file, validate header */ + + FileBuffer = AbGetFile (File1Path, &FileSize); + printf ("File %s contains 0x%X bytes\n\n", File1Path, FileSize); + + FileOutHandle = fopen (File2Path, "wb"); + if (!FileOutHandle) + { + printf ("Could not open %s\n", File2Path); + return -1; + } + + if (!AbValidateHeader ((ACPI_TABLE_HEADER *) FileBuffer)) + { + return -1; + } + + /* Convert binary AML to text, using common dump buffer routine */ + + AcpiGbl_DebugFile = FileOutHandle; + AcpiGbl_DbOutputFlags = ACPI_DB_REDIRECTABLE_OUTPUT; + + AcpiOsPrintf ("%4.4s\n", ((ACPI_TABLE_HEADER *) FileBuffer)->Signature); + AcpiDbgLevel = ACPI_UINT32_MAX; + AcpiUtDumpBuffer ((UINT8 *) FileBuffer, FileSize, + DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AbExtractAmlFile + * + * DESCRIPTION: Extract a binary AML file from a text file (as produced by the + * DumpAmlFile procedure or the "acpidmp" table utility. + * + ******************************************************************************/ + +int +AbExtractAmlFile ( + char *TableSig, + char *File1Path, + char *File2Path) +{ + char *Table; + char Value; + UINT32 i; + FILE *FileHandle; + FILE *FileOutHandle; + UINT32 Count = 0; + int Scanned; + + + /* Open in/out files. input is in text mode, output is in binary mode */ + + FileHandle = fopen (File1Path, "rt"); + if (!FileHandle) + { + printf ("Could not open %s\n", File1Path); + return -1; + } + + FileOutHandle = fopen (File2Path, "w+b"); + if (!FileOutHandle) + { + printf ("Could not open %s\n", File2Path); + return -1; + } + + /* Force input table sig to uppercase */ + + AcpiUtStrupr (TableSig); + + + /* TBD: examine input for ASCII */ + + + /* We have an ascii file, grab one line at a time */ + + while (fgets (Buffer, BUFFER_SIZE, FileHandle)) + { + /* The 4-char ACPI signature appears at the beginning of a line */ + + if (!strncmp (Buffer, TableSig, 4)) + { + printf ("Found table [%4.4s]\n", TableSig); + + /* + * Eat all lines in the table, of the form: + * : <16 bytes of hex data, separated by spaces> + * + * Example: + * + * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........ + * + */ + while (fgets (Buffer, BUFFER_SIZE, FileHandle)) + { + /* Get past the offset, terminated by a colon */ + + Table = strchr (Buffer, ':'); + if (!Table) + { + /* No colon, all done */ + goto Exit; + } + + Table += 2; /* Eat the colon + space */ + + for (i = 0; i < 16; i++) + { + Scanned = AbHexByteToBinary (Table, &Value); + if (!Scanned) + { + goto Exit; + } + + Table += 3; /* Go past this hex byte and space */ + + /* Write the converted (binary) byte */ + + fwrite (&Value, 1, 1, FileOutHandle); + Count++; + } + } + + /* No more lines, EOF, all done */ + + goto Exit; + } + } + + /* Searched entire file, no match to table signature */ + + printf ("Could not match table signature\n"); + fclose (FileHandle); + return -1; + +Exit: + printf ("%u (0x%X) bytes written to %s\n", Count, Count, File2Path); + fclose (FileHandle); + fclose (FileOutHandle); + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: Stubs + * + * DESCRIPTION: For linkage + * + ******************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void) +{ + return AE_OK; +} + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (0xFFFF); +} + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + return (AE_SUPPORT); +} diff --git a/source/tools/acpibin/abmain.c b/source/tools/acpibin/abmain.c new file mode 100644 index 000000000000..cb9c329521f0 --- /dev/null +++ b/source/tools/acpibin/abmain.c @@ -0,0 +1,186 @@ + +/****************************************************************************** + * + * Module Name: abmain - Main module for the acpi binary utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define _DECLARE_GLOBALS +#include "acpibin.h" +#include "acapps.h" + +/* Local prototypes */ + +static void +AbDisplayUsage ( + UINT8 OptionCount); + + +/****************************************************************************** + * + * FUNCTION: AbDisplayUsage + * + * DESCRIPTION: Usage message + * + ******************************************************************************/ + +static void +AbDisplayUsage ( + UINT8 OptionCount) +{ + + if (OptionCount) + { + printf ("Option requires %u arguments\n\n", OptionCount); + } + + ACPI_USAGE_HEADER ("acpibin [options]"); + + ACPI_OPTION ("-c ", "Compare two AML files"); + ACPI_OPTION ("-d ", "Dump AML binary to text file"); + ACPI_OPTION ("-e ", "Extract binary AML table from AcpiDmp file"); + ACPI_OPTION ("-h ", "Display table header for binary AML file"); + ACPI_OPTION ("-s ", "Update checksum for binary AML file"); + ACPI_OPTION ("-t", "Terse mode"); +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * DESCRIPTION: C main function + * + ******************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char *argv[]) +{ + int j; + int Status = AE_OK; + + + AcpiGbl_DebugFile = NULL; + AcpiGbl_DbOutputFlags = DB_CONSOLE_OUTPUT ; + + AcpiOsInitialize (); + printf (ACPI_COMMON_SIGNON ("ACPI Binary AML File Utility")); + + if (argc < 2) + { + AbDisplayUsage (0); + return 0; + } + + /* Command line options */ + + while ((j = AcpiGetopt (argc, argv, "c:d:e:h:s:t")) != EOF) switch(j) + { + case 'c': /* Compare Files */ + + if (argc < 4) + { + AbDisplayUsage (2); + return -1; + } + + Status = AbCompareAmlFiles (AcpiGbl_Optarg, argv[AcpiGbl_Optind]); + break; + + case 'd': /* Dump AML file */ + + if (argc < 4) + { + AbDisplayUsage (2); + return -1; + } + + Status = AbDumpAmlFile (AcpiGbl_Optarg, argv[AcpiGbl_Optind]); + break; + + case 'e': /* Extract AML text file */ + + if (argc < 5) + { + AbDisplayUsage (3); + return -1; + } + + Status = AbExtractAmlFile (AcpiGbl_Optarg, argv[AcpiGbl_Optind], + argv[AcpiGbl_Optind+1]); + break; + + case 'h': /* Display ACPI table header */ + + if (argc < 3) + { + AbDisplayUsage (1); + return -1; + } + + AbDisplayHeader (AcpiGbl_Optarg); + return (0); + + case 's': /* Compute/update checksum */ + + if (argc < 3) + { + AbDisplayUsage (1); + return -1; + } + + AbComputeChecksum (AcpiGbl_Optarg); + return (0); + + case 't': /* Enable terse mode */ + + Gbl_TerseMode = TRUE; + break; + + default: + AbDisplayUsage (0); + return -1; + } + + return Status; +} diff --git a/source/tools/acpibin/acpibin.h b/source/tools/acpibin/acpibin.h new file mode 100644 index 000000000000..63109cc738cf --- /dev/null +++ b/source/tools/acpibin/acpibin.h @@ -0,0 +1,113 @@ + +/****************************************************************************** + * + * Module Name: acpibinh - Include file for AcpiBin utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#include +#endif + +/* O_BINARY is not always defined */ +#ifndef O_BINARY +#define O_BINARY 0x0 +#endif + +#define DB_CONSOLE_OUTPUT 0x02 +#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 + +/* + * Global variables. Defined in main.c only, externed in all other files + */ + +#ifdef _DECLARE_GLOBALS +#define EXTERN +#define INIT_GLOBAL(a,b) a=b +#else +#define EXTERN extern +#define INIT_GLOBAL(a,b) a +#endif + + +/* Globals */ + +EXTERN BOOLEAN INIT_GLOBAL (Gbl_TerseMode, FALSE); +EXTERN FILE INIT_GLOBAL (*AcpiGbl_DebugFile, NULL); + + +/* Prototypes */ + +int +AbCompareAmlFiles ( + char *File1Path, + char *File2Path); + +int +AbExtractAmlFile ( + char *TableSig, + char *File1Path, + char *File2Path); + +int +AbDumpAmlFile ( + char *File1Path, + char *File2Path); + +void +AbComputeChecksum ( + char *File1Path); + +void +AbDisplayHeader ( + char *File1Path); + diff --git a/source/tools/acpiexec/Makefile b/source/tools/acpiexec/Makefile new file mode 100644 index 000000000000..65a1d84411d6 --- /dev/null +++ b/source/tools/acpiexec/Makefile @@ -0,0 +1,286 @@ +# +# acpiexec: ACPI execution simulator. Runs ACPICA code in user +# space. Loads ACPI tables, displays the namespace, and allows +# execution of control methods. +# +# NOTE: This makefile is intended to be used within the native +# ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpiexec + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< +LDFLAGS += -lpthread -lrt + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPIEXEC = $(ACPICA_TOOLS)/acpiexec +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ACPIEXEC) \ + $(ACPICA_DEBUGGER) \ + $(ACPICA_DISASSEMBLER) \ + $(ACPICA_DISPATCHER) \ + $(ACPICA_EVENTS) \ + $(ACPICA_EXECUTER) \ + $(ACPICA_HARDWARE) \ + $(ACPICA_NAMESPACE) \ + $(ACPICA_PARSER) \ + $(ACPICA_RESOURCES) \ + $(ACPICA_TABLES) \ + $(ACPICA_UTILITIES) \ + $(ACPICA_COMMON) \ + $(ACPICA_OSL) + +HEADERS = \ + $(wildcard $(ACPIEXEC)/*.h) + +OBJECTS = \ + aeexec.o \ + aehandlers.o \ + aemain.o \ + aetables.o \ + dbcmds.o \ + dbdisply.o \ + dbexec.o \ + dbfileio.o \ + dbhistry.o \ + dbinput.o \ + dbmethod.o \ + dbnames.o \ + dbstats.o \ + dbutils.o \ + dbxface.o \ + dmbuffer.o \ + dmnames.o \ + dmobject.o \ + dmopcode.o \ + dmresrc.o \ + dmresrcl.o \ + dmresrcl2.o \ + dmresrcs.o \ + dmutils.o \ + dmwalk.o \ + dsargs.o \ + dscontrol.o \ + dsfield.o \ + dsinit.o \ + dsmethod.o \ + dsmthdat.o \ + dsobject.o \ + dsopcode.o \ + dsutils.o \ + dswexec.o \ + dswload.o \ + dswload2.o \ + dswscope.o \ + dswstate.o \ + evevent.o \ + evglock.o \ + evgpe.o \ + evgpeblk.o \ + evgpeinit.o \ + evgpeutil.o \ + evmisc.o \ + evregion.o \ + evrgnini.o \ + evsci.o \ + evxface.o \ + evxfevnt.o \ + evxfgpe.o \ + evxfregn.o \ + exconfig.o \ + exconvrt.o \ + excreate.o \ + exdebug.o \ + exdump.o \ + exfield.o \ + exfldio.o \ + exmisc.o \ + exmutex.o \ + exnames.o \ + exoparg1.o \ + exoparg2.o \ + exoparg3.o \ + exoparg6.o \ + exprep.o \ + exregion.o \ + exresnte.o \ + exresolv.o \ + exresop.o \ + exstore.o \ + exstoren.o \ + exstorob.o \ + exsystem.o \ + exutils.o \ + getopt.o \ + hwacpi.o \ + hwesleep.o \ + hwgpe.o \ + hwpci.o \ + hwregs.o \ + hwsleep.o \ + hwvalid.o \ + hwxface.o \ + hwxfsleep.o \ + nsaccess.o \ + nsalloc.o \ + nsdump.o \ + nsdumpdv.o \ + nseval.o \ + nsinit.o \ + nsload.o \ + nsnames.o \ + nsobject.o \ + nsparse.o \ + nspredef.o \ + nsrepair.o \ + nsrepair2.o \ + nssearch.o \ + nsutils.o \ + nswalk.o \ + nsxfeval.o \ + nsxfname.o \ + nsxfobj.o \ + osunixxf.o \ + psargs.o \ + psloop.o \ + psopcode.o \ + psparse.o \ + psscope.o \ + pstree.o \ + psutils.o \ + pswalk.o \ + psxface.o \ + rsaddr.o \ + rscalc.o \ + rscreate.o \ + rsdump.o \ + rsinfo.o \ + rsio.o \ + rsirq.o \ + rslist.o \ + rsmemory.o \ + rsserial.o \ + rsmisc.o \ + rsutils.o \ + rsxface.o \ + tbfadt.o \ + tbfind.o \ + tbinstal.o \ + tbutils.o \ + tbxface.o \ + tbxfroot.o \ + utaddress.o \ + utalloc.o \ + utcache.o \ + utcopy.o \ + utdebug.o \ + utdecode.o \ + utdelete.o \ + uteval.o \ + utglobal.o \ + utids.o \ + utinit.o \ + utlock.o \ + utmath.o \ + utmisc.o \ + utmutex.o \ + utobject.o \ + utresrc.o \ + utstate.o \ + uttrack.o \ + utosi.o \ + utxferror.o \ + utxface.o \ + utxfmutex.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_EXEC_APP \ + -I$(ACPICA_INCLUDE) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + $(COPYPROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpiexec/aecommon.h b/source/tools/acpiexec/aecommon.h new file mode 100644 index 000000000000..0f1b4c1e7569 --- /dev/null +++ b/source/tools/acpiexec/aecommon.h @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * Module Name: aecommon - common include for the AcpiExec utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _AECOMMON +#define _AECOMMON + +#ifdef _MSC_VER /* disable some level-4 warnings */ +#pragma warning(disable:4100) /* warning C4100: unreferenced formal parameter */ +#endif + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "actables.h" +#include "acinterp.h" +#include "acapps.h" + +#include +#include +#include +#include + +extern FILE *AcpiGbl_DebugFile; +extern BOOLEAN AcpiGbl_IgnoreErrors; +extern UINT8 AcpiGbl_RegionFillValue; +extern UINT8 AcpiGbl_UseHwReducedFadt; +extern BOOLEAN AcpiGbl_DisplayRegionAccess; + +/* Check for unexpected exceptions */ + +#define AE_CHECK_STATUS(Name, Status, Expected) \ + if (Status != Expected) \ + { \ + AcpiOsPrintf ("Unexpected %s from %s (%s-%d)\n", \ + AcpiFormatException (Status), #Name, _AcpiModuleName, __LINE__); \ + } + +/* Check for unexpected non-AE_OK errors */ + +#define AE_CHECK_OK(Name, Status) AE_CHECK_STATUS (Name, Status, AE_OK); + +typedef struct ae_table_desc +{ + ACPI_TABLE_HEADER *Table; + struct ae_table_desc *Next; + +} AE_TABLE_DESC; + +/* + * Debug Regions + */ +typedef struct ae_region +{ + ACPI_PHYSICAL_ADDRESS Address; + UINT32 Length; + void *Buffer; + void *NextRegion; + UINT8 SpaceId; + +} AE_REGION; + +typedef struct ae_debug_regions +{ + UINT32 NumberOfRegions; + AE_REGION *RegionList; + +} AE_DEBUG_REGIONS; + + +#define TEST_OUTPUT_LEVEL(lvl) if ((lvl) & OutputLevel) + +#define OSD_PRINT(lvl,fp) TEST_OUTPUT_LEVEL(lvl) {\ + AcpiOsPrintf PARAM_LIST(fp);} + +void ACPI_SYSTEM_XFACE +AeCtrlCHandler ( + int Sig); + +ACPI_STATUS +AeBuildLocalTables ( + UINT32 TableCount, + AE_TABLE_DESC *TableList); + +ACPI_STATUS +AeInstallTables ( + void); + +void +AeDumpNamespace ( + void); + +void +AeDumpObject ( + char *MethodName, + ACPI_BUFFER *ReturnObj); + +void +AeDumpBuffer ( + UINT32 Address); + +void +AeExecute ( + char *Name); + +void +AeSetScope ( + char *Name); + +void +AeCloseDebugFile ( + void); + +void +AeOpenDebugFile ( + char *Name); + +ACPI_STATUS +AeDisplayAllMethods ( + UINT32 DisplayCount); + +ACPI_STATUS +AeInstallEarlyHandlers ( + void); + +ACPI_STATUS +AeInstallLateHandlers ( + void); + +void +AeMiscellaneousTests ( + void); + +ACPI_STATUS +AeRegionHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext); + +UINT32 +AeGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + void *Context); + +void +AeGlobalEventHandler ( + UINT32 Type, + ACPI_HANDLE GpeDevice, + UINT32 EventNumber, + void *Context); + +#endif /* _AECOMMON */ + diff --git a/source/tools/acpiexec/aeexec.c b/source/tools/acpiexec/aeexec.c new file mode 100644 index 000000000000..407519f9648e --- /dev/null +++ b/source/tools/acpiexec/aeexec.c @@ -0,0 +1,720 @@ +/****************************************************************************** + * + * Module Name: aeexec - Support routines for AcpiExec utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aecommon.h" + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("aeexec") + +/* Local prototypes */ + +static ACPI_STATUS +AeSetupConfiguration ( + void *RegionAddr); + +static void +AeTestBufferArgument ( + void); + +static void +AeTestPackageArgument ( + void); + +static ACPI_STATUS +AeGetDevices ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +ExecuteOSI ( + char *OsiString, + UINT32 ExpectedResult); + +static void +AeMutexInterfaces ( + void); + +static void +AeHardwareInterfaces ( + void); + +static void +AeGenericRegisters ( + void); + +#if (!ACPI_REDUCED_HARDWARE) +static void +AfInstallGpeBlock ( + void); +#endif /* !ACPI_REDUCED_HARDWARE */ + +extern unsigned char Ssdt3Code[]; + + +/****************************************************************************** + * + * FUNCTION: AeSetupConfiguration + * + * PARAMETERS: RegionAddr - Address for an ACPI table to be loaded + * dynamically. Test purposes only. + * + * RETURN: Status + * + * DESCRIPTION: Call AML _CFG configuration control method + * + *****************************************************************************/ + +static ACPI_STATUS +AeSetupConfiguration ( + void *RegionAddr) +{ + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg[3]; + + + /* + * Invoke _CFG method if present + */ + ArgList.Count = 1; + ArgList.Pointer = Arg; + + Arg[0].Type = ACPI_TYPE_INTEGER; + Arg[0].Integer.Value = ACPI_TO_INTEGER (RegionAddr); + + (void) AcpiEvaluateObject (NULL, "\\_CFG", &ArgList, NULL); + return (AE_OK); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * FUNCTION: AfInstallGpeBlock + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Test GPE block device initialization. Requires test ASL with + * A \GPE2 device. + * + *****************************************************************************/ + +static void +AfInstallGpeBlock ( + void) +{ + ACPI_STATUS Status; + ACPI_HANDLE Handle; + ACPI_HANDLE Handle2 = NULL; + ACPI_HANDLE Handle3 = NULL; + ACPI_GENERIC_ADDRESS BlockAddress; + ACPI_HANDLE GpeDevice; + + + Status = AcpiGetHandle (NULL, "\\_GPE", &Handle); + if (ACPI_FAILURE (Status)) + { + return; + } + + ACPI_MEMSET (&BlockAddress, 0, sizeof (ACPI_GENERIC_ADDRESS)); + BlockAddress.SpaceId = ACPI_ADR_SPACE_SYSTEM_MEMORY; + BlockAddress.Address = 0x76540000; + + Status = AcpiGetHandle (NULL, "\\GPE2", &Handle2); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 7, 8); + AE_CHECK_OK (AcpiInstallGpeBlock, Status); + + Status = AcpiInstallGpeHandler (Handle2, 8, + ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (Handle2, 8); + AE_CHECK_OK (AcpiEnableGpe, Status); + + Status = AcpiGetGpeDevice (0x30, &GpeDevice); + AE_CHECK_OK (AcpiGetGpeDevice, Status); + + Status = AcpiGetGpeDevice (0x42, &GpeDevice); + AE_CHECK_OK (AcpiGetGpeDevice, Status); + + Status = AcpiGetGpeDevice (AcpiCurrentGpeCount-1, &GpeDevice); + AE_CHECK_OK (AcpiGetGpeDevice, Status); + + Status = AcpiGetGpeDevice (AcpiCurrentGpeCount, &GpeDevice); + AE_CHECK_STATUS (AcpiGetGpeDevice, Status, AE_NOT_EXIST); + + Status = AcpiRemoveGpeHandler (Handle2, 8, AeGpeHandler); + AE_CHECK_OK (AcpiRemoveGpeHandler, Status); + } + + Status = AcpiGetHandle (NULL, "\\GPE3", &Handle3); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiInstallGpeBlock (Handle3, &BlockAddress, 8, 11); + AE_CHECK_OK (AcpiInstallGpeBlock, Status); + } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/* Test using a Buffer object as a method argument */ + +static void +AeTestBufferArgument ( + void) +{ + ACPI_OBJECT_LIST Params; + ACPI_OBJECT BufArg; + UINT8 Buffer[] = { + 0,0,0,0, + 4,0,0,0, + 1,2,3,4}; + + + BufArg.Type = ACPI_TYPE_BUFFER; + BufArg.Buffer.Length = 12; + BufArg.Buffer.Pointer = Buffer; + + Params.Count = 1; + Params.Pointer = &BufArg; + + (void) AcpiEvaluateObject (NULL, "\\BUF", &Params, NULL); +} + + +static ACPI_OBJECT PkgArg; +static ACPI_OBJECT PkgElements[5]; +static ACPI_OBJECT Pkg2Elements[5]; +static ACPI_OBJECT_LIST Params; + + +/* + * Test using a Package object as an method argument + */ +static void +AeTestPackageArgument ( + void) +{ + + /* Main package */ + + PkgArg.Type = ACPI_TYPE_PACKAGE; + PkgArg.Package.Count = 4; + PkgArg.Package.Elements = PkgElements; + + /* Main package elements */ + + PkgElements[0].Type = ACPI_TYPE_INTEGER; + PkgElements[0].Integer.Value = 0x22228888; + + PkgElements[1].Type = ACPI_TYPE_STRING; + PkgElements[1].String.Length = sizeof ("Top-level package"); + PkgElements[1].String.Pointer = "Top-level package"; + + PkgElements[2].Type = ACPI_TYPE_BUFFER; + PkgElements[2].Buffer.Length = sizeof ("XXXX"); + PkgElements[2].Buffer.Pointer = (UINT8 *) "XXXX"; + + PkgElements[3].Type = ACPI_TYPE_PACKAGE; + PkgElements[3].Package.Count = 2; + PkgElements[3].Package.Elements = Pkg2Elements; + + /* Sub-package elements */ + + Pkg2Elements[0].Type = ACPI_TYPE_INTEGER; + Pkg2Elements[0].Integer.Value = 0xAAAABBBB; + + Pkg2Elements[1].Type = ACPI_TYPE_STRING; + Pkg2Elements[1].String.Length = sizeof ("Nested Package"); + Pkg2Elements[1].String.Pointer = "Nested Package"; + + /* Parameter object */ + + Params.Count = 1; + Params.Pointer = &PkgArg; + + (void) AcpiEvaluateObject (NULL, "\\_PKG", &Params, NULL); +} + + +static ACPI_STATUS +AeGetDevices ( + ACPI_HANDLE ObjHandle, + UINT32 NestingLevel, + void *Context, + void **ReturnValue) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: ExecuteOSI + * + * PARAMETERS: OsiString - String passed to _OSI method + * ExpectedResult - 0 (FALSE) or 0xFFFFFFFF (TRUE) + * + * RETURN: Status + * + * DESCRIPTION: Execute the internally implemented (in ACPICA) _OSI method. + * + *****************************************************************************/ + +static ACPI_STATUS +ExecuteOSI ( + char *OsiString, + UINT32 ExpectedResult) +{ + ACPI_STATUS Status; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg[1]; + ACPI_BUFFER ReturnValue; + ACPI_OBJECT *Obj; + + + /* Setup input argument */ + + ArgList.Count = 1; + ArgList.Pointer = Arg; + + Arg[0].Type = ACPI_TYPE_STRING; + Arg[0].String.Pointer = OsiString; + Arg[0].String.Length = strlen (Arg[0].String.Pointer); + + /* Ask ACPICA to allocate space for the return object */ + + ReturnValue.Length = ACPI_ALLOCATE_BUFFER; + + Status = AcpiEvaluateObject (NULL, "\\_OSI", &ArgList, &ReturnValue); + + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not execute _OSI method, %s\n", + AcpiFormatException (Status)); + return (Status); + } + + if (ReturnValue.Length < sizeof (ACPI_OBJECT)) + { + AcpiOsPrintf ("Return value from _OSI method too small, %.8X\n", + ReturnValue.Length); + return (AE_ERROR); + } + + Obj = ReturnValue.Pointer; + if (Obj->Type != ACPI_TYPE_INTEGER) + { + AcpiOsPrintf ("Invalid return type from _OSI method, %.2X\n", Obj->Type); + return (AE_ERROR); + } + + if (Obj->Integer.Value != ExpectedResult) + { + AcpiOsPrintf ("Invalid return value from _OSI, expected %.8X found %.8X\n", + ExpectedResult, (UINT32) Obj->Integer.Value); + return (AE_ERROR); + } + + /* Reset the OSI data */ + + AcpiGbl_OsiData = 0; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeGenericRegisters + * + * DESCRIPTION: Call the AcpiRead/Write interfaces. + * + *****************************************************************************/ + +static ACPI_GENERIC_ADDRESS GenericRegister; + +static void +AeGenericRegisters ( + void) +{ + ACPI_STATUS Status; + UINT64 Value; + + + GenericRegister.Address = 0x1234; + GenericRegister.BitWidth = 64; + GenericRegister.BitOffset = 0; + GenericRegister.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO; + + Status = AcpiRead (&Value, &GenericRegister); + AE_CHECK_OK (AcpiRead, Status); + + Status = AcpiWrite (Value, &GenericRegister); + AE_CHECK_OK (AcpiWrite, Status); + + GenericRegister.Address = 0x12345678; + GenericRegister.BitOffset = 0; + GenericRegister.SpaceId = ACPI_ADR_SPACE_SYSTEM_MEMORY; + + Status = AcpiRead (&Value, &GenericRegister); + AE_CHECK_OK (AcpiRead, Status); + + Status = AcpiWrite (Value, &GenericRegister); + AE_CHECK_OK (AcpiWrite, Status); +} + + +/****************************************************************************** + * + * FUNCTION: AeMutexInterfaces + * + * DESCRIPTION: Exercise the AML mutex access interfaces + * + *****************************************************************************/ + +static void +AeMutexInterfaces ( + void) +{ + ACPI_STATUS Status; + ACPI_HANDLE MutexHandle; + + + /* Get a handle to an AML mutex */ + + Status = AcpiGetHandle (NULL, "\\MTX1", &MutexHandle); + if (Status == AE_NOT_FOUND) + { + return; + } + + AE_CHECK_OK (AcpiGetHandle, Status); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Acquire the mutex */ + + Status = AcpiAcquireMutex (NULL, "\\MTX1", 0xFFFF); + AE_CHECK_OK (AcpiAcquireMutex, Status); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Release mutex with different parameters */ + + Status = AcpiReleaseMutex (MutexHandle, NULL); + AE_CHECK_OK (AcpiReleaseMutex, Status); +} + + +/****************************************************************************** + * + * FUNCTION: AeHardwareInterfaces + * + * DESCRIPTION: Call various hardware support interfaces + * + *****************************************************************************/ + +static void +AeHardwareInterfaces ( + void) +{ +#if (!ACPI_REDUCED_HARDWARE) + + ACPI_STATUS Status; + UINT32 Value; + + + /* If Hardware Reduced flag is set, we are all done */ + + if (AcpiGbl_ReducedHardware) + { + return; + } + + Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, 1); + AE_CHECK_OK (AcpiWriteBitRegister, Status); + + Status = AcpiWriteBitRegister (ACPI_BITREG_GLOBAL_LOCK_ENABLE, 1); + AE_CHECK_OK (AcpiWriteBitRegister, Status); + + Status = AcpiWriteBitRegister (ACPI_BITREG_SLEEP_ENABLE, 1); + AE_CHECK_OK (AcpiWriteBitRegister, Status); + + Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1); + AE_CHECK_OK (AcpiWriteBitRegister, Status); + + + Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &Value); + AE_CHECK_OK (AcpiReadBitRegister, Status); + + Status = AcpiReadBitRegister (ACPI_BITREG_GLOBAL_LOCK_ENABLE, &Value); + AE_CHECK_OK (AcpiReadBitRegister, Status); + + Status = AcpiReadBitRegister (ACPI_BITREG_SLEEP_ENABLE, &Value); + AE_CHECK_OK (AcpiReadBitRegister, Status); + + Status = AcpiReadBitRegister (ACPI_BITREG_ARB_DISABLE, &Value); + AE_CHECK_OK (AcpiReadBitRegister, Status); + +#endif /* !ACPI_REDUCED_HARDWARE */ +} + + +/****************************************************************************** + * + * FUNCTION: AeMiscellaneousTests + * + * DESCRIPTION: Various ACPICA validation tests. + * + *****************************************************************************/ + +void +AeMiscellaneousTests ( + void) +{ + ACPI_BUFFER ReturnBuf; + char Buffer[32]; + ACPI_STATUS Status; + ACPI_STATISTICS Stats; + +#if (!ACPI_REDUCED_HARDWARE) + ACPI_HANDLE Handle; + ACPI_VENDOR_UUID Uuid = {0, {ACPI_INIT_UUID (0,0,0,0,0,0,0,0,0,0,0)}}; + UINT32 LockHandle1; + UINT32 LockHandle2; +#endif /* !ACPI_REDUCED_HARDWARE */ + + + AeHardwareInterfaces (); + AeGenericRegisters (); + AeSetupConfiguration (Ssdt3Code); + + AeTestBufferArgument(); + AeTestPackageArgument (); + AeMutexInterfaces (); + + Status = AcpiInstallInterface (""); + AE_CHECK_STATUS (AcpiInstallInterface, Status, AE_BAD_PARAMETER); + + Status = AcpiInstallInterface ("TestString"); + AE_CHECK_OK (AcpiInstallInterface, Status); + + Status = AcpiInstallInterface ("TestString"); + AE_CHECK_STATUS (AcpiInstallInterface, Status, AE_ALREADY_EXISTS); + + Status = AcpiRemoveInterface ("Windows 2006"); + AE_CHECK_OK (AcpiRemoveInterface, Status); + + Status = AcpiRemoveInterface ("TestString"); + AE_CHECK_OK (AcpiRemoveInterface, Status); + + Status = AcpiRemoveInterface ("XXXXXX"); + AE_CHECK_STATUS (AcpiRemoveInterface, Status, AE_NOT_EXIST); + + Status = AcpiInstallInterface ("AnotherTestString"); + AE_CHECK_OK (AcpiInstallInterface, Status); + + + Status = ExecuteOSI ("Windows 2001", 0xFFFFFFFF); + AE_CHECK_OK (ExecuteOSI, Status); + + Status = ExecuteOSI ("MichiganTerminalSystem", 0); + AE_CHECK_OK (ExecuteOSI, Status); + + + ReturnBuf.Length = 32; + ReturnBuf.Pointer = Buffer; + + Status = AcpiGetName (AcpiGbl_RootNode, ACPI_FULL_PATHNAME, &ReturnBuf); + AE_CHECK_OK (AcpiGetName, Status); + + /* Get Devices */ + + Status = AcpiGetDevices (NULL, AeGetDevices, NULL, NULL); + AE_CHECK_OK (AcpiGetDevices, Status); + + Status = AcpiGetStatistics (&Stats); + AE_CHECK_OK (AcpiGetStatistics, Status); + + +#if (!ACPI_REDUCED_HARDWARE) + + Status = AcpiInstallGlobalEventHandler (AeGlobalEventHandler, NULL); + AE_CHECK_OK (AcpiInstallGlobalEventHandler, Status); + + /* If Hardware Reduced flag is set, we are all done */ + + if (AcpiGbl_ReducedHardware) + { + return; + } + + Status = AcpiEnableEvent (ACPI_EVENT_GLOBAL, 0); + AE_CHECK_OK (AcpiEnableEvent, Status); + + /* + * GPEs: Handlers, enable/disable, etc. + */ + Status = AcpiInstallGpeHandler (NULL, 0, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 0); + AE_CHECK_OK (AcpiEnableGpe, Status); + + Status = AcpiRemoveGpeHandler (NULL, 0, AeGpeHandler); + AE_CHECK_OK (AcpiRemoveGpeHandler, Status); + + Status = AcpiInstallGpeHandler (NULL, 0, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 0); + AE_CHECK_OK (AcpiEnableGpe, Status); + + Status = AcpiSetGpe (NULL, 0, ACPI_GPE_DISABLE); + AE_CHECK_OK (AcpiSetGpe, Status); + + Status = AcpiSetGpe (NULL, 0, ACPI_GPE_ENABLE); + AE_CHECK_OK (AcpiSetGpe, Status); + + + Status = AcpiInstallGpeHandler (NULL, 1, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 1); + AE_CHECK_OK (AcpiEnableGpe, Status); + + + Status = AcpiInstallGpeHandler (NULL, 2, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 2); + AE_CHECK_OK (AcpiEnableGpe, Status); + + + Status = AcpiInstallGpeHandler (NULL, 3, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiInstallGpeHandler (NULL, 4, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiInstallGpeHandler (NULL, 5, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiGetHandle (NULL, "\\_SB", &Handle); + AE_CHECK_OK (AcpiGetHandle, Status); + + Status = AcpiSetupGpeForWake (Handle, NULL, 5); + AE_CHECK_OK (AcpiSetupGpeForWake, Status); + + Status = AcpiSetGpeWakeMask (NULL, 5, ACPI_GPE_ENABLE); + AE_CHECK_OK (AcpiGpeWakeup, Status); + + Status = AcpiSetupGpeForWake (Handle, NULL, 6); + AE_CHECK_OK (AcpiSetupGpeForWake, Status); + + Status = AcpiSetupGpeForWake (Handle, NULL, 9); + AE_CHECK_OK (AcpiSetupGpeForWake, Status); + + Status = AcpiInstallGpeHandler (NULL, 0x19, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 0x19); + AE_CHECK_OK (AcpiEnableGpe, Status); + + + Status = AcpiInstallGpeHandler (NULL, 0x62, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AE_CHECK_OK (AcpiInstallGpeHandler, Status); + + Status = AcpiEnableGpe (NULL, 0x62); + AE_CHECK_OK (AcpiEnableGpe, Status); + + Status = AcpiDisableGpe (NULL, 0x62); + AE_CHECK_OK (AcpiDisableGpe, Status); + + AfInstallGpeBlock (); + + /* Here is where the GPEs are actually "enabled" */ + + Status = AcpiUpdateAllGpes (); + AE_CHECK_OK (AcpiUpdateAllGpes, Status); + + Status = AcpiGetHandle (NULL, "RSRC", &Handle); + if (ACPI_SUCCESS (Status)) + { + ReturnBuf.Length = ACPI_ALLOCATE_BUFFER; + + Status = AcpiGetVendorResource (Handle, "_CRS", &Uuid, &ReturnBuf); + if (ACPI_SUCCESS (Status)) + { + AcpiOsFree (ReturnBuf.Pointer); + } + } + + /* Test global lock */ + + Status = AcpiAcquireGlobalLock (0xFFFF, &LockHandle1); + AE_CHECK_OK (AcpiAcquireGlobalLock, Status); + + Status = AcpiAcquireGlobalLock (0x5, &LockHandle2); + AE_CHECK_OK (AcpiAcquireGlobalLock, Status); + + Status = AcpiReleaseGlobalLock (LockHandle1); + AE_CHECK_OK (AcpiReleaseGlobalLock, Status); + + Status = AcpiReleaseGlobalLock (LockHandle2); + AE_CHECK_OK (AcpiReleaseGlobalLock, Status); + +#endif /* !ACPI_REDUCED_HARDWARE */ +} + diff --git a/source/tools/acpiexec/aehandlers.c b/source/tools/acpiexec/aehandlers.c new file mode 100644 index 000000000000..f41dd53d31ed --- /dev/null +++ b/source/tools/acpiexec/aehandlers.c @@ -0,0 +1,1251 @@ +/****************************************************************************** + * + * Module Name: aehandlers - Various handlers for acpiexec + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aecommon.h" + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("aehandlers") + +/* Local prototypes */ + +static void +AeNotifyHandler ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context); + +static void +AeDeviceNotifyHandler ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context); + +static ACPI_STATUS +AeExceptionHandler ( + ACPI_STATUS AmlStatus, + ACPI_NAME Name, + UINT16 Opcode, + UINT32 AmlOffset, + void *Context); + +static ACPI_STATUS +AeTableHandler ( + UINT32 Event, + void *Table, + void *Context); + +static ACPI_STATUS +AeRegionInit ( + ACPI_HANDLE RegionHandle, + UINT32 Function, + void *HandlerContext, + void **RegionContext); + +static void +AeAttachedDataHandler ( + ACPI_HANDLE Object, + void *Data); + +static UINT32 +AeInterfaceHandler ( + ACPI_STRING InterfaceName, + UINT32 Supported); + +#if (!ACPI_REDUCED_HARDWARE) +static UINT32 +AeEventHandler ( + void *Context); + +static char *TableEvents[] = +{ + "LOAD", + "UNLOAD", + "UNKNOWN" +}; +#endif /* !ACPI_REDUCED_HARDWARE */ + +static UINT32 SigintCount = 0; +static AE_DEBUG_REGIONS AeRegions; +BOOLEAN AcpiGbl_DisplayRegionAccess = FALSE; + + +/* + * We will override some of the default region handlers, especially the + * SystemMemory handler, which must be implemented locally. Do not override + * the PCI_Config handler since we would like to exercise the default handler + * code. These handlers are installed "early" - before any _REG methods + * are executed - since they are special in the sense that tha ACPI spec + * declares that they must "always be available". Cannot override the + * DataTable region handler either -- needed for test execution. + */ +static ACPI_ADR_SPACE_TYPE DefaultSpaceIdList[] = +{ + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO +}; + +/* + * We will install handlers for some of the various address space IDs. + * Test one user-defined address space (used by aslts.) + */ +#define ACPI_ADR_SPACE_USER_DEFINED1 0x80 +#define ACPI_ADR_SPACE_USER_DEFINED2 0xE4 + +static ACPI_ADR_SPACE_TYPE SpaceIdList[] = +{ + ACPI_ADR_SPACE_EC, + ACPI_ADR_SPACE_SMBUS, + ACPI_ADR_SPACE_GSBUS, + ACPI_ADR_SPACE_GPIO, + ACPI_ADR_SPACE_PCI_BAR_TARGET, + ACPI_ADR_SPACE_IPMI, + ACPI_ADR_SPACE_FIXED_HARDWARE, + ACPI_ADR_SPACE_USER_DEFINED1, + ACPI_ADR_SPACE_USER_DEFINED2 +}; + + +static ACPI_CONNECTION_INFO AeMyContext; + +/****************************************************************************** + * + * FUNCTION: AeCtrlCHandler + * + * PARAMETERS: Sig + * + * RETURN: none + * + * DESCRIPTION: Control-C handler. Abort running control method if any. + * + *****************************************************************************/ + +void ACPI_SYSTEM_XFACE +AeCtrlCHandler ( + int Sig) +{ + + signal (SIGINT, SIG_IGN); + SigintCount++; + + AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount); + + if (AcpiGbl_MethodExecuting) + { + AcpiGbl_AbortMethod = TRUE; + signal (SIGINT, AeCtrlCHandler); + + if (SigintCount < 10) + { + return; + } + } + + exit (0); +} + + +/****************************************************************************** + * + * FUNCTION: AeNotifyHandler + * + * PARAMETERS: Standard notify handler parameters + * + * RETURN: Status + * + * DESCRIPTION: System notify handler for AcpiExec utility. Used by the ASL + * test suite(s) to communicate errors and other information to + * this utility via the Notify() operator. + * + *****************************************************************************/ + +static void +AeNotifyHandler ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context) +{ + + switch (Value) + { +#if 0 + case 0: + printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n"); + } + break; + + + case 1: + printf ("[AcpiExec] Method Error: Incorrect numeric result\n"); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n"); + } + break; + + + case 2: + printf ("[AcpiExec] Method Error: An operand was overwritten\n"); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n"); + } + break; + +#endif + + default: + printf ("[AcpiExec] Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", + AcpiUtGetNodeName (Device), Device, Value, + AcpiUtGetNotifyName (Value)); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("[AcpiExec] Received a system notify, Value 0x%2.2X\n", Value); + } + + (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); + break; + } +} + + +/****************************************************************************** + * + * FUNCTION: AeDeviceNotifyHandler + * + * PARAMETERS: Standard notify handler parameters + * + * RETURN: Status + * + * DESCRIPTION: Device notify handler for AcpiExec utility. Used by the ASL + * test suite(s) to communicate errors and other information to + * this utility via the Notify() operator. + * + *****************************************************************************/ + +static void +AeDeviceNotifyHandler ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context) +{ + + printf ("[AcpiExec] Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", + AcpiUtGetNodeName (Device), Device, Value, + AcpiUtGetNotifyName (Value)); + if (AcpiGbl_DebugFile) + { + AcpiOsPrintf ("[AcpiExec] Received a device notify, Value 0x%2.2X\n", Value); + } + + (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); +} + + +/****************************************************************************** + * + * FUNCTION: AeExceptionHandler + * + * PARAMETERS: Standard exception handler parameters + * + * RETURN: Status + * + * DESCRIPTION: System exception handler for AcpiExec utility. + * + *****************************************************************************/ + +static ACPI_STATUS +AeExceptionHandler ( + ACPI_STATUS AmlStatus, + ACPI_NAME Name, + UINT16 Opcode, + UINT32 AmlOffset, + void *Context) +{ + ACPI_STATUS NewAmlStatus = AmlStatus; + ACPI_STATUS Status; + ACPI_BUFFER ReturnObj; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg[3]; + const char *Exception; + + + Exception = AcpiFormatException (AmlStatus); + AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception); + if (Name) + { + AcpiOsPrintf ("of method [%4.4s]", (char *) &Name); + } + else + { + AcpiOsPrintf ("at module level (table load)"); + } + AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset); + + /* + * Invoke the _ERR method if present + * + * Setup parameter object + */ + ArgList.Count = 3; + ArgList.Pointer = Arg; + + Arg[0].Type = ACPI_TYPE_INTEGER; + Arg[0].Integer.Value = AmlStatus; + + Arg[1].Type = ACPI_TYPE_STRING; + Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception); + Arg[1].String.Length = ACPI_STRLEN (Exception); + + Arg[2].Type = ACPI_TYPE_INTEGER; + Arg[2].Integer.Value = AcpiOsGetThreadId(); + + /* Setup return buffer */ + + ReturnObj.Pointer = NULL; + ReturnObj.Length = ACPI_ALLOCATE_BUFFER; + + Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj); + if (ACPI_SUCCESS (Status)) + { + if (ReturnObj.Pointer) + { + /* Override original status */ + + NewAmlStatus = (ACPI_STATUS) + ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value; + + AcpiOsFree (ReturnObj.Pointer); + } + } + else if (Status != AE_NOT_FOUND) + { + AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n", + AcpiFormatException (Status)); + } + + /* Global override */ + + if (AcpiGbl_IgnoreErrors) + { + NewAmlStatus = AE_OK; + } + + if (NewAmlStatus != AmlStatus) + { + AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n", + AcpiFormatException (NewAmlStatus)); + } + + return (NewAmlStatus); +} + + +/****************************************************************************** + * + * FUNCTION: AeTableHandler + * + * PARAMETERS: Table handler + * + * RETURN: Status + * + * DESCRIPTION: System table handler for AcpiExec utility. + * + *****************************************************************************/ + +static ACPI_STATUS +AeTableHandler ( + UINT32 Event, + void *Table, + void *Context) +{ +#if (!ACPI_REDUCED_HARDWARE) + ACPI_STATUS Status; +#endif /* !ACPI_REDUCED_HARDWARE */ + + + if (Event > ACPI_NUM_TABLE_EVENTS) + { + Event = ACPI_NUM_TABLE_EVENTS; + } + +#if (!ACPI_REDUCED_HARDWARE) + /* Enable any GPEs associated with newly-loaded GPE methods */ + + Status = AcpiUpdateAllGpes (); + AE_CHECK_OK (AcpiUpdateAllGpes, Status); + + printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n", + TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table); +#endif /* !ACPI_REDUCED_HARDWARE */ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeGpeHandler + * + * DESCRIPTION: Common GPE handler for acpiexec + * + *****************************************************************************/ + +UINT32 +AeGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + void *Context) +{ + ACPI_NAMESPACE_NODE *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice; + + + AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE%02X (GPE block %4.4s)\n", + GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT"); + + return (ACPI_REENABLE_GPE); +} + + +/****************************************************************************** + * + * FUNCTION: AeGlobalEventHandler + * + * DESCRIPTION: Global GPE/Fixed event handler + * + *****************************************************************************/ + +void +AeGlobalEventHandler ( + UINT32 Type, + ACPI_HANDLE Device, + UINT32 EventNumber, + void *Context) +{ + char *TypeName; + + + switch (Type) + { + case ACPI_EVENT_TYPE_GPE: + TypeName = "GPE"; + break; + + case ACPI_EVENT_TYPE_FIXED: + TypeName = "FixedEvent"; + break; + + default: + TypeName = "UNKNOWN"; + break; + } + + AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n", + TypeName, EventNumber, Device); +} + + +/****************************************************************************** + * + * FUNCTION: AeAttachedDataHandler + * + * DESCRIPTION: Handler for deletion of nodes with attached data (attached via + * AcpiAttachData) + * + *****************************************************************************/ + +static void +AeAttachedDataHandler ( + ACPI_HANDLE Object, + void *Data) +{ + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data); + + + AcpiOsPrintf ("Received an attached data deletion on %4.4s\n", + Node->Name.Ascii); +} + + +/****************************************************************************** + * + * FUNCTION: AeInterfaceHandler + * + * DESCRIPTION: Handler for _OSI invocations + * + *****************************************************************************/ + +static UINT32 +AeInterfaceHandler ( + ACPI_STRING InterfaceName, + UINT32 Supported) +{ + ACPI_FUNCTION_NAME (AeInterfaceHandler); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Received _OSI (\"%s\"), is %ssupported\n", + InterfaceName, Supported == 0 ? "not " : "")); + + return (Supported); +} + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * FUNCTION: AeEventHandler + * + * DESCRIPTION: Handler for Fixed Events + * + *****************************************************************************/ + +static UINT32 +AeEventHandler ( + void *Context) +{ + return (0); +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/****************************************************************************** + * + * FUNCTION: AeRegionInit + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Opregion init function. + * + *****************************************************************************/ + +static ACPI_STATUS +AeRegionInit ( + ACPI_HANDLE RegionHandle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + /* + * Real simple, set the RegionContext to the RegionHandle + */ + *RegionContext = RegionHandle; + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeInstallLateHandlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install handlers for the AcpiExec utility. + * + *****************************************************************************/ + +ACPI_STATUS +AeInstallLateHandlers ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + +#if (!ACPI_REDUCED_HARDWARE) + if (!AcpiGbl_ReducedHardware) + { + /* Install some fixed event handlers */ + + Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL); + AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); + + Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL); + AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); + } +#endif /* !ACPI_REDUCED_HARDWARE */ + + AeMyContext.Connection = NULL; + AeMyContext.AccessLength = 0xA5; + + /* + * Install handlers for some of the "device driver" address spaces + * such as EC, SMBus, etc. + */ + for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++) + { + /* Install handler at the root object */ + + Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode, + SpaceIdList[i], AeRegionHandler, + AeRegionInit, &AeMyContext); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not install an OpRegion handler for %s space(%u)", + AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i])); + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeInstallEarlyHandlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install handlers for the AcpiExec utility. + * + * Notes: Don't install handler for PCI_Config, we want to use the + * default handler to exercise that code. + * + *****************************************************************************/ + +ACPI_STATUS +AeInstallEarlyHandlers ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + ACPI_HANDLE Handle; + + + ACPI_FUNCTION_ENTRY (); + + + Status = AcpiInstallInterfaceHandler (AeInterfaceHandler); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install interface handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiInstallTableHandler (AeTableHandler, NULL); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install table handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiInstallExceptionHandler (AeExceptionHandler); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install exception handler, %s\n", + AcpiFormatException (Status)); + } + + /* Install global notify handler */ + + Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, + AeNotifyHandler, NULL); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install a global notify handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, + AeDeviceNotifyHandler, NULL); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install a global notify handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiGetHandle (NULL, "\\_SB", &Handle); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, + AeNotifyHandler, NULL); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install a notify handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, + AeNotifyHandler); + if (ACPI_FAILURE (Status)) + { + printf ("Could not remove a notify handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, + AeNotifyHandler, NULL); + AE_CHECK_OK (AcpiInstallNotifyHandler, Status); + + Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY, + AeNotifyHandler); + AE_CHECK_OK (AcpiRemoveNotifyHandler, Status); + + Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, + AeNotifyHandler, NULL); + if (ACPI_FAILURE (Status)) + { + printf ("Could not install a notify handler, %s\n", + AcpiFormatException (Status)); + } + + Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); + AE_CHECK_OK (AcpiAttachData, Status); + + Status = AcpiDetachData (Handle, AeAttachedDataHandler); + AE_CHECK_OK (AcpiDetachData, Status); + + Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); + AE_CHECK_OK (AcpiAttachData, Status); + } + else + { + printf ("No _SB_ found, %s\n", AcpiFormatException (Status)); + } + + + /* + * Install handlers that will override the default handlers for some of + * the space IDs. + */ + for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++) + { + /* Install handler at the root object */ + + Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode, + DefaultSpaceIdList[i], AeRegionHandler, + AeRegionInit, &AeMyContext); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not install a default OpRegion handler for %s space(%u)", + AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]), + DefaultSpaceIdList[i])); + return (Status); + } + } + + /* + * Initialize the global Region Handler space + * MCW 3/23/00 + */ + AeRegions.NumberOfRegions = 0; + AeRegions.RegionList = NULL; + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AeRegionHandler + * + * PARAMETERS: Standard region handler parameters + * + * RETURN: Status + * + * DESCRIPTION: Test handler - Handles some dummy regions via memory that can + * be manipulated in Ring 3. Simulates actual reads and writes. + * + *****************************************************************************/ + +ACPI_STATUS +AeRegionHandler ( + UINT32 Function, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 BitWidth, + UINT64 *Value, + void *HandlerContext, + void *RegionContext) +{ + + ACPI_OPERAND_OBJECT *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext); + UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Value); + ACPI_PHYSICAL_ADDRESS BaseAddress; + ACPI_SIZE Length; + BOOLEAN BufferExists; + AE_REGION *RegionElement; + void *BufferValue; + ACPI_STATUS Status; + UINT32 ByteWidth; + UINT32 i; + UINT8 SpaceId; + ACPI_CONNECTION_INFO *MyContext; + UINT32 Value1; + UINT32 Value2; + ACPI_RESOURCE *Resource; + + + ACPI_FUNCTION_NAME (AeRegionHandler); + + /* + * If the object is not a region, simply return + */ + if (RegionObject->Region.Type != ACPI_TYPE_REGION) + { + return (AE_OK); + } + + /* Check that we actually got back our context parameter */ + + if (HandlerContext != &AeMyContext) + { + printf ("Region handler received incorrect context %p, should be %p\n", + HandlerContext, &AeMyContext); + } + + MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext); + + /* + * Find the region's address space and length before searching + * the linked list. + */ + BaseAddress = RegionObject->Region.Address; + Length = (ACPI_SIZE) RegionObject->Region.Length; + SpaceId = RegionObject->Region.SpaceId; + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n", + AcpiUtGetRegionName (RegionObject->Region.SpaceId), + (UINT32) Address)); + + /* + * Region support can be disabled with the -do option. + * We use this to support dynamically loaded tables where we pass a valid + * address to the AML. + */ + if (AcpiGbl_DbOpt_NoRegionSupport) + { + BufferValue = ACPI_TO_POINTER (Address); + ByteWidth = (BitWidth / 8); + + if (BitWidth % 8) + { + ByteWidth += 1; + } + goto DoFunction; + } + + switch (SpaceId) + { + case ACPI_ADR_SPACE_SYSTEM_IO: + /* + * For I/O space, exercise the port validation + * Note: ReadPort currently always returns all ones, length=BitLength + */ + switch (Function & ACPI_IO_MASK) + { + case ACPI_READ: + + if (BitWidth == 64) + { + /* Split the 64-bit request into two 32-bit requests */ + + Status = AcpiHwReadPort (Address, &Value1, 32); + AE_CHECK_OK (AcpiHwReadPort, Status); + Status = AcpiHwReadPort (Address+4, &Value2, 32); + AE_CHECK_OK (AcpiHwReadPort, Status); + + *Value = Value1 | ((UINT64) Value2 << 32); + } + else + { + Status = AcpiHwReadPort (Address, &Value1, BitWidth); + AE_CHECK_OK (AcpiHwReadPort, Status); + *Value = (UINT64) Value1; + } + break; + + case ACPI_WRITE: + + if (BitWidth == 64) + { + /* Split the 64-bit request into two 32-bit requests */ + + Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32); + AE_CHECK_OK (AcpiHwWritePort, Status); + Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32); + AE_CHECK_OK (AcpiHwWritePort, Status); + } + else + { + Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth); + AE_CHECK_OK (AcpiHwWritePort, Status); + } + break; + + default: + Status = AE_BAD_PARAMETER; + break; + } + + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Now go ahead and simulate the hardware */ + break; + + /* + * SMBus and GenericSerialBus support the various bidirectional + * protocols. + */ + case ACPI_ADR_SPACE_SMBUS: + case ACPI_ADR_SPACE_GSBUS: /* ACPI 5.0 */ + + Length = 0; + + switch (Function & ACPI_IO_MASK) + { + case ACPI_READ: + switch (Function >> 16) + { + case AML_FIELD_ATTRIB_QUICK: + case AML_FIELD_ATTRIB_SEND_RCV: + case AML_FIELD_ATTRIB_BYTE: + Length = 1; + break; + + case AML_FIELD_ATTRIB_WORD: + case AML_FIELD_ATTRIB_WORD_CALL: + Length = 2; + break; + + case AML_FIELD_ATTRIB_BLOCK: + case AML_FIELD_ATTRIB_BLOCK_CALL: + Length = 32; + break; + + + case AML_FIELD_ATTRIB_MULTIBYTE: + case AML_FIELD_ATTRIB_RAW_BYTES: + case AML_FIELD_ATTRIB_RAW_PROCESS: + + /* (-2) for status/length */ + Length = MyContext->AccessLength - 2; + break; + + default: + break; + } + break; + + case ACPI_WRITE: + switch (Function >> 16) + { + case AML_FIELD_ATTRIB_QUICK: + case AML_FIELD_ATTRIB_SEND_RCV: + case AML_FIELD_ATTRIB_BYTE: + case AML_FIELD_ATTRIB_WORD: + case AML_FIELD_ATTRIB_BLOCK: + Length = 0; + break; + + case AML_FIELD_ATTRIB_WORD_CALL: + Length = 2; + break; + + case AML_FIELD_ATTRIB_BLOCK_CALL: + Length = 32; + break; + + case AML_FIELD_ATTRIB_MULTIBYTE: + case AML_FIELD_ATTRIB_RAW_BYTES: + case AML_FIELD_ATTRIB_RAW_PROCESS: + + /* (-2) for status/length */ + Length = MyContext->AccessLength - 2; + break; + + default: + break; + } + break; + + default: + break; + } + + if (AcpiGbl_DisplayRegionAccess) + { + AcpiOsPrintf ("AcpiExec: %s " + "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X", + AcpiUtGetRegionName (SpaceId), + (Function & ACPI_IO_MASK) ? "Write" : "Read ", + (UINT32) (Function >> 16), + (UINT32) Address, (UINT32) BaseAddress, + Length, BitWidth, Buffer[1]); + + /* GenericSerialBus has a Connection() parameter */ + + if (SpaceId == ACPI_ADR_SPACE_GSBUS) + { + Status = AcpiBufferToResource (MyContext->Connection, + MyContext->Length, &Resource); + + AcpiOsPrintf (" [AccLen %.2X Conn %p]", + MyContext->AccessLength, MyContext->Connection); + } + AcpiOsPrintf ("\n"); + } + + /* Setup the return buffer. Note: ASLTS depends on these fill values */ + + for (i = 0; i < Length; i++) + { + Buffer[i+2] = (UINT8) (0xA0 + i); + } + + Buffer[0] = 0x7A; + Buffer[1] = (UINT8) Length; + return (AE_OK); + + + case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */ + + if (AcpiGbl_DisplayRegionAccess) + { + AcpiOsPrintf ("AcpiExec: IPMI " + "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n", + (Function & ACPI_IO_MASK) ? "Write" : "Read ", + (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress, + Length, BitWidth, Buffer[1]); + } + + /* + * Regardless of a READ or WRITE, this handler is passed a 66-byte + * buffer in which to return the IPMI status/length/data. + * + * Return some example data to show use of the bidirectional buffer + */ + Buffer[0] = 0; /* Status byte */ + Buffer[1] = 64; /* Return buffer data length */ + Buffer[2] = 0; /* Completion code */ + Buffer[3] = 0; /* Reserved */ + + /* + * Fill the 66-byte buffer with the return data. + * Note: ASLTS depends on these fill values. + */ + for (i = 4; i < 66; i++) + { + Buffer[i] = (UINT8) (i); + } + return (AE_OK); + + default: + break; + } + + /* + * Search through the linked list for this region's buffer + */ + BufferExists = FALSE; + RegionElement = AeRegions.RegionList; + + if (AeRegions.NumberOfRegions) + { + while (!BufferExists && RegionElement) + { + if (RegionElement->Address == BaseAddress && + RegionElement->Length == Length && + RegionElement->SpaceId == SpaceId) + { + BufferExists = TRUE; + } + else + { + RegionElement = RegionElement->NextRegion; + } + } + } + + /* + * If the Region buffer does not exist, create it now + */ + if (!BufferExists) + { + /* + * Do the memory allocations first + */ + RegionElement = AcpiOsAllocate (sizeof (AE_REGION)); + if (!RegionElement) + { + return (AE_NO_MEMORY); + } + + RegionElement->Buffer = AcpiOsAllocate (Length); + if (!RegionElement->Buffer) + { + AcpiOsFree (RegionElement); + return (AE_NO_MEMORY); + } + + /* Initialize the region with the default fill value */ + + ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length); + + RegionElement->Address = BaseAddress; + RegionElement->Length = Length; + RegionElement->SpaceId = SpaceId; + RegionElement->NextRegion = NULL; + + /* + * Increment the number of regions and put this one + * at the head of the list as it will probably get accessed + * more often anyway. + */ + AeRegions.NumberOfRegions += 1; + + if (AeRegions.RegionList) + { + RegionElement->NextRegion = AeRegions.RegionList; + } + + AeRegions.RegionList = RegionElement; + } + + /* + * Calculate the size of the memory copy + */ + ByteWidth = (BitWidth / 8); + + if (BitWidth % 8) + { + ByteWidth += 1; + } + + /* + * The buffer exists and is pointed to by RegionElement. + * We now need to verify the request is valid and perform the operation. + * + * NOTE: RegionElement->Length is in bytes, therefore it we compare against + * ByteWidth (see above) + */ + if (((UINT64) Address + ByteWidth) > + ((UINT64)(RegionElement->Address) + RegionElement->Length)) + { + ACPI_WARNING ((AE_INFO, + "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X", + (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address, + ByteWidth, (UINT32)(RegionElement->Address), + RegionElement->Length)); + + return (AE_AML_REGION_LIMIT); + } + + /* + * Get BufferValue to point to the "address" in the buffer + */ + BufferValue = ((UINT8 *) RegionElement->Buffer + + ((UINT64) Address - (UINT64) RegionElement->Address)); + +DoFunction: + /* + * Perform a read or write to the buffer space + */ + switch (Function) + { + case ACPI_READ: + /* + * Set the pointer Value to whatever is in the buffer + */ + ACPI_MEMCPY (Value, BufferValue, ByteWidth); + break; + + case ACPI_WRITE: + /* + * Write the contents of Value to the buffer + */ + ACPI_MEMCPY (BufferValue, Value, ByteWidth); + break; + + default: + return (AE_BAD_PARAMETER); + } + + if (AcpiGbl_DisplayRegionAccess) + { + switch (SpaceId) + { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + + AcpiOsPrintf ("AcpiExec: SystemMemory " + "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n", + (Function & ACPI_IO_MASK) ? "Write" : "Read ", + (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length); + break; + + case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */ + + /* This space is required to always be ByteAcc */ + + Status = AcpiBufferToResource (MyContext->Connection, + MyContext->Length, &Resource); + + AcpiOsPrintf ("AcpiExec: GeneralPurposeIo " + "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n", + (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value, + (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth, + MyContext->AccessLength, MyContext->Connection); + break; + + default: + break; + } + } + + return (AE_OK); +} + + diff --git a/source/tools/acpiexec/aemain.c b/source/tools/acpiexec/aemain.c new file mode 100644 index 000000000000..a5d519c1e178 --- /dev/null +++ b/source/tools/acpiexec/aemain.c @@ -0,0 +1,700 @@ +/****************************************************************************** + * + * Module Name: aemain - Main routine for the AcpiExec utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aecommon.h" + +#ifdef _DEBUG +#include +#endif + +#define _COMPONENT PARSER + ACPI_MODULE_NAME ("aemain") + + +UINT8 AcpiGbl_RegionFillValue = 0; +BOOLEAN AcpiGbl_IgnoreErrors = FALSE; +BOOLEAN AcpiGbl_DbOpt_NoRegionSupport = FALSE; +BOOLEAN AcpiGbl_DebugTimeout = FALSE; +UINT8 AcpiGbl_UseHwReducedFadt = FALSE; + +static UINT8 AcpiGbl_BatchMode = 0; +static char BatchBuffer[128]; +static AE_TABLE_DESC *AeTableListHead = NULL; + +#define ASL_MAX_FILES 256 +static char *FileList[ASL_MAX_FILES]; + + +#define AE_SUPPORTED_OPTIONS "?b:d:e:f:gm^orv:x:" + + +/****************************************************************************** + * + * FUNCTION: usage + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print a usage message + * + *****************************************************************************/ + +static void +usage (void) +{ + + ACPI_USAGE_HEADER ("acpiexec [options] AMLfile1 AMLfile2 ..."); + + ACPI_OPTION ("-?", "Display this message"); + ACPI_OPTION ("-b ", "Batch mode command execution"); + ACPI_OPTION ("-m [Method]", "Batch mode method execution. Default=MAIN"); + printf ("\n"); + + ACPI_OPTION ("-da", "Disable method abort on error"); + ACPI_OPTION ("-di", "Disable execution of STA/INI methods during init"); + ACPI_OPTION ("-do", "Disable Operation Region address simulation"); + ACPI_OPTION ("-dr", "Disable repair of method return values"); + ACPI_OPTION ("-dt", "Disable allocation tracking (performance)"); + printf ("\n"); + + ACPI_OPTION ("-ef", "Enable display of final memory statistics"); + ACPI_OPTION ("-em", "Enable Interpreter Serialized Mode"); + ACPI_OPTION ("-es", "Enable Interpreter Slack Mode"); + ACPI_OPTION ("-et", "Enable debug semaphore timeout"); + printf ("\n"); + + ACPI_OPTION ("-f ", "Operation Region initialization fill value"); + ACPI_OPTION ("-r", "Use hardware-reduced FADT V5"); + ACPI_OPTION ("-vi", "Verbose initialization output"); + ACPI_OPTION ("-vr", "Verbose region handler output"); + ACPI_OPTION ("-x ", "Debug output level"); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiDbRunBatchMode + * + * PARAMETERS: BatchCommandLine - A semicolon separated list of commands + * to be executed. + * Use only commas to separate elements of + * particular command. + * RETURN: Status + * + * DESCRIPTION: For each command of list separated by ';' prepare the command + * buffer and pass it to AcpiDbCommandDispatch. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiDbRunBatchMode ( + void) +{ + ACPI_STATUS Status; + char *Ptr = BatchBuffer; + char *Cmd = Ptr; + UINT8 Run = 0; + + + AcpiGbl_MethodExecuting = FALSE; + AcpiGbl_StepToNextCall = FALSE; + + while (*Ptr) + { + if (*Ptr == ',') + { + /* Convert commas to spaces */ + *Ptr = ' '; + } + else if (*Ptr == ';') + { + *Ptr = '\0'; + Run = 1; + } + + Ptr++; + + if (Run || (*Ptr == '\0')) + { + (void) AcpiDbCommandDispatch (Cmd, NULL, NULL); + Run = 0; + Cmd = Ptr; + } + } + + Status = AcpiTerminate (); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: FlStrdup + * + * DESCRIPTION: Local strdup function + * + ******************************************************************************/ + +static char * +FlStrdup ( + char *String) +{ + char *NewString; + + + NewString = AcpiOsAllocate (strlen (String) + 1); + if (!NewString) + { + return (NULL); + } + + strcpy (NewString, String); + return (NewString); +} + + +/******************************************************************************* + * + * FUNCTION: FlSplitInputPathname + * + * PARAMETERS: InputFilename - The user-specified ASL source file to be + * compiled + * OutDirectoryPath - Where the directory path prefix is + * returned + * OutFilename - Where the filename part is returned + * + * RETURN: Status + * + * DESCRIPTION: Split the input path into a directory and filename part + * 1) Directory part used to open include files + * 2) Filename part used to generate output filenames + * + ******************************************************************************/ + +ACPI_STATUS +FlSplitInputPathname ( + char *InputPath, + char **OutDirectoryPath, + char **OutFilename) +{ + char *Substring; + char *DirectoryPath; + char *Filename; + + + *OutDirectoryPath = NULL; + *OutFilename = NULL; + + if (!InputPath) + { + return (AE_OK); + } + + /* Get the path to the input filename's directory */ + + DirectoryPath = FlStrdup (InputPath); + if (!DirectoryPath) + { + return (AE_NO_MEMORY); + } + + Substring = strrchr (DirectoryPath, '\\'); + if (!Substring) + { + Substring = strrchr (DirectoryPath, '/'); + if (!Substring) + { + Substring = strrchr (DirectoryPath, ':'); + } + } + + if (!Substring) + { + DirectoryPath[0] = 0; + Filename = FlStrdup (InputPath); + } + else + { + Filename = FlStrdup (Substring + 1); + *(Substring+1) = 0; + } + + if (!Filename) + { + return (AE_NO_MEMORY); + } + + *OutDirectoryPath = DirectoryPath; + *OutFilename = Filename; + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AsDoWildcard + * + * PARAMETERS: DirectoryPathname - Path to parent directory + * FileSpecifier - the wildcard specification (*.c, etc.) + * + * RETURN: Pointer to a list of filenames + * + * DESCRIPTION: Process files via wildcards. This function is for the Windows + * case only. + * + ******************************************************************************/ + +static char ** +AsDoWildcard ( + char *DirectoryPathname, + char *FileSpecifier) +{ +#ifdef WIN32 + void *DirInfo; + char *Filename; + int FileCount; + + + FileCount = 0; + + /* Open parent directory */ + + DirInfo = AcpiOsOpenDirectory (DirectoryPathname, FileSpecifier, REQUEST_FILE_ONLY); + if (!DirInfo) + { + /* Either the directory or file does not exist */ + + printf ("File or directory %s%s does not exist\n", DirectoryPathname, FileSpecifier); + return (NULL); + } + + /* Process each file that matches the wildcard specification */ + + while ((Filename = AcpiOsGetNextFilename (DirInfo))) + { + /* Add the filename to the file list */ + + FileList[FileCount] = AcpiOsAllocate (strlen (Filename) + 1); + strcpy (FileList[FileCount], Filename); + FileCount++; + + if (FileCount >= ASL_MAX_FILES) + { + printf ("Max files reached\n"); + FileList[0] = NULL; + return (FileList); + } + } + + /* Cleanup */ + + AcpiOsCloseDirectory (DirInfo); + FileList[FileCount] = NULL; + return (FileList); + +#else + if (!FileSpecifier) + { + return (NULL); + } + + /* + * Linux/Unix cases - Wildcards are expanded by the shell automatically. + * Just return the filename in a null terminated list + */ + FileList[0] = AcpiOsAllocate (strlen (FileSpecifier) + 1); + strcpy (FileList[0], FileSpecifier); + FileList[1] = NULL; + + return (FileList); +#endif +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * PARAMETERS: argc, argv + * + * RETURN: Status + * + * DESCRIPTION: Main routine for AcpiDump utility + * + *****************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char **argv) +{ + int j; + ACPI_STATUS Status; + UINT32 InitFlags; + ACPI_TABLE_HEADER *Table = NULL; + UINT32 TableCount; + AE_TABLE_DESC *TableDesc; + char **WildcardList; + char *Filename; + char *Directory; + char *FullPathname; + + +#ifdef _DEBUG + _CrtSetDbgFlag (_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | + _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); +#endif + + printf (ACPI_COMMON_SIGNON ("AML Execution/Debug Utility")); + + if (argc < 2) + { + usage (); + return (0); + } + + signal (SIGINT, AeCtrlCHandler); + + /* Init globals */ + + AcpiDbgLevel = ACPI_NORMAL_DEFAULT; + AcpiDbgLayer = 0xFFFFFFFF; + + /* Init ACPI and start debugger thread */ + + Status = AcpiInitializeSubsystem (); + AE_CHECK_OK (AcpiInitializeSubsystem, Status); + + /* Get the command line options */ + + while ((j = AcpiGetopt (argc, argv, AE_SUPPORTED_OPTIONS)) != EOF) switch(j) + { + case 'b': + if (strlen (AcpiGbl_Optarg) > 127) + { + printf ("**** The length of command line (%u) exceeded maximum (127)\n", + (UINT32) strlen (AcpiGbl_Optarg)); + return (-1); + } + AcpiGbl_BatchMode = 1; + strcpy (BatchBuffer, AcpiGbl_Optarg); + break; + + case 'd': + switch (AcpiGbl_Optarg[0]) + { + case 'a': + AcpiGbl_IgnoreErrors = TRUE; + break; + + case 'i': + AcpiGbl_DbOpt_ini_methods = FALSE; + break; + + case 'o': + AcpiGbl_DbOpt_NoRegionSupport = TRUE; + break; + + case 'r': + AcpiGbl_DisableAutoRepair = TRUE; + break; + + case 't': + #ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiGbl_DisableMemTracking = TRUE; + #endif + break; + + default: + printf ("Unknown option: -d%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + case 'e': + switch (AcpiGbl_Optarg[0]) + { + case 'f': + #ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiGbl_DisplayFinalMemStats = TRUE; + #endif + break; + + case 'm': + AcpiGbl_AllMethodsSerialized = TRUE; + printf ("Enabling AML Interpreter serialized mode\n"); + break; + + case 's': + AcpiGbl_EnableInterpreterSlack = TRUE; + printf ("Enabling AML Interpreter slack mode\n"); + break; + + case 't': + AcpiGbl_DebugTimeout = TRUE; + break; + + default: + printf ("Unknown option: -e%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + case 'f': + AcpiGbl_RegionFillValue = (UINT8) strtoul (AcpiGbl_Optarg, NULL, 0); + break; + + case 'g': + AcpiGbl_DbOpt_tables = TRUE; + AcpiGbl_DbFilename = NULL; + break; + + case 'm': + AcpiGbl_BatchMode = 2; + switch (AcpiGbl_Optarg[0]) + { + case '^': + strcpy (BatchBuffer, "MAIN"); + break; + + default: + strcpy (BatchBuffer, AcpiGbl_Optarg); + break; + } + break; + + case 'o': + AcpiGbl_DbOpt_disasm = TRUE; + AcpiGbl_DbOpt_stats = TRUE; + break; + + case 'r': + AcpiGbl_UseHwReducedFadt = TRUE; + printf ("Using ACPI 5.0 Hardware Reduced Mode via version 5 FADT\n"); + break; + + case 'v': + switch (AcpiGbl_Optarg[0]) + { + case 'i': + AcpiDbgLevel |= ACPI_LV_INIT_NAMES; + break; + + case 'r': + AcpiGbl_DisplayRegionAccess = TRUE; + break; + + default: + printf ("Unknown option: -v%s\n", AcpiGbl_Optarg); + return (-1); + } + break; + + case 'x': + AcpiDbgLevel = strtoul (AcpiGbl_Optarg, NULL, 0); + AcpiGbl_DbConsoleDebugLevel = AcpiDbgLevel; + printf ("Debug Level: 0x%8.8X\n", AcpiDbgLevel); + break; + + case '?': + case 'h': + default: + usage(); + return (-1); + } + + + InitFlags = (ACPI_NO_HANDLER_INIT | ACPI_NO_ACPI_ENABLE); + if (!AcpiGbl_DbOpt_ini_methods) + { + InitFlags |= (ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT); + } + + /* The remaining arguments are filenames for ACPI tables */ + + if (argv[AcpiGbl_Optind]) + { + AcpiGbl_DbOpt_tables = TRUE; + TableCount = 0; + + /* Get each of the ACPI table files on the command line */ + + while (argv[AcpiGbl_Optind]) + { + /* Split incoming path into a directory/filename combo */ + + Status = FlSplitInputPathname (argv[AcpiGbl_Optind], &Directory, &Filename); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Expand wildcards (Windows only) */ + + WildcardList = AsDoWildcard (Directory, Filename); + if (!WildcardList) + { + return (-1); + } + + while (*WildcardList) + { + FullPathname = AcpiOsAllocate ( + strlen (Directory) + strlen (*WildcardList) + 1); + + /* Construct a full path to the file */ + + strcpy (FullPathname, Directory); + strcat (FullPathname, *WildcardList); + + /* Get one table */ + + Status = AcpiDbReadTableFromFile (FullPathname, &Table); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not get input table %s, %s\n", FullPathname, + AcpiFormatException (Status)); + goto enterloop; + } + + AcpiOsFree (FullPathname); + AcpiOsFree (*WildcardList); + *WildcardList = NULL; + WildcardList++; + + /* Ignore non-AML tables, we can't use them. Except for an FADT */ + + if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FADT) && + !AcpiUtIsAmlTable (Table)) + { + ACPI_WARNING ((AE_INFO,"Table %4.4s is not an AML table, ignoring", + Table->Signature)); + AcpiOsFree (Table); + continue; + } + + /* Allocate and link a table descriptor */ + + TableDesc = AcpiOsAllocate (sizeof (AE_TABLE_DESC)); + TableDesc->Table = Table; + TableDesc->Next = AeTableListHead; + AeTableListHead = TableDesc; + + TableCount++; + } + + AcpiGbl_Optind++; + } + + /* Build a local RSDT with all tables and let ACPICA process the RSDT */ + + Status = AeBuildLocalTables (TableCount, AeTableListHead); + if (ACPI_FAILURE (Status)) + { + return (-1); + } + + Status = AeInstallTables (); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not load ACPI tables, %s\n", AcpiFormatException (Status)); + goto enterloop; + } + + /* + * Install most of the handlers. + * Override some default region handlers, especially SystemMemory + */ + Status = AeInstallEarlyHandlers (); + if (ACPI_FAILURE (Status)) + { + goto enterloop; + } + + /* + * TBD: Need a way to call this after the "LOAD" command + */ + Status = AcpiEnableSubsystem (InitFlags); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not EnableSubsystem, %s\n", AcpiFormatException (Status)); + goto enterloop; + } + + Status = AcpiInitializeObjects (InitFlags); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not InitializeObjects, %s\n", AcpiFormatException (Status)); + goto enterloop; + } + + /* + * Install handlers for "device driver" space IDs (EC,SMBus, etc.) + * and fixed event handlers + */ + AeInstallLateHandlers (); + AeMiscellaneousTests (); + } + +enterloop: + + if (AcpiGbl_BatchMode == 1) + { + AcpiDbRunBatchMode (); + } + else if (AcpiGbl_BatchMode == 2) + { + AcpiDbExecute (BatchBuffer, NULL, NULL, EX_NO_SINGLE_STEP); + } + else + { + /* Enter the debugger command loop */ + + AcpiDbUserCommands (ACPI_DEBUGGER_COMMAND_PROMPT, NULL); + } + + return (0); +} + diff --git a/source/tools/acpiexec/aetables.c b/source/tools/acpiexec/aetables.c new file mode 100644 index 000000000000..afada0d71417 --- /dev/null +++ b/source/tools/acpiexec/aetables.c @@ -0,0 +1,464 @@ +/****************************************************************************** + * + * Module Name: aetables - ACPI table setup/install for acpiexec utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aecommon.h" +#include "aetables.h" + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("aetables") + +/* Local prototypes */ + +void +AeTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + +/* User table (DSDT) */ + +static ACPI_TABLE_HEADER *DsdtToInstallOverride; + +/* Non-AML tables that are constructed locally and installed */ + +static ACPI_TABLE_RSDP LocalRSDP; +static ACPI_TABLE_FACS LocalFACS; +static ACPI_TABLE_HEADER LocalTEST; +static ACPI_TABLE_HEADER LocalBADTABLE; + +/* + * We need a local FADT so that the hardware subcomponent will function, + * even though the underlying OSD HW access functions don't do anything. + */ +static ACPI_TABLE_FADT LocalFADT; + +/* + * Use XSDT so that both 32- and 64-bit versions of this utility will + * function automatically. + */ +static ACPI_TABLE_XSDT *LocalXSDT; + +#define BASE_XSDT_TABLES 8 +#define BASE_XSDT_SIZE (sizeof (ACPI_TABLE_XSDT) + \ + ((BASE_XSDT_TABLES -1) * sizeof (UINT64))) + +#define ACPI_MAX_INIT_TABLES (32) +static ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES]; + + +/****************************************************************************** + * + * FUNCTION: AeTableOverride + * + * DESCRIPTION: Local implementation of AcpiOsTableOverride. + * Exercise the override mechanism + * + *****************************************************************************/ + +void +AeTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable) +{ + + /* This code exercises the table override mechanism in the core */ + + if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT)) + { + *NewTable = DsdtToInstallOverride; + } + + /* This code tests override of dynamically loaded tables */ + + else if (ACPI_COMPARE_NAME (ExistingTable->Signature, "OEM9")) + { + *NewTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Ssdt3Code); + } +} + + +/****************************************************************************** + * + * FUNCTION: AeBuildLocalTables + * + * PARAMETERS: TableCount - Number of tables on the command line + * TableList - List of actual tables from files + * + * RETURN: Status + * + * DESCRIPTION: Build a complete ACPI table chain, with a local RSDP, XSDT, + * FADT, and several other test tables. + * + *****************************************************************************/ + +ACPI_STATUS +AeBuildLocalTables ( + UINT32 TableCount, + AE_TABLE_DESC *TableList) +{ + ACPI_PHYSICAL_ADDRESS DsdtAddress = 0; + UINT32 XsdtSize; + AE_TABLE_DESC *NextTable; + UINT32 NextIndex; + ACPI_TABLE_FADT *ExternalFadt = NULL; + + + /* + * Update the table count. For DSDT, it is not put into the XSDT. For + * FADT, this is already accounted for since we usually install a + * local FADT. + */ + NextTable = TableList; + while (NextTable) + { + if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) + { + TableCount--; + } + NextTable = NextTable->Next; + } + + XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64)); + + /* Build an XSDT */ + + LocalXSDT = AcpiOsAllocate (XsdtSize); + if (!LocalXSDT) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET (LocalXSDT, 0, XsdtSize); + ACPI_STRNCPY (LocalXSDT->Header.Signature, ACPI_SIG_XSDT, 4); + LocalXSDT->Header.Length = XsdtSize; + LocalXSDT->Header.Revision = 1; + + LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalTEST); + LocalXSDT->TableOffsetEntry[1] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE); + LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (&LocalFADT); + + /* Install two SSDTs to test multiple table support */ + + LocalXSDT->TableOffsetEntry[3] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code); + LocalXSDT->TableOffsetEntry[4] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code); + + /* Install the OEM1 table to test LoadTable */ + + LocalXSDT->TableOffsetEntry[5] = ACPI_PTR_TO_PHYSADDR (&Oem1Code); + + /* Install the OEMx table to test LoadTable */ + + LocalXSDT->TableOffsetEntry[6] = ACPI_PTR_TO_PHYSADDR (&OemxCode); + + /* Install the ECDT table to test _REG */ + + LocalXSDT->TableOffsetEntry[7] = ACPI_PTR_TO_PHYSADDR (&EcdtCode); + + /* + * Install the user tables. The DSDT must be installed in the FADT. + * All other tables are installed directly into the XSDT. + */ + NextIndex = BASE_XSDT_TABLES; + NextTable = TableList; + while (NextTable) + { + /* + * Incoming DSDT or FADT are special cases. All other tables are + * just immediately installed into the XSDT. + */ + if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT)) + { + if (DsdtAddress) + { + printf ("Already found a DSDT, only one allowed\n"); + return (AE_ALREADY_EXISTS); + } + + /* The incoming user table is a DSDT */ + + DsdtAddress = ACPI_PTR_TO_PHYSADDR (&DsdtCode); + DsdtToInstallOverride = NextTable->Table; + } + else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) + { + ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table); + LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); + } + else + { + /* Install the table in the XSDT */ + + LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); + NextIndex++; + } + + NextTable = NextTable->Next; + } + + /* Build an RSDP */ + + ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP)); + ACPI_MEMCPY (LocalRSDP.Signature, ACPI_SIG_RSDP, 8); + ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6); + LocalRSDP.Revision = 2; + LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT); + LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT); + + /* Set checksums for both XSDT and RSDP */ + + LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) LocalXSDT, LocalXSDT->Header.Length); + LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH); + + if (!DsdtAddress) + { + /* Use the local DSDT because incoming table(s) are all SSDT(s) */ + + DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode); + DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode); + } + + if (ExternalFadt) + { + /* + * Use the external FADT, but we must update the DSDT/FACS addresses + * as well as the checksum + */ + ExternalFadt->Dsdt = DsdtAddress; + if (!AcpiGbl_ReducedHardware) + { + ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + } + + if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt)) + { + ExternalFadt->XDsdt = DsdtAddress; + + if (!AcpiGbl_ReducedHardware) + { + ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + } + } + + /* Complete the FADT with the checksum */ + + ExternalFadt->Header.Checksum = 0; + ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) ExternalFadt, ExternalFadt->Header.Length); + } + else if (AcpiGbl_UseHwReducedFadt) + { + ACPI_MEMCPY (&LocalFADT, HwReducedFadtCode, sizeof (ACPI_TABLE_FADT)); + LocalFADT.Dsdt = DsdtAddress; + LocalFADT.XDsdt = DsdtAddress; + + LocalFADT.Header.Checksum = 0; + LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalFADT, LocalFADT.Header.Length); + } + else + { + /* + * Build a local FADT so we can test the hardware/event init + */ + ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT)); + ACPI_STRNCPY (LocalFADT.Header.Signature, ACPI_SIG_FADT, 4); + + /* Setup FADT header and DSDT/FACS addresses */ + + LocalFADT.Dsdt = 0; + LocalFADT.Facs = 0; + + LocalFADT.XDsdt = DsdtAddress; + LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + + LocalFADT.Header.Revision = 3; + LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT); + + /* Miscellaneous FADT fields */ + + LocalFADT.Gpe0BlockLength = 16; + LocalFADT.Gpe0Block = 0x00001234; + + LocalFADT.Gpe1BlockLength = 6; + LocalFADT.Gpe1Block = 0x00005678; + LocalFADT.Gpe1Base = 96; + + LocalFADT.Pm1EventLength = 4; + LocalFADT.Pm1aEventBlock = 0x00001aaa; + LocalFADT.Pm1bEventBlock = 0x00001bbb; + + LocalFADT.Pm1ControlLength = 2; + LocalFADT.Pm1aControlBlock = 0xB0; + + LocalFADT.PmTimerLength = 4; + LocalFADT.PmTimerBlock = 0xA0; + + LocalFADT.Pm2ControlBlock = 0xC0; + LocalFADT.Pm2ControlLength = 1; + + /* Setup one example X-64 field */ + + LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO; + LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock; + LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength); + + /* Complete the FADT with the checksum */ + + LocalFADT.Header.Checksum = 0; + LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalFADT, LocalFADT.Header.Length); + } + + /* Build a FACS */ + + ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS)); + ACPI_STRNCPY (LocalFACS.Signature, ACPI_SIG_FACS, 4); + + LocalFACS.Length = sizeof (ACPI_TABLE_FACS); + LocalFACS.GlobalLock = 0x11AA0011; + + /* + * Build a fake table [TEST] so that we make sure that the + * ACPICA core ignores it + */ + ACPI_MEMSET (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER)); + ACPI_STRNCPY (LocalTEST.Signature, "TEST", 4); + + LocalTEST.Revision = 1; + LocalTEST.Length = sizeof (ACPI_TABLE_HEADER); + LocalTEST.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalTEST, LocalTEST.Length); + + /* + * Build a fake table with a bad signature [BAD!] so that we make + * sure that the ACPICA core ignores it + */ + ACPI_MEMSET (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER)); + ACPI_STRNCPY (LocalBADTABLE.Signature, "BAD!", 4); + + LocalBADTABLE.Revision = 1; + LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER); + LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalBADTABLE, LocalBADTABLE.Length); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeInstallTables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install the various ACPI tables + * + *****************************************************************************/ + +ACPI_STATUS +AeInstallTables ( + void) +{ + ACPI_STATUS Status; + + + Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE); + AE_CHECK_OK (AcpiInitializeTables, Status); + + Status = AcpiReallocateRootTable (); + AE_CHECK_OK (AcpiReallocateRootTable, Status); + + Status = AcpiLoadTables (); + AE_CHECK_OK (AcpiLoadTables, Status); + + /* + * Test run-time control method installation. Do it twice to test code + * for an existing name. + */ + Status = AcpiInstallMethod (MethodCode); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("%s, Could not install method\n", + AcpiFormatException (Status)); + } + + Status = AcpiInstallMethod (MethodCode); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("%s, Could not install method\n", + AcpiFormatException (Status)); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeLocalGetRootPointer + * + * PARAMETERS: Flags - not used + * Address - Where the root pointer is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a local RSDP, used to dynamically load tables via the + * standard ACPI mechanism. + * + *****************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void) +{ + + return ((ACPI_PHYSICAL_ADDRESS) &LocalRSDP); +} diff --git a/source/tools/acpiexec/aetables.h b/source/tools/acpiexec/aetables.h new file mode 100644 index 000000000000..16b3e896d699 --- /dev/null +++ b/source/tools/acpiexec/aetables.h @@ -0,0 +1,371 @@ +/****************************************************************************** + * + * Module Name: aetables.h - Precompiled AML ACPI tables for acpiexec + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __AETABLES_H__ +#define __AETABLES_H__ + + +/* + * Miscellaneous pre-compiled AML ACPI tables to be installed + */ + +/* Default DSDT. This will be replaced with the input DSDT */ + +static unsigned char DsdtCode[] = +{ + 0x44,0x53,0x44,0x54,0x24,0x00,0x00,0x00, /* 00000000 "DSDT$..." */ + 0x02,0x6F,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 ".oIntel." */ + 0x4E,0x75,0x6C,0x6C,0x44,0x53,0x44,0x54, /* 00000010 "NullDSDT" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x04,0x12,0x08,0x20, +}; + +static unsigned char LocalDsdtCode[] = +{ + 0x44,0x53,0x44,0x54,0x24,0x00,0x00,0x00, /* 00000000 "DSDT$..." */ + 0x02,0x2C,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 ".,Intel." */ + 0x4C,0x6F,0x63,0x61,0x6C,0x00,0x00,0x00, /* 00000010 "Local..." */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x30,0x07,0x09,0x20, +}; + +/* Several example SSDTs */ + +static unsigned char Ssdt1Code[] = /* Has method _T98 */ +{ + 0x53,0x53,0x44,0x54,0x30,0x00,0x00,0x00, /* 00000000 "SSDT0..." */ + 0x01,0xB8,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ + 0x4D,0x61,0x6E,0x79,0x00,0x00,0x00,0x00, /* 00000010 "Many...." */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x24,0x04,0x03,0x20,0x14,0x0B,0x5F,0x54, /* 00000020 "$.. .._T" */ + 0x39,0x38,0x00,0x70,0x0A,0x04,0x60,0xA4, /* 00000028 "98.p..`." */ +}; + +static unsigned char Ssdt2Code[] = /* Has method _T99 */ +{ + 0x53,0x53,0x44,0x54,0x30,0x00,0x00,0x00, /* 00000000 "SSDT0..." */ + 0x01,0xB7,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ + 0x4D,0x61,0x6E,0x79,0x00,0x00,0x00,0x00, /* 00000010 "Many...." */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x24,0x04,0x03,0x20,0x14,0x0B,0x5F,0x54, /* 00000020 "$.. .._T" */ + 0x39,0x39,0x00,0x70,0x0A,0x04,0x60,0xA4, /* 00000028 "99.p..`." */ +}; + +unsigned char Ssdt3Code[] = /* OEM9: Has method _T97 */ +{ + 0x4F,0x45,0x4D,0x39,0x30,0x00,0x00,0x00, /* 00000000 "OEM10..." */ + 0x01,0xDD,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ + 0x4D,0x61,0x6E,0x79,0x00,0x00,0x00,0x00, /* 00000010 "Many...." */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x24,0x04,0x03,0x20,0x14,0x0B,0x5F,0x54, /* 00000020 "$.. .._T" */ + 0x39,0x37,0x00,0x70,0x0A,0x04,0x60,0xA4, /* 00000028 "97.p..`." */ +}; + +/* "Hardware-Reduced" ACPI 5.0 FADT (No FACS, no ACPI hardware) */ + +unsigned char HwReducedFadtCode[] = +{ + 0x46,0x41,0x43,0x50,0x0C,0x01,0x00,0x00, /* 00000000 "FACP...." */ + 0x05,0x8C,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x41,0x43,0x50,0x49,0x35,0x30,0x20,0x20, /* 00000010 "ACPI50 " */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x13,0x04,0x11,0x20,0x00,0x00,0x00,0x00, /* 00000020 "... ...." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068 "........" */ + 0x00,0x00,0x78,0x00,0x01,0x08,0x00,0x01, /* 00000070 "..x....." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000080 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000088 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x02, /* 00000090 "..... .." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000098 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x10,0x00,0x02, /* 000000A8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00, /* 000000C0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */ + 0x01,0x20,0x00,0x03,0x00,0x00,0x00,0x00, /* 000000D0 ". ......" */ + 0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x01, /* 000000D8 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x01, /* 000000F0 "........" */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F8 "........" */ + 0x01,0x08,0x00,0x01,0x01,0x00,0x00,0x00, /* 00000100 "........" */ + 0x00,0x00,0x00,0x00 /* 00000108 "........" */ +}; + +/* Example OEM table */ + +static unsigned char Oem1Code[] = +{ + 0x4F,0x45,0x4D,0x31,0x38,0x00,0x00,0x00, /* 00000000 "OEM18..." */ + 0x01,0x4B,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 ".KIntel." */ + 0x4D,0x61,0x6E,0x79,0x00,0x00,0x00,0x00, /* 00000010 "Many...." */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x18,0x09,0x03,0x20,0x08,0x5F,0x58,0x54, /* 00000020 "... ._XT" */ + 0x32,0x0A,0x04,0x14,0x0C,0x5F,0x58,0x54, /* 00000028 "2...._XT" */ + 0x31,0x00,0x70,0x01,0x5F,0x58,0x54,0x32, /* 00000030 "1.p._XT2" */ +}; + +/* ASL source for this table is at the end of this file */ + +static unsigned char OemxCode[] = +{ + 0x4F,0x45,0x4D,0x58,0xB0,0x00,0x00,0x00, /* 00000000 "OEMX...." */ + 0x02,0x54,0x4D,0x79,0x4F,0x45,0x4D,0x00, /* 00000008 ".TMyOEM." */ + 0x54,0x65,0x73,0x74,0x00,0x00,0x00,0x00, /* 00000010 "Test...." */ + 0x32,0x04,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "2...INTL" */ + 0x31,0x03,0x10,0x20,0x14,0x1D,0x5F,0x49, /* 00000020 "1.. .._I" */ + 0x4E,0x49,0x00,0x70,0x0D,0x54,0x61,0x62, /* 00000028 "NI.p.Tab" */ + 0x6C,0x65,0x20,0x4F,0x45,0x4D,0x58,0x20, /* 00000030 "le OEMX " */ + 0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x00, /* 00000038 "running." */ + 0x5B,0x31,0x10,0x22,0x5C,0x5F,0x47,0x50, /* 00000040 "[1."\_GP" */ + 0x45,0x14,0x06,0x5F,0x45,0x30,0x37,0x00, /* 00000048 "E.._E07." */ + 0x14,0x06,0x5F,0x45,0x32,0x32,0x00,0x14, /* 00000050 ".._E22.." */ + 0x06,0x5F,0x4C,0x33,0x31,0x00,0x14,0x06, /* 00000058 "._L31..." */ + 0x5F,0x4C,0x36,0x36,0x00,0x5B,0x82,0x10, /* 00000060 "_L66.[.." */ + 0x4F,0x45,0x4D,0x31,0x08,0x5F,0x50,0x52, /* 00000068 "OEM1._PR" */ + 0x57,0x12,0x05,0x02,0x0A,0x07,0x00,0x5B, /* 00000070 "W......[" */ + 0x82,0x10,0x4F,0x45,0x4D,0x32,0x08,0x5F, /* 00000078 "..OEM2._" */ + 0x50,0x52,0x57,0x12,0x05,0x02,0x0A,0x66, /* 00000080 "PRW....f" */ + 0x00,0x10,0x26,0x5C,0x47,0x50,0x45,0x32, /* 00000088 "..&\GPE2" */ + 0x14,0x06,0x5F,0x4C,0x30,0x31,0x00,0x14, /* 00000090 ".._L01.." */ + 0x06,0x5F,0x45,0x30,0x37,0x00,0x08,0x5F, /* 00000098 "._E07.._" */ + 0x50,0x52,0x57,0x12,0x0C,0x02,0x12,0x08, /* 000000A0 "PRW....." */ + 0x02,0x5C,0x47,0x50,0x45,0x32,0x01,0x00 /* 000000A8 ".\GPE2.." */ +}; + +/* Example ECDT */ + +unsigned char EcdtCode[] = +{ + 0x45,0x43,0x44,0x54,0x4E,0x00,0x00,0x00, /* 00000000 "ECDTN..." */ + 0x01,0x94,0x20,0x49,0x6E,0x74,0x65,0x6C, /* 00000008 ".. Intel" */ + 0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65, /* 00000010 "Template" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x16,0x03,0x11,0x20,0x01,0x08,0x00,0x00, /* 00000020 "... ...." */ + 0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "f......." */ + 0x01,0x08,0x00,0x00,0x62,0x00,0x00,0x00, /* 00000030 "....b..." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x09,0x5C,0x5F,0x53,0x42,0x2E,0x50,0x43, /* 00000040 ".\_SB.PC" */ + 0x49,0x30,0x2E,0x45,0x43,0x00 /* 00000048 "I0.EC." */ +}; + + +/* + * Example installable control method + * + * DefinitionBlock ("", "DSDT", 2, "Intel", "MTHDTEST", 0x20090512) + * { + * Method (\_SI_._T97, 1, Serialized) + * { + * Store ("Example installed method", Debug) + * Store (Arg0, Debug) + * Return () + * } + * } + * + * Compiled byte code below. + */ +static unsigned char MethodCode[] = +{ + 0x44,0x53,0x44,0x54,0x53,0x00,0x00,0x00, /* 00000000 "DSDTS..." */ + 0x02,0xF9,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ + 0x4D,0x54,0x48,0x44,0x54,0x45,0x53,0x54, /* 00000010 "MTHDTEST" */ + 0x12,0x05,0x09,0x20,0x49,0x4E,0x54,0x4C, /* 00000018 "... INTL" */ + 0x22,0x04,0x09,0x20,0x14,0x2E,0x2E,0x5F, /* 00000020 "".. ..._" */ + 0x54,0x49,0x5F,0x5F,0x54,0x39,0x37,0x09, /* 00000028 "SI__T97." */ + 0x70,0x0D,0x45,0x78,0x61,0x6D,0x70,0x6C, /* 00000030 "p.Exampl" */ + 0x65,0x20,0x69,0x6E,0x73,0x74,0x61,0x6C, /* 00000038 "e instal" */ + 0x6C,0x65,0x64,0x20,0x6D,0x65,0x74,0x68, /* 00000040 "led meth" */ + 0x6F,0x64,0x00,0x5B,0x31,0x70,0x68,0x5B, /* 00000048 "od.[1ph[" */ + 0x31,0xA4,0x00, +}; + + +#if 0 +/****************************************************************************** + * + * DESCRIPTION: ASL tables that are used in RSDT/XSDT, also used to test + * Load/LoadTable operators. + * + *****************************************************************************/ + +DefinitionBlock ("", "OEMX", 2, "MyOEM", "Test", 0x00000432) +{ + External (GPE2, DeviceObj) + + Method (_INI) + { + Store ("Table OEMX running", Debug) + } + + Scope (\_GPE) + { + Method (_E07) {} + Method (_E22) {} + Method (_L31) {} + Method (_L66) {} + } + + Device (OEM1) + { + Name (_PRW, Package(){7,0}) + } + Device (OEM2) + { + Name (_PRW, Package(){0x66,0}) + } + + Scope (\GPE2) + { + Method (_L01) {} + Method (_E07) {} + + Name (_PRW, Package() {Package() {\GPE2, 1}, 0}) + } +} + +/* Parent gr.asl file */ + +DefinitionBlock ("", "DSDT", 2, "Intel", "Many", 0x00000001) +{ + Name (BUF1, Buffer() + { + 0x4F,0x45,0x4D,0x58,0xB0,0x00,0x00,0x00, /* 00000000 "OEMX...." */ + 0x02,0x54,0x4D,0x79,0x4F,0x45,0x4D,0x00, /* 00000008 ".TMyOEM." */ + 0x54,0x65,0x73,0x74,0x00,0x00,0x00,0x00, /* 00000010 "Test...." */ + 0x32,0x04,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "2...INTL" */ + 0x31,0x03,0x10,0x20,0x14,0x1D,0x5F,0x49, /* 00000020 "1.. .._I" */ + 0x4E,0x49,0x00,0x70,0x0D,0x54,0x61,0x62, /* 00000028 "NI.p.Tab" */ + 0x6C,0x65,0x20,0x4F,0x45,0x4D,0x58,0x20, /* 00000030 "le OEMX " */ + 0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x00, /* 00000038 "running." */ + 0x5B,0x31,0x10,0x22,0x5C,0x5F,0x47,0x50, /* 00000040 "[1."\_GP" */ + 0x45,0x14,0x06,0x5F,0x45,0x30,0x37,0x00, /* 00000048 "E.._E07." */ + 0x14,0x06,0x5F,0x45,0x32,0x32,0x00,0x14, /* 00000050 ".._E22.." */ + 0x06,0x5F,0x4C,0x33,0x31,0x00,0x14,0x06, /* 00000058 "._L31..." */ + 0x5F,0x4C,0x36,0x36,0x00,0x5B,0x82,0x10, /* 00000060 "_L66.[.." */ + 0x4F,0x45,0x4D,0x31,0x08,0x5F,0x50,0x52, /* 00000068 "OEM1._PR" */ + 0x57,0x12,0x05,0x02,0x0A,0x07,0x00,0x5B, /* 00000070 "W......[" */ + 0x82,0x10,0x4F,0x45,0x4D,0x32,0x08,0x5F, /* 00000078 "..OEM2._" */ + 0x50,0x52,0x57,0x12,0x05,0x02,0x0A,0x66, /* 00000080 "PRW....f" */ + 0x00,0x10,0x26,0x5C,0x47,0x50,0x45,0x32, /* 00000088 "..&\GPE2" */ + 0x14,0x06,0x5F,0x4C,0x30,0x31,0x00,0x14, /* 00000090 ".._L01.." */ + 0x06,0x5F,0x45,0x30,0x37,0x00,0x08,0x5F, /* 00000098 "._E07.._" */ + 0x50,0x52,0x57,0x12,0x0C,0x02,0x12,0x08, /* 000000A0 "PRW....." */ + 0x02,0x5C,0x47,0x50,0x45,0x32,0x01,0x00 /* 000000A8 ".\GPE2.." */ + }) + + Name (HNDL, 0) + Method (LD) + { + Load (BUF1, HNDL) + Store ("Load operator, handle:", Debug) + Store (HNDL, Debug) + } + + Method (MAIN, 0, NotSerialized) + { + Store ("Loading OEMX table", Debug) + Store (LoadTable ("OEMX", "MyOEM", "Test"), Debug) + } + + Scope (\_GPE) + { + Method (_L08) {} + Method (_E08) {} + Method (_L0B) {} + } + + Device (DEV0) + { + Name (_PRW, Package() {0x11, 0}) + } + + Device (\GPE2) + { + Method (_L00) {} + } +} + +/* Example ECDT */ + +[000h 0000 4] Signature : "ECDT" /* Embedded Controller Boot Resources Table */ +[004h 0004 4] Table Length : 0000004E +[008h 0008 1] Revision : 01 +[009h 0009 1] Checksum : 14 +[00Ah 0010 6] Oem ID : " Intel" +[010h 0016 8] Oem Table ID : "Template" +[018h 0024 4] Oem Revision : 00000001 +[01Ch 0028 4] Asl Compiler ID : "INTL" +[020h 0032 4] Asl Compiler Revision : 20110316 + + +[024h 0036 12] Command/Status Register : +[024h 0036 1] Space ID : 01 (SystemIO) +[025h 0037 1] Bit Width : 08 +[026h 0038 1] Bit Offset : 00 +[027h 0039 1] Encoded Access Width : 00 (Undefined/Legacy) +[028h 0040 8] Address : 0000000000000066 + +[030h 0048 12] Data Register : +[030h 0048 1] Space ID : 01 (SystemIO) +[031h 0049 1] Bit Width : 08 +[032h 0050 1] Bit Offset : 00 +[033h 0051 1] Encoded Access Width : 00 (Undefined/Legacy) +[034h 0052 8] Address : 0000000000000062 + +[03Ch 0060 4] UID : 00000000 +[040h 0064 1] GPE Number : 09 +[041h 0065 13] Namepath : "\_SB.PCI0.EC" + +#endif + +#endif /* __AETABLES_H__ */ diff --git a/source/tools/acpihelp/Makefile b/source/tools/acpihelp/Makefile new file mode 100644 index 000000000000..481f9c2fa35f --- /dev/null +++ b/source/tools/acpihelp/Makefile @@ -0,0 +1,121 @@ +# +# acpihelp - ACPI Help utility. Displays ASL operator syntax and +# information about ACPI predefined names. +# +# NOTE: This makefile is intended to be used within the native +# ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpihelp + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPIHELP = $(ACPICA_TOOLS)/acpihelp +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ACPIHELP) \ + $(ACPICA_COMMON) + +HEADERS = \ + $(wildcard $(ACPIHELP)/*.h) + +OBJECTS = \ + ahamlops.o \ + ahaslkey.o \ + ahaslops.o \ + ahdecode.o \ + ahpredef.o \ + ahmain.o \ + getopt.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_HELP_APP \ + -I$(ACPICA_INCLUDE) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + $(COPYPROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpihelp/acpihelp.h b/source/tools/acpihelp/acpihelp.h new file mode 100644 index 000000000000..427353a06b51 --- /dev/null +++ b/source/tools/acpihelp/acpihelp.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * Module Name: acpihelp.h - Include file for AcpiHelp utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACPIHELP_H +#define __ACPIHELP_H + + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" + +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#endif +#include + + +#define AH_DECODE_DEFAULT 0 +#define AH_DECODE_ASL 1 +#define AH_DECODE_ASL_KEYWORD 2 +#define AH_DECODE_PREDEFINED_NAME 3 +#define AH_DECODE_AML 4 +#define AH_DECODE_AML_OPCODE 5 +#define AH_DISPLAY_DEVICE_IDS 6 + +#define AH_MAX_ASL_LINE_LENGTH 70 +#define AH_MAX_AML_LINE_LENGTH 100 + + +typedef struct ah_aml_opcode +{ + UINT16 OpcodeRangeStart; + UINT16 OpcodeRangeEnd; + char *OpcodeString; + char *OpcodeName; + char *Type; + char *FixedArguments; + char *VariableArguments; + char *Grammar; + +} AH_AML_OPCODE; + +typedef struct ah_asl_operator +{ + char *Name; + char *Syntax; + char *Description; + +} AH_ASL_OPERATOR; + +typedef struct ah_asl_keyword +{ + char *Name; + char *Description; + char *KeywordList; + +} AH_ASL_KEYWORD; + +typedef struct ah_predefined_name +{ + char *Name; + char *Description; + char *Action; + +} AH_PREDEFINED_NAME; + +typedef struct ah_device_id +{ + char *Name; + char *Description; + +} AH_DEVICE_ID; + + +extern const AH_AML_OPCODE AmlOpcodeInfo[]; +extern const AH_ASL_OPERATOR AslOperatorInfo[]; +extern const AH_ASL_KEYWORD AslKeywordInfo[]; +extern const AH_PREDEFINED_NAME AslPredefinedInfo[]; +extern BOOLEAN AhDisplayAll; + +void +AhStrupr ( + char *SrcString); + +void +AhFindAmlOpcode ( + char *Name); + +void +AhDecodeAmlOpcode ( + char *Name); + +void +AhFindPredefinedNames ( + char *Name); + +void +AhFindAslOperators ( + char *Name); + +void +AhFindAslKeywords ( + char *Name); + +void +AhDisplayDeviceIds ( + void); + +#endif /* __ACPIHELP_H */ diff --git a/source/tools/acpihelp/ahamlops.c b/source/tools/acpihelp/ahamlops.c new file mode 100644 index 000000000000..222eb3454df1 --- /dev/null +++ b/source/tools/acpihelp/ahamlops.c @@ -0,0 +1,325 @@ +/****************************************************************************** + * + * Module Name: ahamlops - Table of all known AML opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + +/* + * AML opcodes with related syntax and grammar information. + * This table was extracted from the ACPI specification. + */ +const AH_AML_OPCODE AmlOpcodeInfo[] = +{ + {0x00, 0x00, "0x00", "ZeroOp", "DataObject", NULL, NULL, + NULL}, + {0x01, 0x01, "0x01", "OneOp", "DataObject", NULL, NULL, + NULL}, + {0x02, 0x05, "0x02-0x05", NULL, NULL, NULL, NULL, + NULL}, + {0x06, 0x06, "0x06", "AliasOp", "TermObject", "NameString NameString", NULL, + "DefAlias := AliasOp NameString NameString"}, + {0x07, 0x07, "0x07", NULL, NULL, NULL, NULL, + NULL}, + {0x08, 0x08, "0x08", "NameOp", "TermObject", "NameString DataRefObject", NULL, + "DefName := NameOp NameString DataRefObject"}, + {0x09, 0x09, "0x09", NULL, NULL, NULL, NULL, + NULL}, + {0x0A, 0x0A, "0x0A", "BytePrefix", "DataObject", "ByteData", NULL, + "ByteConst := BytePrefix ByteData"}, + {0x0B, 0x0B, "0x0B", "WordPrefix", "DataObject", "WordData", NULL, + "WordConst := WordPrefix WordData"}, + {0x0C, 0x0C, "0x0C", "DWordPrefix", "DataObject", "DWordData", NULL, + "DWordConst := DWordPrefix DWordData"}, + {0x0D, 0x0D, "0x0D", "StringPrefix", "DataObject", "AsciiCharList NullChar", NULL, + "String := StringPrefix AsciiCharList NullChar"}, + {0x0E, 0x0E, "0x0E", "QWordPrefix", "DataObject", "QWordData", NULL, + "QWordConst := QWordPrefix QWordData"}, + {0x0F, 0x0F, "0x0F", NULL, NULL, NULL, NULL, + NULL}, + {0x10, 0x10, "0x10", "ScopeOp", "TermObject", "NameString", "TermList", + "DefScope := ScopeOp PkgLength NameString TermList"}, + {0x11, 0x11, "0x11", "BufferOp", "TermObject", "TermArg", "ByteList", + "DefBuffer := BufferOp PkgLength BufferSize ByteList"}, + {0x12, 0x12, "0x12", "PackageOp", "TermObject", "ByteData", "Package TermList", + "DefPackage := PackageOp PkgLength NumElements PackageElementList"}, + {0x13, 0x13, "0x13", "VarPackageOp", "TermObject", "TermArg", "Package TermList", + "DefVarPackage := VarPackageOp PkgLength VarNumElements PackageElementList"}, + {0x14, 0x14, "0x14", "MethodOp", "TermObject", "NameString ByteData", "TermList", + "DefMethod := MethodOp PkgLength NameString MethodFlags TermList"}, + {0x15, 0x2D, "0x15-0x2D", NULL, NULL, NULL, NULL, + NULL}, + {0x2E, 0x2E, "0x2E", "DualNamePrefix", "NameObject", "NameSeg NameSeg", NULL, + "DualNamePath := DualNamePrefix NameSeg NameSeg"}, + {0x2F, 0x2F, "0x2F", "MultiNamePrefix", "NameObject", "ByteData NameSeg", NULL, + "MultiNamePath := MultiNamePrefix SegCount NameSeg(SegCount)"}, + {0x30, 0x39, "0x30-0x39", "DigitChar", "NameObject", NULL, NULL, + NULL}, + {0x3A, 0x40, "0x3A-0x40", NULL, NULL, NULL, NULL, + NULL}, + {0x41, 0x5A, "0x41-0x5A", "NameChar", "NameObject", NULL, NULL, + NULL}, + {0x5B, 0x5B, "0x5B", "ExtOpPrefix", "DataObject", "ByteData", NULL, + NULL}, + {0x5B00, 0x5B00, "0x5B00", NULL, NULL, NULL, NULL, + NULL}, + {0x5B01, 0x5B01, "0x5B01", "MutexOp", "TermObject", "NameString ByteData", NULL, + "DefMutex := MutexOp NameString SyncFlags"}, + {0x5B02, 0x5B02, "0x5B02", "EventOp", "TermObject", "NameString", NULL, + "DefEvent := EventOp NameString"}, + {0x5B12, 0x5B12, "0x5B12", "CondRefOfOp", "TermObject", "SuperName SuperName", NULL, + "DefCondRefOf := CondRefOfOp SuperName Target"}, + {0x5B13, 0x5B13, "0x5B13", "CreateFieldOp", "TermObject", "TermArg TermArg TermArg NameString", NULL, + "DefCreateField := CreateFieldOp SourceBuff BitIndex NumBits NameString"}, + {0x5B1F, 0x5B1F, "0x5B1F", "LoadTableOp", "TermObject", "TermArg TermArg TermArg TermArg TermArg TermArg", NULL, + "DefLoadTable := LoadTableOp TermArg TermArg TermArg TermArg TermArg TermArg"}, + {0x5B20, 0x5B20, "0x5B20", "LoadOp", "TermObject", "NameString SuperName", NULL, + "DefLoad := LoadOp NameString DDBHandleObject"}, + {0x5B21, 0x5B21, "0x5B21", "StallOp", "TermObject", "TermArg", NULL, + "DefStall := StallOp UsecTime"}, + {0x5B22, 0x5B22, "0x5B22", "SleepOp", "TermObject", "TermArg", NULL, + "DefSleep := SleepOp MsecTime"}, + {0x5B23, 0x5B23, "0x5B23", "AcquireOp", "TermObject", "SuperName WordData", NULL, + "DefAcquire := AcquireOp MutexObject Timeout"}, + {0x5B24, 0x5B24, "0x5B24", "SignalOp", "TermObject", "SuperName", NULL, + "DefSignal := SignalOp EventObject"}, + {0x5B25, 0x5B25, "0x5B25", "WaitOp", "TermObject", "SuperName TermArg", NULL, + "DefWait := WaitOp EventObject Operand"}, + {0x5B26, 0x5B26, "0x5B26", "ResetOp", "TermObject", "SuperName", NULL, + "DefReset := ResetOp EventObject"}, + {0x5B27, 0x5B27, "0x5B27", "ReleaseOp", "TermObject", "SuperName", NULL, + "DefRelease := ReleaseOp MutexObject"}, + {0x5B28, 0x5B28, "0x5B28", "FromBCDOp", "TermObject", "TermArg Target", NULL, + "DefFromBCD := FromBCDOp BCDValue Target"}, + {0x5B29, 0x5B29, "0x5B29", "ToBCD", "TermObject", "TermArg Target", NULL, + "DefToBCD := ToBCDOp Operand Target"}, + {0x5B2A, 0x5B2A, "0x5B2A", "UnloadOp", "TermObject", "SuperName", NULL, + "DefUnload := UnloadOp DDBHandleObject"}, + {0x5B30, 0x5B30, "0x5B30", "RevisionOp", "DataObject", NULL, NULL, + NULL}, + {0x5B31, 0x5B31, "0x5B31", "DebugOp", "DebugObject", NULL, NULL, + NULL}, + {0x5B32, 0x5B32, "0x5B32", "FatalOp", "TermObject", "ByteData DWordData TermArg", NULL, + "DefFatal := FatalOp FatalType FatalCode FatalArg"}, + {0x5B33, 0x5B33, "0x5B33", "TimerOp", "TermObject", NULL, NULL, + "DefTimer := TimerOp"}, + {0x5B80, 0x5B80, "0x5B80", "OpRegionOp", "TermObject", "NameString ByteData TermArg TermArg", NULL, + "DefOpRegion := OpRegionOp NameString RegionSpace RegionOffset RegionLen"}, + {0x5B81, 0x5B81, "0x5B81", "FieldOp", "TermObject", "NameString ByteData", "FieldList", + "DefField := FieldOp PkgLength NameString FieldFlags FieldList"}, + {0x5B82, 0x5B82, "0x5B82", "DeviceOp", "TermObject", "NameString", "ObjectList", + "DefDevice := DeviceOp PkgLength NameString ObjectList"}, + {0x5B83, 0x5B83, "0x5B83", "ProcessorOp", "TermObject", "NameString ByteData DWordData ByteData", "ObjectList", + "DefProcessor := ProcessorOp PkgLength NameString ProcID PblkAddr PblkLen ObjectList"}, + {0x5B84, 0x5B84, "0x5B84", "PowerResOp", "TermObject", "NameString ByteData WordData", "ObjectList", + "DefPowerRes := PowerResOp PkgLength NameString SystemLevel ResourceOrder ObjectList"}, + {0x5B85, 0x5B85, "0x5B85", "ThermalZoneOp", "TermObject", "NameString", "ObjectList", + "DefThermalZone := ThermalZoneOp PkgLength NameString ObjectList"}, + {0x5B86, 0x5B86, "0x5B86", "IndexFieldOp", "TermObject", "NameString NameString ByteData", "FieldList", + "DefIndexField := IndexFieldOp PkgLength NameString NameString FieldFlags FieldList"}, + {0x5B87, 0x5B87, "0x5B87", "BankFieldOp", "TermObject", "NameString NameString TermArg ByteData", "FieldList", + "DefBankField := BankFieldOp PkgLength NameString NameString BankValue FieldFlags FieldList"}, + {0x5B88, 0x5B88, "0x5B88", "DataRegionOp", "TermObject", "NameString TermArg TermArg TermArg", NULL, + "DefDataRegion := DataRegionOp NameString TermArg TermArg TermArg"}, + {0x5B89, 0x5BFF, "0x5B89-0x5BFF", NULL, NULL, NULL, NULL, + NULL}, + {0x5C, 0x5C, "0x5C", "RootChar", "NameObject", NULL, NULL, + NULL}, + {0x5D, 0x5D, "0x5D", NULL, NULL, NULL, NULL, + NULL}, + {0x5E, 0x5E, "0x5E", "ParentPrefixChar", "NameObject", NULL, NULL, + NULL}, + {0x5F, 0x5F, "0x5F", "NameChar", "NameObject", NULL, NULL, + NULL}, + {0x60, 0x60, "0x60", "Local0Op", "LocalObject", NULL, NULL, + NULL}, + {0x61, 0x61, "0x61", "Local1Op", "LocalObject", NULL, NULL, + NULL}, + {0x62, 0x62, "0x62", "Local2Op", "LocalObject", NULL, NULL, + NULL}, + {0x63, 0x63, "0x63", "Local3Op", "LocalObject", NULL, NULL, + NULL}, + {0x64, 0x64, "0x64", "Local4Op", "LocalObject", NULL, NULL, + NULL}, + {0x65, 0x65, "0x65", "Local5Op", "LocalObject", NULL, NULL, + NULL}, + {0x66, 0x66, "0x66", "Local6Op", "LocalObject", NULL, NULL, + NULL}, + {0x67, 0x67, "0x67", "Local7Op", "LocalObject", NULL, NULL, + NULL}, + {0x68, 0x68, "0x68", "Arg0Op", "ArgObject", NULL, NULL, + NULL}, + {0x69, 0x69, "0x69", "Arg1Op", "ArgObject", NULL, NULL, + NULL}, + {0x6A, 0x6A, "0x6A", "Arg2Op", "ArgObject", NULL, NULL, + NULL}, + {0x6B, 0x6B, "0x6B", "Arg3Op", "ArgObject", NULL, NULL, + NULL}, + {0x6C, 0x6C, "0x6C", "Arg4Op", "ArgObject", NULL, NULL, + NULL}, + {0x6D, 0x6D, "0x6D", "Arg5Op", "ArgObject", NULL, NULL, + NULL}, + {0x6E, 0x6E, "0x6E", "Arg6Op", "ArgObject", NULL, NULL, + NULL}, + {0x6F, 0x6F, "0x6F", NULL, NULL, NULL, NULL, + NULL}, + {0x70, 0x70, "0x70", "StoreOp", "TermObject", "TermArg SuperName", NULL, + "DefStore := StoreOp TermArg SuperName"}, + {0x71, 0x71, "0x71", "RefOfOp", "TermObject", "SuperName ", NULL, + "DefRefOf := RefOfOp SuperName"}, + {0x72, 0x72, "0x72", "AddOp", "TermObject", "TermArg TermArg Target", NULL, + "DefAdd := AddOp Operand Operand Target"}, + {0x73, 0x73, "0x73", "ConcatOp", "TermObject", "TermArg TermArg Target", NULL, + "DefConcat := ConcatOp Data Data Target"}, + {0x74, 0x74, "0x74", "SubtractOp", "TermObject", "TermArg TermArg Target", NULL, + "DefSubtract := SubtractOp Operand Operand Target"}, + {0x75, 0x75, "0x75", "IncrementOp", "TermObject", "SuperName", NULL, + "DefIncrement := IncrementOp SuperName"}, + {0x76, 0x76, "0x76", "DecrementOp", "TermObject", "SuperName", NULL, + "DefDecrement := DecrementOp SuperName"}, + {0x77, 0x77, "0x77", "MultiplyOp", "TermObject", "TermArg TermArg Target", NULL, + "DefMultiply := MultiplyOp Operand Operand Target"}, + {0x78, 0x78, "0x78", "DivideOp", "TermObject", "TermArg TermArg Target Target", NULL, + "DefDivide := DivideOp Dividend Divisor Remainder Quotient"}, + {0x79, 0x79, "0x79", "ShiftLeftOp", "TermObject", "TermArg TermArg Target", NULL, + "DefShiftLeft := ShiftLeftOp Operand ShiftCount Target"}, + {0x7A, 0x7A, "0x7A", "ShiftRightOp", "TermObject", "TermArg TermArg Target", NULL, + "DefShiftRight := ShiftRightOp Operand ShiftCount Target"}, + {0x7B, 0x7B, "0x7B", "AndOp", "TermObject", "TermArg TermArg Target", NULL, + "DefAnd := AndOp Operand Operand Target"}, + {0x7C, 0x7C, "0x7C", "NandOp", "TermObject", "TermArg TermArg Target", NULL, + "DefNAnd := NandOp Operand Operand Target"}, + {0x7D, 0x7D, "0x7D", "OrOp", "TermObject", "TermArg TermArg Target", NULL, + "DefOr := OrOp Operand Operand Target"}, + {0x7E, 0x7E, "0x7E", "NorOp", "TermObject", "TermArg TermArg Target", NULL, + "DefNOr := NorOp Operand Operand Target"}, + {0x7F, 0x7F, "0x7F", "XorOp", "TermObject", "TermArg TermArg Target", NULL, + "DefXOr := XorOp Operand Operand Target"}, + {0x80, 0x80, "0x80", "NotOp", "TermObject", "TermArg Target", NULL, + "DefNot := NotOp Operand Target"}, + {0x81, 0x81, "0x81", "FindSetLeftBitOp", "TermObject", "TermArg Target", NULL, + "DefFindSetLeftBit := FindSetLeftBitOp Operand Target"}, + {0x82, 0x82, "0x82", "FindSetRightBitOp", "TermObject", "TermArg Target", NULL, + "DefFindSetRightBit := FindSetRightBitOp Operand Target"}, + {0x83, 0x83, "0x83", "DerefOfOp", "TermObject", "TermArg", NULL, + "DefDerefOf := DerefOfOp ObjReference"}, + {0x84, 0x84, "0x84", "ConcatResOp", "TermObject", "TermArg TermArg Target", NULL, + "DefConcatRes := ConcatResOp BufData BufData Target"}, + {0x85, 0x85, "0x85", "ModOp", "TermObject", "TermArg TermArg Target", NULL, + "DefMod := ModOp Dividend Divisor Target"}, + {0x86, 0x86, "0x86", "NotifyOp", "TermObject", "SuperName TermArg", NULL, + "DefNotify := NotifyOp NotifyObject NotifyValue"}, + {0x87, 0x87, "0x87", "SizeOfOp", "TermObject", "SuperName", NULL, + "DefSizeOf := SizeOfOp SuperName"}, + {0x88, 0x88, "0x88", "IndexOp", "TermObject", "TermArg TermArg Target", NULL, + "DefIndex := IndexOp BuffPkgStrObj IndexValue Target"}, + {0x89, 0x89, "0x89", "MatchOp", "TermObject", "TermArg ByteData TermArg ByteData TermArg TermArg", NULL, + "DefMatch := MatchOp SearchPkg MatchOpcode Operand MatchOpcode Operand StartIndex"}, + {0x8A, 0x8A, "0x8A", "CreateDWordFieldOp", "TermObject", "TermArg TermArg NameString", NULL, + "DefCreateDWordField := CreateDWordFieldOp SourceBuff ByteIndex NameString"}, + {0x8B, 0x8B, "0x8B", "CreateWordFieldOp", "TermObject", "TermArg TermArg NameString", NULL, + "DefCreateWordField := CreateWordFieldOp SourceBuff ByteIndex NameString"}, + {0x8C, 0x8C, "0x8C", "CreateByteFieldOp", "TermObject", "TermArg TermArg NameString", NULL, + "DefCreateByteField := CreateByteFieldOp SourceBuff ByteIndex NameString"}, + {0x8D, 0x8D, "0x8D", "CreateBitFieldOp", "TermObject", "TermArg TermArg NameString", NULL, + "DefCreateBitField := CreateBitFieldOp SourceBuff BitIndex NameString"}, + {0x8E, 0x8E, "0x8E", "ObjectTypeOp", "TermObject", "SuperName", NULL, + "DefObjectType := ObjectTypeOp SuperName"}, + {0x8F, 0x8F, "0x8F", "CreateQWordFieldOp", "TermObject", "TermArg TermArg NameString", NULL, + "DefCreateQWordField := CreateQWordFieldOp SourceBuff ByteIndex NameString"}, + {0x90, 0x90, "0x90", "LAndOp", "TermObject", "TermArg TermArg", NULL, + "DefLAnd := LandOp Operand Operand"}, + {0x91, 0x91, "0x91", "LOrOp", "TermObject", "TermArg TermArg", NULL, + "DefLOr := LorOp Operand Operand"}, + {0x92, 0x92, "0x92", "LNotOp", "TermObject", "TermArg", NULL, + "DefLNot := LnotOp Operand"}, + {0x9293, 0x9293, "0x9293", "LNotEqualOp", "TermObject", "TermArg TermArg", NULL, + "DefLNotEqual := LnotEqualOp Operand Operand"}, + {0x9294, 0x9294, "0x9294", "LLessEqualOp", "TermObject", "TermArg TermArg", NULL, + "DefLLessEqual := LlessEqualOp Operand Operand"}, + {0x9295, 0x9295, "0x9295", "LGreaterEqualOp", "TermObject", "TermArg TermArg", NULL, + "DefLGreaterEqual := LgreaterEqualOp Operand Operand"}, + {0x93, 0x93, "0x93", "LEqualOp", "TermObject", "TermArg TermArg", NULL, + "DefLEqual := LequalOp Operand Operand"}, + {0x94, 0x94, "0x94", "LGreaterOp", "TermObject", "TermArg TermArg", NULL, + "DefLGreater := LgreaterOp Operand Operand"}, + {0x95, 0x95, "0x95", "LLessOp", "TermObject", "TermArg TermArg", NULL, + "DefLLess := LlessOp Operand Operand"}, + {0x96, 0x96, "0x96", "ToBufferOp", "TermObject", "TermArg Target", NULL, + "DefToBuffer := ToBufferOp Operand Target"}, + {0x97, 0x97, "0x97", "ToDecimalStringOp", "TermObject", "TermArg Target", NULL, + "DefToDecimalString := ToDecimalStringOp Operand Target"}, + {0x98, 0x98, "0x98", "ToHexStringOp", "TermObject", "TermArg Target", NULL, + "DefToHexString := ToHexStringOp Operand Target"}, + {0x99, 0x99, "0x99", "ToIntegerOp", "TermObject", "TermArg Target", NULL, + "DefToInteger := ToIntegerOp Operand Target"}, + {0x9A, 0x9B, "0x9A-0x9B", NULL, NULL, NULL, NULL, + NULL}, + {0x9C, 0x9C, "0x9C", "ToStringOp", "TermObject", "TermArg TermArg Target", NULL, + "DefToString := ToStringOp TermArg LengthArg Target"}, + {0x9D, 0x9D, "0x9D", "CopyObjectOp", "TermObject", "TermArg SimpleName", NULL, + "DefCopyObject := CopyObjectOp TermArg SimpleName"}, + {0x9E, 0x9E, "0x9E", "MidOp", "TermObject", "TermArg TermArg TermArg Target", NULL, + "DefMid := MidOp MidObj TermArg TermArg Target"}, + {0x9F, 0x9F, "0x9F", "ContinueOp", "TermObject", NULL, NULL, + "DefContinue := ContinueOp"}, + {0xA0, 0xA0, "0xA0", "IfOp", "TermObject", "TermArg", "TermList", + "DefIfElse := IfOp PkgLength Predicate TermList DefElse"}, + {0xA1, 0xA1, "0xA1", "ElseOp", "TermObject", NULL, "TermList", + "DefElse := Nothing | "}, + {0xA2, 0xA2, "0xA2", "WhileOp", "TermObject", "TermArg", "TermList", + "DefWhile := WhileOp PkgLength Predicate TermList"}, + {0xA3, 0xA3, "0xA3", "NoopOp", "TermObject", NULL, NULL, + "DefNoop := NoopOp"}, + {0xA4, 0xA4, "0xA4", "ReturnOp", "TermObject", "TermArg", NULL, + "DefReturn := ReturnOp ArgObject"}, + {0xA5, 0xA5, "0xA5", "BreakOp", "TermObject", NULL, NULL, + "DefBreak := BreakOp"}, + {0xA6, 0xCB, "0xA6-0xCB", NULL, NULL, NULL, NULL, + NULL}, + {0xCC, 0xCC, "0xCC", "BreakPointOp", "TermObject", NULL, NULL, + "DefBreakPoint := BreakPointOp"}, + {0xCD, 0xFE, "0xCD-0xFE", NULL, NULL, NULL, NULL, + NULL}, + {0xFF, 0xFF, "0xFF", "OnesOp", "DataObject", NULL, NULL, + NULL}, + {0, 0, NULL, NULL, NULL, NULL, NULL, NULL} +}; diff --git a/source/tools/acpihelp/ahaslkey.c b/source/tools/acpihelp/ahaslkey.c new file mode 100644 index 000000000000..65adc5b44a77 --- /dev/null +++ b/source/tools/acpihelp/ahaslkey.c @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Module Name: ahaslkey - Table of all known ASL non-operator keywords + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + +/* + * ASL Keyword types and associated actual keywords. + * This table was extracted from the ACPI specification. + */ +const AH_ASL_KEYWORD AslKeywordInfo[] = +{ + {"AccessAttribKeyword", "Serial Bus Attributes (with legacy SMBus aliases)", + ":= AttribQuick (SMBusQuick) | AttribSendReceive (SMBusSendReceive) | " + "AttribByte (SMBusByte) | AttribWord (SMBusWord) | " + "AttribBlock (SMBusBlock) | AttribProcessCall (SMBusProcessCall) | " + "AttribBlockProcessCall (SMBusProcessCall)"}, + {"AccessTypeKeyword", "Field Access Types", + ":= AnyAcc | ByteAcc | WordAcc | DWordAcc | QWordAcc | BufferAcc"}, + {"AddressingModeKeyword", "Mode - Resource Descriptors", + ":= AddressingMode7Bit | AddressingMode10Bit"}, + {"AddressKeyword", "ACPI memory range types", + ":= AddressRangeMemory | AddressRangeReserved | " + "AddressRangeNVS | AddressRangeACPI"}, + {"AddressSpaceKeyword", "Operation Region Address Space Types", + ":= RegionSpaceKeyword | FFixedHW"}, + {"BusMasterKeyword", "DMA Bus Mastering", + ":= BusMaster | NotBusMaster"}, + {"ByteLengthKeyword", "Bits per Byte - Resource Descriptors", + ":= DataBitsFive | DataBitsSix | DataBitsSeven | DataBitsEight | DataBitsNine"}, + {"ClockPhaseKeyword", "Resource Descriptors", + ":= ClockPhaseFirst | ClockPhaseSecond"}, + {"ClockPolarityKeyword", "Resource Descriptors", + ":= ClockPolarityLow | ClockPolarityHigh"}, + {"DecodeKeyword", "Type of Memory Decoding - Resource Descriptors", + ":= SubDecode | PosDecode"}, + {"DmaTypeKeyword", "DMA Types - DMA Resource Descriptor", + ":= Compatibility | TypeA | TypeB | TypeF"}, + {"EndianKeyword", "Endian type - Resource Descriptor", + ":= BigEndian | LittleEndian"}, + {"ExtendedAttribKeyword", "Extended Bus Attributes", + ":= AttribBytes (AccessLength) | AttribRawBytes (AccessLength) | " + "AttribRawProcessBytes (AccessLength)"}, + {"FlowControlKeyword", "Resource Descriptor", + ":= FlowControlNone | FlowControlXon | FlowControlHardware"}, + {"InterruptLevelKeyword", "Interrupt Active Types", + ":= ActiveHigh | ActiveLow | ActiveBoth"}, + {"InterruptTypeKeyword", "Interrupt Types", + ":= Edge | Level"}, + {"IoDecodeKeyword", "I/O Decoding - IO Resource Descriptor", + ":= Decode16 | Decode10"}, + {"IoRestrictionKeyword", "I/O Restriction - GPIO Resource Descriptors", + ":= IoRestrictionNone | IoRestrictionInputOnly | " + "IoRestrictionOutputOnly | IoRestrictionNoneAndPreserve"}, + {"LockRuleKeyword", "Global Lock use for Field Operator", + ":= Lock | NoLock"}, + {"MatchOpKeyword", "Types for Match Operator", + ":= MTR | MEQ | MLE | MLT | MGE | MGT"}, + {"MaxKeyword", "Max Range Type - Resource Descriptors", + ":= MaxFixed | MaxNotFixed"}, + {"MemTypeKeyword", "Memory Types - Resource Descriptors", + ":= Cacheable | WriteCombining | Prefetchable | NonCacheable"}, + {"MinKeyword", "Min Range Type - Resource Descriptors", + ":= MinFixed | MinNotFixed"}, + {"ObjectTypeKeyword", "ACPI Object Types", + ":= UnknownObj | IntObj | StrObj | BuffObj | PkgObj | FieldUnitObj | " + "DeviceObj | EventObj | MethodObj | MutexObj | OpRegionObj | PowerResObj | " + "ProcessorObj | ThermalZoneObj | BuffFieldObj | DDBHandleObj"}, + {"ParityKeyword", "Resource Descriptors", + ":= ParityTypeNone | ParityTypeSpace | ParityTypeMark | " + "ParityTypeOdd | ParityTypeEven"}, + {"PinConfigKeyword", "Pin Configuration - GPIO Resource Descriptors", + ":= PullDefault | PullUp | PullDown | PullNone"}, + {"PolarityKeyword", "Resource Descriptors", + ":= PolarityHigh | PolarityLow"}, + {"RangeTypeKeyword", "I/O Range Types - Resource Descriptors", + ":= ISAOnlyRanges | NonISAOnlyRanges | EntireRange"}, + {"ReadWriteKeyword", "Memory Access Types - Resource Descriptors", + ":= ReadWrite | ReadOnly"}, + {"RegionSpaceKeyword", "Operation Region Address Space Types", + ":= UserDefRegionSpace | SystemIO | SystemMemory | PCI_Config | " + "EmbeddedControl | SMBus | SystemCMOS | PciBarTarget | IPMI | " + "GeneralPurposeIo, GenericSerialBus"}, + {"ResourceTypeKeyword", "Resource Usage - Resource Descriptors", + ":= ResourceConsumer | ResourceProducer"}, + {"SerializeRuleKeyword", "Control Method Serialization", + ":= Serialized | NotSerialized"}, + {"ShareTypeKeyword", "Interrupt Sharing - Resource Descriptors", + ":= Shared | Exclusive | SharedAndWake | ExclusiveAndWake"}, + {"SlaveModeKeyword", "Resource Descriptors", + ":= ControllerInitiated | DeviceInitiated"}, + {"StopBitsKeyword", "Resource Descriptors", + ":= StopBitsZero | StopBitsOne | StopBitsOnePlusHalf | StopBitsTwo"}, + {"TransferWidthKeyword", "DMA Widths - Fixed DMA Resource Descriptor", + ":= Width8bit | Width16bit | Width32bit | Width64bit | " + "Width128bit | Width256bit"}, + {"TranslationKeyword", "Translation Density Types - Resource Descriptors", + ":= SparseTranslation | DenseTranslation"}, + {"TypeKeyword", "Translation Types - Resource Descriptors", + ":= TypeTranslation | TypeStatic"}, + {"UpdateRuleKeyword", "Field Update Rules", + ":= Preserve | WriteAsOnes | WriteAsZeros"}, + {"UserDefRegionSpace", "User defined address spaces", + ":= IntegerData => 0x80 - 0xFF"}, + {"WireModeKeyword", "SPI Wire Mode - Resource Descriptors", + ":= ThreeWireMode | FourWireMode"}, + {"XferTypeKeyword", "DMA Transfer Types", + ":= Transfer8 | Transfer16 | Transfer8_16"}, + {NULL, NULL, NULL} +}; diff --git a/source/tools/acpihelp/ahaslops.c b/source/tools/acpihelp/ahaslops.c new file mode 100644 index 000000000000..80ea1d2dcd03 --- /dev/null +++ b/source/tools/acpihelp/ahaslops.c @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * Module Name: ahaslops - Table of all known ASL operators + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + +/* + * ASL operators with syntax (directly from ACPI specification). + * Note: All tokens require a space separator. + * Long lines are automatically split during output. + */ +const AH_ASL_OPERATOR AslOperatorInfo[] = +{ + {"AccessAs", "(AccessType, AccessAttribKeyword | " + "ExtendedAttribKeyword (AccessLength))", + "ChangeFieldUnitAccess"}, + {"Acquire", "(SyncObject, TimeoutValue) => Boolean", + "Acquire a mutex"}, + {"Add", "(Addend1, Addend2, Result) => Integer", + "Integer Add"}, + {"Alias", "(SourceObject, AliasObject)", + "Define a name alias"}, + {"And", "(Source1, Source2, Result) => Integer", + "Integer Bitwise And"}, + {"Arg", "Arg0 - Arg6", + "Method argument data objects"}, + {"BankField", "(RegionName, BankName, BankValue, " + "AccessTypeKeyword, LockRuleKeyword, " + "UpdateRuleKeyword) {FieldUnitList}", + "Declare fields in a banked configuration object"}, + {"Break", "No parameters", + "Continue following the innermost enclosing While"}, + {"BreakPoint", "No parameters", + "Used for debugging, stops execution in the debugger"}, + {"Buffer", "(BufferSize) {String or ByteList} => Buffer", + "Declare Buffer object"}, + {"Case", "(Value) {TermList}", + "Expression for conditional execution"}, + {"Concatenate", "(Source1, Source2, Result) => ComputationalData", + "Concatenate two strings}, integers or buffers"}, + {"ConcatenateResTemplate", "(Source1, Source2, Result) => Buffer", + "Concatenate two resource templates"}, + {"CondRefOf", "(Source, Result) => Boolean", + "Conditional reference to an object"}, + {"Connection", "(ResourceMacro)", + "Associate connection with FieldUnits within a Field object"}, + {"Continue", "No parameters", + "Continue innermost enclosing While loop"}, + {"CopyObject", "(Source, Destination) => DataRefObject", + "Copy and existing object"}, + {"CreateBitField", "(SourceBuffer, BitIndex, BitFieldName)", + "Declare a bit field object of a buffer object"}, + {"CreateByteField", "(SourceBuffer, ByteIndex, ByteFieldName)", + "Declare a byte field object of a buffer object"}, + {"CreateDWordField", "(SourceBuffer, ByteIndex, DWordFieldName)", + "Declare a DWord field object of a buffer object"}, + {"CreateField", "(SourceBuffer, BitIndex, NumBits, FieldName)", + "Declare an arbitrary length bit field of a buffer object"}, + {"CreateQWordField", "(SourceBuffer, ByteIndex, QWordFieldName)", + "Declare a QWord field object of a buffer object"}, + {"CreateWordField", "(SourceBuffer, ByteIndex, WordFieldName)", + "Declare a Word field object of a buffer object"}, + {"DataTableRegion", "(RegionName, SignatureString, OemIDString, OemTableIDString)", + "Declare a Data Table Region"}, + {"Debug", "No parameters", + "Debugger output"}, + {"Decrement", "(Minuend) => Integer", + "Decrement an Integer"}, + {"Default", "{TermList}", + "Default execution path in Switch()"}, + {"DefinitionBlock", "(AMLFileName, TableSignature, ComplianceRevision, " + "OEMID, TableID, OEMRevision) {TermList}", + "Declare a Definition Block"}, + {"DerefOf", "(Source) => Object", + "Dereference an object reference"}, + {"Device", "(DeviceName) {ObjectList}", + "Declare a bus/device object"}, + {"Divide", "(Dividend, Divisor, Remainder, Result) => Integer", + "Integer Divide"}, + {"DMA", "(DmaTypeKeyword, BusMasterKeyword, XferTypeKeyword, " + "DescriptorName) {DmaChannelList} => Buffer", + "DMA Resource Descriptor macro"}, + {"DWordIO", "(ResourceTypeKeyword, MinKeyword, MaxKeyword, " + "DecodeKeyword, RangeTypeKeyword, AddressGranularity, " + "AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, ResourceSourceIndex, " + "ResourceSource, DescriptorName, TypeKeyword, TranslationKeyword)", + "DWord IO Resource Descriptor macro"}, + {"DWordMemory", "(ResourceTypeKeyword, DecodeKeyword, MinKeyword, " + "MaxKeyword, MemTypeKeyword, ReadWriteKeyword, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName, AddressKeyword, " + "TypeKeyword)", + "DWord Memory Resource Descriptor macro"}, + {"DWordSpace", "(ResourceType, ResourceTypeKeyword, DecodeKeyword, " + "MinKeyword, MaxKeyword, TypeSpecificFlags, " + "AddressGranularity, AddressMinimum, AddressMaximum, " + "AddressTranslation, RangeLength, " + "ResourceSourceIndex, ResourceSource, DescriptorName)", + "DWord Space Resource Descriptor macro"}, + {"EISAID", "(EisaIdString) => DWordConst", + "EISA ID String to Integer conversion macro"}, + {"Else", "{TermList}", + "Alternate conditional execution"}, + {"ElseIf", "(Predicate)", + "Conditional execution"}, + {"EndDependentFn", "() => Buffer", + "End Dependent Function Resource Descriptor macro"}, + {"Event", "(EventName)", + "Declare an event synchronization object"}, + {"ExtendedIO", "(ResourceTypeKeyword, MinKeyword, MaxKeyword, " + "DecodeKeyword, RangeTypeKeyword, AddressGranularity, " + "AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, " + "TypeSpecificAttributes, DescriptorName, TypeKeyword, TranslationKeyword)", + "Extended IO Resource Descriptor macro"}, + {"ExtendedMemory", "(ResourceTypeKeyword, DecodeKeyword, MinKeyword, " + "MaxKeyword, MemTypeKeyword, ReadWriteKeyword, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, TypeSpecificAttributes, DescriptorName, " + "AddressKeyword, TypeKeyword)", + "Extended Memory Resource Descriptor macro"}, + {"ExtendedSpace", "(ResourceType, ResourceTypeKeyword, DecodeKeyword, " + "MinKeyword, MaxKeyword, TypeSpecificFlags, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, TypeSpecificAttributes, DescriptorName)", + "Extended Space Resource Descriptor macro"}, + {"External", "(ObjectName, ObjectTypeKeyword, ReturnType, ParameterTypes)", + "Declare external objects"}, + {"Fatal", "(Type, Code, Arg)", + "Fatal error check"}, + {"Field", "(RegionName, AccessTypeKeyword, LockRuleKeyword, " + "UpdateRuleKeyword) {FieldUnitList}", + "Declare fields of an operation region object"}, + {"FindSetLeftBit", "(Source, Result) => Integer", + "Index of first least significant bit set"}, + {"FindSetRightBit", "(Source, Result) => Integer", + "Index of first most significant bit set"}, + {"FixedDMA", "(DmaRequestLine, Channel, TransferWidthKeyword, DescriptorName) => Buffer", + "Fixed DMA Resource Descriptor macro"}, + {"FixedIO", "(AddressBase, RangeLength, DescriptorName) => Buffer", + "Fixed I/O Resource Descriptor macro"}, + {"FromBCD", "(BCDValue, Result) => Integer", + "Convert from BCD to numeric"}, + {"Function", "(FunctionName, ReturnType, ParameterTypes) {TermList}", + "Declare control method"}, + {"GpioInt", "(InterruptTypeKeyword, InterruptLevelKeyword, " + "ShareTypeKeyword, PinConfigKeyword, " + "DebounceTimeout, ResourceSource, " + "ResourceSourceIndex, ResourceTypeKeyword, DescriptorName, " + "RawDataBuffer() {VendorData}) {Pin}", + "GPIO Interrupt Connection Resource Descriptor Macro"}, + {"GpioIo", "(ShareTypeKeyword, PinConfigKeyword, DebounceTimeout, DriveStrength, " + "IoRestrictionKeyword, ResourceSource, " + "ResourceSourceIndex, ResourceTypeKeyword, DescriptorName, " + "RawDataBuffer() {VendorData}) {PinList}", + "GPIO I/O Connection Resource Descriptor Macro"}, + {"I2cSerialBus", "(SlaveAddress, SlaveModeKeyword, ConnectionSpeed, " + "AddressingModeKeyword, ResourceSource, " + "ResourceSourceIndex, ResourceTypeKeyword, DescriptorName, " + "RawDataBuffer() {VendorData})", + "I2C Serial Bus Connection Resource Descriptor Macro"}, + {"If", "(Predicate) {TermList}", + "Conditional execution"}, + {"Include", "(FilePathName)", + "Include another ASL file"}, + {"Increment", "(Addend) => Integer", + "Increment a Integer"}, + {"Index", "(Source, Index, Destination) => ObjectReference", + "Indexed Reference to member object"}, + {"IndexField", "(IndexName, DataName, AccessTypeKeyword, LockRuleKeyword, " + "UpdateRuleKeyword) {FieldUnitList}", + "Declare Index/Data Fields"}, + {"Interrupt", "(ResourceTypeKeyword, InterruptTypeKeyword, InterruptLevelKeyword, " + "ShareTypeKeyword, ResourceSourceIndex, " + "ResourceSource, DescriptorName) {InterruptList} => Buffer", + "Interrupt Resource Descriptor macro"}, + {"IO", "(IoDecodeKeyword, AddressMin, AddressMax, AddressAlignment, " + "RangeLength, DescriptorName) => Buffer", + "IO Resource Descriptor macro"}, + {"IRQ", "(InterruptTypeKeyword, InterruptLevelKeyword, ShareTypeKeyword, " + "DescriptorName) {InterruptList} => Buffer", + "Interrupt Resource Descriptor macro"}, + {"IRQNoFlags", "(DescriptorName) {InterruptList} => Buffer", + "Short Interrupt Resource Descriptor macro"}, + {"LAnd", "(Source1, Source2) => Boolean", + "Logical And"}, + {"LEqual", "(Source1, Source2) => Boolean", + "Logical Equal"}, + {"LGreater", "(Source1, Source2) => Boolean", + "Logical Greater"}, + {"LGreaterEqual", "(Source1, Source2) => Boolean", + "Logical Not less"}, + {"LLess", "(Source1, Source2) => Boolean", + "Logical Less"}, + {"LLessEqual", "(Source1, Source2) => Boolean", + "Logical Not greater"}, + {"LNot", "(Source) => Boolean", + "Logical Not"}, + {"LNotEqual", "(Source1, Source2) => Boolean", + "Logical Not equal"}, + {"Load", "(Object, DDBHandle)", + "Load differentiating definition block"}, + {"LoadTable", "(SignatureString, OEMIDString, OEMTableIDString, RootPathString, " + "ParameterPathString, ParameterData) => DDBHandle", + "Load Table from RSDT/XSDT"}, + {"Local", "Local0 - Local 7", + "Method local data objects"}, + {"LOr", "(Source1, Source2) => Boolean", + "Logical Or"}, + {"Match", "(SearchPackage, MatchOpKeyword, MatchObject1, MatchOpKeyword, " + "MatchObject2, StartIndex) => Ones | Integer", + "Search for match in package array"}, + {"Memory24", "(ReadWriteKeyword, AddressMinimum, AddressMaximum, AddressAlignment, " + "RangeLength, DescriptorName)", + "Memory Resource Descriptor macro"}, + {"Memory32", "(ReadWriteKeyword, AddressMinimum, AddressMaximum, AddressAlignment, " + "RangeLength, DescriptorName)", + "Memory Resource Descriptor macro"}, + {"Memory32Fixed", "(ReadWriteKeyword, AddressBase, RangeLength, DescriptorName)", + "Memory Resource Descriptor macro"}, + {"Method", "(MethodName, NumArgs, SerializeRuleKeyword, " + "SyncLevel, ReturnType, ParameterTypes) " + "{TermList}", + "Declare a control method"}, + {"Mid", "(Source, Index, Length, Result) => Buffer or String", + "Return a portion of buffer or string"}, + {"Mod", "(Dividend, Divisor, Result) => Integer", + "Integer Modulo"}, + {"Multiply", "(Multiplicand, Multiplier, Result) => Integer", + "Integer Multiply"}, + {"Mutex", "(MutexName, SyncLevel)", + "Declare a mutex synchronization object"}, + {"Name", "(ObjectName, Object)", + "Declare a Named object"}, + {"NAnd", "(Source1, Source2, Result) => Integer", + "Integer Bitwise Nand"}, + {"NoOp", "No parameters", + "No operation"}, + {"NOr", "(Source1, Source2, Result) => Integer", + "Integer Bitwise Nor"}, + {"Not", "(Source, Result) => Integer", + "Integer Bitwise Not"}, + {"Notify", "(Object, NotificationValue)", + "Notify Object of event"}, + {"ObjectType", "(Object) => Integer", + "Type of object"}, + {"Offset", "(ByteOffset)", + "Change Current Field Unit Offset"}, + {"One", "=> Integer", + "Constant One Object (1)"}, + {"Ones", "=> Integer", + "Constant Ones Object (-1)"}, + {"OperationRegion", "(RegionName, RegionSpaceKeyword, Offset, Length)", + "Declare an operational region"}, + {"Or", "(Source1, Source2, Result) => Integer", + "Integer Bitwise Or"}, + {"Package", "(NumElements) {PackageList} => Package", + "Declare a package object"}, + {"PowerResource", "(ResourceName, SystemLevel, ResourceOrder) {ObjectList}", + "Declare a power resource object"}, + {"Processor", "(ProcessorName, ProcessorID, PBlockAddress, PblockLength) {ObjectList}", + "Declare a processor package"}, + {"QWordIO", "(ResourceTypeKeyword, MinKeyword, MaxKeyword, DecodeKeyword, " + "RangeTypeKeyword, AddressGranularity, " + "AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, " + "ResourceSourceIndex, ResourceSource, DescriptorName, TypeKeyword, " + "TranslationKeyword)", + "QWord IO Resource Descriptor macro"}, + {"QWordMemory", "(ResourceTypeKeyword, DecodeKeyword, MinKeyword, MaxKeyword, " + "MemTypeKeyword, ReadWriteKeyword, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, ResourceSourceIndex, ResourceSource, " + "DescriptorName, AddressKeyword, " + "TypeKeyword)", + "QWord Memory Resource Descriptor macro"}, + {"QWordSpace", "(ResourceType, ResourceTypeKeyword, DecodeKeyword, " + "MinKeyword, MaxKeyword, TypeSpecificFlags, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName)", + "Qword Space Resource Descriptor macro"}, + {"RawDataBuffer", "(BufferSize) {ByteList} => RawDataBuffer", + "Create a raw data buffer (does not use Buffer AML opcode)"}, + {"RefOf", "(Object) => ObjectReference", + "Create Reference to an object"}, + {"Register", "(AddressSpaceKeyword, RegisterBitWidth, " + "RegisterBitOffset, RegisterAddress, " + "AccessSize, DescriptorName)", + "Generic register Resource Descriptor macro"}, + {"Release", "(SyncObject)", + "Release a synchronization object"}, + {"Reset", "(SyncObject)", + "Reset a synchronization object"}, + {"ResourceTemplate", "() {ResourceMacroList} => Buffer", + "Resource to buffer conversion macro"}, + {"Return", "None | () | (ReturnArg)", + "Return from method execution"}, + {"Revision", "=> Integer", + "Constant revision object"}, + {"Scope", "(Location) {ObjectList}", + "Open named scope "}, + {"ShiftLeft", "(Source, ShiftCount, Result) => Integer", + "Integer shift value left"}, + {"ShiftRight", "(Source, ShiftCount, Result) => Integer", + "Integer shift value right"}, + {"Signal", "(SyncObject)", + "Signal a synchronization object"}, + {"SizeOf", "(ObjectName) => Integer", + "Get the size of a buffer}, string}, or package"}, + {"Sleep", "(MilliSeconds)", + "Sleep n milliseconds (yields the processor)"}, + {"SpiSerialBus", "(DeviceSelection, PolarityKeyword, WireModeKeyword, " + "DataBitLength, SlaveModeKeyword, " + "ConnectionSpeed, ClockPolarityKeyword, ClockPhaseKeyword, " + "ResourceSource, ResourceSourceIndex, " + "ResourceTypeKeyword, DescriptorName, RawDataBuffer() {VendorData})", + "SPI Serial Bus Connection Resource Descriptor Macro"}, + {"Stall", "(MicroSeconds)", + "Delay n microseconds (does not yield the processor)"}, + {"StartDependentFn", "(CompatibilityPriority, PerformancePriority) {ResourceList}", + "Start Dependent Function Resource Descriptor macro"}, + {"StartDependentFnNoPri", "() {ResourceList}", + "Start Dependent Function Resource Descriptor macro"}, + {"Store", "(Source, Destination) => DataRefObject", + "Store object"}, + {"Subtract", "(Minuend, Subtrahend, Result) => Integer", + "Integer Subtract"}, + {"Switch", "(Expression) {CaseTermList}", + "Select code to execute based on expression value"}, + {"ThermalZone", "(ThermalZoneName) {ObjectList}", + "Declare a thermal zone package"}, + {"Timer", "=> Integer", + "Get 64-bit timer value"}, + {"ToBCD", "(Value, Result) => Integer", + "Convert Integer to BCD"}, + {"ToBuffer", "(Data, Result) => Buffer", + "Convert data type to buffer"}, + {"ToDecimalString", "(Data, Result) => String", + "Convert data type to decimal string"}, + {"ToHexString", "(Data, Result) => String", + "Convert data type to hexadecimal string"}, + {"ToInteger", "(Data, Result) => Integer", + "Convert data type to integer"}, + {"ToString", "(Source, Length, Result) => String", + "Copy ASCII string from buffer"}, + {"ToUUID", "(AsciiString) => Buffer", + "Convert Ascii string to UUID"}, + {"UartSerialBus", "(ConnectionSpeed, ByteLengthKeyword, StopBitsKeyword, " + "LinesInUse, EndianKeyword, ParityKeyword, " + "FlowControlKeyword, ReceiveBufferSize, TransmitBufferSize, ResourceSource, " + "ResourceSourceIndex, ResourceTypeKeyword, DescriptorName, " + "RawDataBuffer() {VendorData})", + "UART Serial Bus Connection Resource Descriptor Macro"}, + {"Unicode", "(String) => Buffer", + "String to Unicode conversion macro"}, + {"Unload", "(Handle)", + "Unload definition block"}, + {"VendorLong", "(DescriptorName) {VendorByteList}", + "Vendor Resource Descriptor"}, + {"VendorShort", "(DescriptorName) {VendorByteList}", + "Vendor Resource Descriptor"}, + {"Wait", "(SyncObject, TimeoutValue) => Boolean", + "Wait on an Event"}, + {"While", "(Predicate) {TermList}", + "Conditional loop"}, + {"WordBusNumber", "(ResourceTypeKeyword, MinKeyword, MaxKeyword, DecodeKeyword, " + "AddressGranularity, AddressMinimum, " + "AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, " + "ResourceSource, DescriptorName)", + "Word Bus number Resource Descriptor macro"}, + {"WordIO", "(ResourceTypeKeyword, MinKeyword, MaxKeyword, DecodeKeyword, " + "RangeTypeKeyword, AddressGranularity, " + "AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, " + "ResourceSourceIndex, ResourceSource, DescriptorName, TypeKeyword, " + "TranslationKeyword)", + "Word IO Resource Descriptor macro"}, + {"WordSpace", "(ResourceType, ResourceTypeKeyword, DecodeKeyword, MinKeyword, " + "MaxKeyword, TypeSpecificFlags, " + "AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, " + "RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName)", + "Word Space Resource Descriptor macro"}, + {"XOr", "(Source1, Source2, Result) => Integer", + "Integer Bitwise Xor"}, + {"Zero", "=> Integer", + "Constant Zero object (0)"}, + {NULL, NULL, NULL} +}; diff --git a/source/tools/acpihelp/ahdecode.c b/source/tools/acpihelp/ahdecode.c new file mode 100644 index 000000000000..a61eccfe0beb --- /dev/null +++ b/source/tools/acpihelp/ahdecode.c @@ -0,0 +1,855 @@ +/****************************************************************************** + * + * Module Name: ahdecode - Operator/Opcode decoding for acpihelp utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + +#define ACPI_CREATE_PREDEFINED_TABLE +#include "acpredef.h" + +#define BUFFER_LENGTH 128 +#define LINE_BUFFER_LENGTH 512 + +static char Gbl_Buffer[BUFFER_LENGTH]; +static char Gbl_LineBuffer[LINE_BUFFER_LENGTH]; +static const char *AcpiRtypeNames[] = +{ + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + + +/* Local prototypes */ + +static BOOLEAN +AhDisplayPredefinedName ( + char *Name, + UINT32 Length); + +static void +AhDisplayPredefinedInfo ( + char *Name); + +static void +AhGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes); + +static void +AhDisplayAmlOpcode ( + const AH_AML_OPCODE *Op); + +static void +AhDisplayAslOperator ( + const AH_ASL_OPERATOR *Op); + +static void +AhDisplayOperatorKeywords ( + const AH_ASL_OPERATOR *Op); + +static void +AhDisplayAslKeyword ( + const AH_ASL_KEYWORD *Op); + +static void +AhPrintOneField ( + UINT32 Indent, + UINT32 CurrentPosition, + UINT32 MaxPosition, + const char *Field); + + +/******************************************************************************* + * + * FUNCTION: AhFindPredefinedNames (entry point for predefined name search) + * + * PARAMETERS: NamePrefix - Name or prefix to find. Must start with + * an underscore. NULL means "find all" + * + * RETURN: None + * + * DESCRIPTION: Find and display all ACPI predefined names that match the + * input name or prefix. Includes the required number of arguments + * and the expected return type, if any. + * + ******************************************************************************/ + +void +AhFindPredefinedNames ( + char *NamePrefix) +{ + UINT32 Length; + BOOLEAN Found; + char Name[9]; + + + if (!NamePrefix) + { + Found = AhDisplayPredefinedName (Name, 0); + return; + } + + /* Contruct a local name or name prefix */ + + AhStrupr (NamePrefix); + if (*NamePrefix == '_') + { + NamePrefix++; + } + + Name[0] = '_'; + strncpy (&Name[1], NamePrefix, 7); + + Length = strlen (Name); + if (Length > 4) + { + printf ("%.8s: Predefined name must be 4 characters maximum\n", Name); + return; + } + + Found = AhDisplayPredefinedName (Name, Length); + if (!Found) + { + printf ("%s, no matching predefined names\n", Name); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayPredefinedName + * + * PARAMETERS: Name - Name or name prefix + * + * RETURN: TRUE if any names matched, FALSE otherwise + * + * DESCRIPTION: Display information about ACPI predefined names that match + * the input name or name prefix. + * + ******************************************************************************/ + +static BOOLEAN +AhDisplayPredefinedName ( + char *Name, + UINT32 Length) +{ + const AH_PREDEFINED_NAME *Info; + BOOLEAN Found = FALSE; + BOOLEAN Matched; + UINT32 i; + + + /* Find/display all names that match the input name prefix */ + + for (Info = AslPredefinedInfo; Info->Name; Info++) + { + if (!Name) + { + Found = TRUE; + printf ("%s: <%s>\n", Info->Name, Info->Description); + printf ("%*s%s\n", 6, " ", Info->Action); + + AhDisplayPredefinedInfo (Info->Name); + continue; + } + + Matched = TRUE; + for (i = 0; i < Length; i++) + { + if (Info->Name[i] != Name[i]) + { + Matched = FALSE; + break; + } + } + + if (Matched) + { + Found = TRUE; + printf ("%s: <%s>\n", Info->Name, Info->Description); + printf ("%*s%s\n", 6, " ", Info->Action); + + AhDisplayPredefinedInfo (Info->Name); + } + } + + return (Found); +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayPredefinedInfo + * + * PARAMETERS: Name - Exact 4-character ACPI name. + * + * RETURN: None + * + * DESCRIPTION: Find the name in the main ACPICA predefined info table and + * display the # of arguments and the return value type. + * + * Note: Resource Descriptor field names do not appear in this + * table -- thus, nothing will be displayed for them. + * + ******************************************************************************/ + +static void +AhDisplayPredefinedInfo ( + char *Name) +{ + const ACPI_PREDEFINED_INFO *ThisName; + BOOLEAN Matched; + UINT32 i; + + + /* Find/display only the exact input name */ + + for (ThisName = PredefinedNames; ThisName->Info.Name[0]; ThisName++) + { + Matched = TRUE; + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (ThisName->Info.Name[i] != Name[i]) + { + Matched = FALSE; + break; + } + } + + if (Matched) + { + AhGetExpectedTypes (Gbl_Buffer, ThisName->Info.ExpectedBtypes); + + printf ("%*s%4.4s has %u arguments, returns: %s\n", + 6, " ", ThisName->Info.Name, ThisName->Info.ParamCount, + ThisName->Info.ExpectedBtypes ? Gbl_Buffer : "-Nothing-"); + return; + } + + if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE) + { + ThisName++; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AhGetExpectedTypes + * + * PARAMETERS: Buffer - Where the formatted string is returned + * ExpectedBTypes - Bitfield of expected data types + * + * RETURN: Formatted string in Buffer. + * + * DESCRIPTION: Format the expected object types into a printable string. + * + ******************************************************************************/ + +static void +AhGetExpectedTypes ( + char *Buffer, + UINT32 ExpectedBtypes) +{ + UINT32 ThisRtype; + UINT32 i; + UINT32 j; + + + j = 1; + Buffer[0] = 0; + ThisRtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) + { + /* If one of the expected types, concatenate the name of this type */ + + if (ExpectedBtypes & ThisRtype) + { + strcat (Buffer, &AcpiRtypeNames[i][j]); + j = 0; /* Use name separator from now on */ + } + ThisRtype <<= 1; /* Next Rtype */ + } +} + + +/******************************************************************************* + * + * FUNCTION: AhFindAmlOpcode (entry point for AML opcode name search) + * + * PARAMETERS: Name - Name or prefix for an AML opcode. + * NULL means "find all" + * + * RETURN: None + * + * DESCRIPTION: Find all AML opcodes that match the input Name or name + * prefix. + * + ******************************************************************************/ + +void +AhFindAmlOpcode ( + char *Name) +{ + const AH_AML_OPCODE *Op; + BOOLEAN Found = FALSE; + + + AhStrupr (Name); + + /* Find/display all opcode names that match the input name prefix */ + + for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++) + { + if (!Op->OpcodeName) /* Unused opcodes */ + { + continue; + } + + if (!Name) + { + AhDisplayAmlOpcode (Op); + Found = TRUE; + continue; + } + + /* Upper case the opcode name before substring compare */ + + strcpy (Gbl_Buffer, Op->OpcodeName); + AhStrupr (Gbl_Buffer); + + if (strstr (Gbl_Buffer, Name) == Gbl_Buffer) + { + AhDisplayAmlOpcode (Op); + Found = TRUE; + } + } + + if (!Found) + { + printf ("%s, no matching AML operators\n", Name); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDecodeAmlOpcode (entry point for AML opcode search) + * + * PARAMETERS: OpcodeString - String version of AML opcode + * + * RETURN: None + * + * DESCRIPTION: Display information about the input AML opcode + * + ******************************************************************************/ + +void +AhDecodeAmlOpcode ( + char *OpcodeString) +{ + const AH_AML_OPCODE *Op; + UINT32 Opcode; + UINT8 Prefix; + + + if (!OpcodeString) + { + AhFindAmlOpcode (NULL); + return; + } + + Opcode = ACPI_STRTOUL (OpcodeString, NULL, 16); + if (Opcode > ACPI_UINT16_MAX) + { + printf ("Invalid opcode (more than 16 bits)\n"); + return; + } + + /* Only valid opcode extension is 0x5B */ + + Prefix = (Opcode & 0x0000FF00) >> 8; + if (Prefix && (Prefix != 0x5B)) + { + printf ("Invalid opcode (invalid extension prefix 0x%X)\n", + Prefix); + return; + } + + /* Find/Display the opcode. May fall within an opcode range */ + + for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++) + { + if ((Opcode >= Op->OpcodeRangeStart) && + (Opcode <= Op->OpcodeRangeEnd)) + { + AhDisplayAmlOpcode (Op); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayAmlOpcode + * + * PARAMETERS: Op - An opcode info struct + * + * RETURN: None + * + * DESCRIPTION: Display the contents of an AML opcode information struct + * + ******************************************************************************/ + +static void +AhDisplayAmlOpcode ( + const AH_AML_OPCODE *Op) +{ + + if (!Op->OpcodeName) + { + printf ("%18s: Opcode=%-9s\n", "Reserved opcode", Op->OpcodeString); + return; + } + + /* Opcode name and value(s) */ + + printf ("%18s: Opcode=%-9s Type (%s)", + Op->OpcodeName, Op->OpcodeString, Op->Type); + + /* Optional fixed/static arguments */ + + if (Op->FixedArguments) + { + printf (" FixedArgs ("); + AhPrintOneField (37, 36 + 7 + strlen (Op->Type) + 12, + AH_MAX_AML_LINE_LENGTH, Op->FixedArguments); + printf (")"); + } + + /* Optional variable-length argument list */ + + if (Op->VariableArguments) + { + if (Op->FixedArguments) + { + printf ("\n%*s", 36, " "); + } + printf (" VariableArgs ("); + AhPrintOneField (37, 15, AH_MAX_AML_LINE_LENGTH, Op->VariableArguments); + printf (")"); + } + printf ("\n"); + + /* Grammar specification */ + + if (Op->Grammar) + { + AhPrintOneField (37, 0, AH_MAX_AML_LINE_LENGTH, Op->Grammar); + printf ("\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhFindAslKeywords (entry point for ASL keyword search) + * + * PARAMETERS: Name - Name or prefix for an ASL keyword. + * NULL means "find all" + * + * RETURN: None + * + * DESCRIPTION: Find all ASL keywords that match the input Name or name + * prefix. + * + ******************************************************************************/ + +void +AhFindAslKeywords ( + char *Name) +{ + const AH_ASL_KEYWORD *Keyword; + BOOLEAN Found = FALSE; + + + AhStrupr (Name); + + for (Keyword = AslKeywordInfo; Keyword->Name; Keyword++) + { + if (!Name) + { + AhDisplayAslKeyword (Keyword); + Found = TRUE; + continue; + } + + /* Upper case the operator name before substring compare */ + + strcpy (Gbl_Buffer, Keyword->Name); + AhStrupr (Gbl_Buffer); + + if (strstr (Gbl_Buffer, Name) == Gbl_Buffer) + { + AhDisplayAslKeyword (Keyword); + Found = TRUE; + } + } + + if (!Found) + { + printf ("%s, no matching ASL keywords\n", Name); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayAslKeyword + * + * PARAMETERS: Op - Pointer to ASL keyword with syntax info + * + * RETURN: None + * + * DESCRIPTION: Format and display syntax info for an ASL keyword. Splits + * long lines appropriately for reading. + * + ******************************************************************************/ + +static void +AhDisplayAslKeyword ( + const AH_ASL_KEYWORD *Op) +{ + + /* ASL keyword name and description */ + + printf ("%22s: %s\n", Op->Name, Op->Description); + if (!Op->KeywordList) + { + return; + } + + /* List of actual keywords */ + + AhPrintOneField (24, 0, AH_MAX_ASL_LINE_LENGTH, Op->KeywordList); + printf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AhFindAslOperators (entry point for ASL operator search) + * + * PARAMETERS: Name - Name or prefix for an ASL operator. + * NULL means "find all" + * + * RETURN: None + * + * DESCRIPTION: Find all ASL operators that match the input Name or name + * prefix. + * + ******************************************************************************/ + +void +AhFindAslOperators ( + char *Name) +{ + const AH_ASL_OPERATOR *Operator; + BOOLEAN Found = FALSE; + + + AhStrupr (Name); + + /* Find/display all names that match the input name prefix */ + + for (Operator = AslOperatorInfo; Operator->Name; Operator++) + { + if (!Name) + { + AhDisplayAslOperator (Operator); + Found = TRUE; + continue; + } + + /* Upper case the operator name before substring compare */ + + strcpy (Gbl_Buffer, Operator->Name); + AhStrupr (Gbl_Buffer); + + if (strstr (Gbl_Buffer, Name) == Gbl_Buffer) + { + AhDisplayAslOperator (Operator); + Found = TRUE; + } + } + + if (!Found) + { + printf ("%s, no matching ASL operators\n", Name); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayAslOperator + * + * PARAMETERS: Op - Pointer to ASL operator with syntax info + * + * RETURN: None + * + * DESCRIPTION: Format and display syntax info for an ASL operator. Splits + * long lines appropriately for reading. + * + ******************************************************************************/ + +static void +AhDisplayAslOperator ( + const AH_ASL_OPERATOR *Op) +{ + + /* ASL operator name and description */ + + printf ("%16s: %s\n", Op->Name, Op->Description); + if (!Op->Syntax) + { + return; + } + + /* Syntax for the operator */ + + AhPrintOneField (18, 0, AH_MAX_ASL_LINE_LENGTH, Op->Syntax); + printf ("\n"); + + AhDisplayOperatorKeywords (Op); + printf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayOperatorKeywords + * + * PARAMETERS: Op - Pointer to ASL keyword with syntax info + * + * RETURN: None + * + * DESCRIPTION: Display any/all keywords that are associated with the ASL + * operator. + * + ******************************************************************************/ + +static void +AhDisplayOperatorKeywords ( + const AH_ASL_OPERATOR *Op) +{ + char *Token; + char *Separators = "(){}, "; + BOOLEAN FirstKeyword = TRUE; + + + if (!Op || !Op->Syntax) + { + return; + } + + /* + * Find all parameters that have the word "keyword" within, and then + * display the info about that keyword + */ + strcpy (Gbl_LineBuffer, Op->Syntax); + Token = strtok (Gbl_LineBuffer, Separators); + while (Token) + { + if (strstr (Token, "Keyword")) + { + if (FirstKeyword) + { + printf ("\n"); + FirstKeyword = FALSE; + } + + /* Found a keyword, display keyword information */ + + AhFindAslKeywords (Token); + } + + Token = strtok (NULL, Separators); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhPrintOneField + * + * PARAMETERS: Indent - Indent length for new line(s) + * CurrentPosition - Position on current line + * MaxPosition - Max allowed line length + * Field - Data to output + * + * RETURN: Line position after field is written + * + * DESCRIPTION: Split long lines appropriately for ease of reading. + * + ******************************************************************************/ + +static void +AhPrintOneField ( + UINT32 Indent, + UINT32 CurrentPosition, + UINT32 MaxPosition, + const char *Field) +{ + UINT32 Position; + UINT32 TokenLength; + const char *This; + const char *Next; + const char *Last; + + + This = Field; + Position = CurrentPosition; + + if (Position == 0) + { + printf ("%*s", (int) Indent, " "); + Position = Indent; + } + + Last = This + strlen (This); + while ((Next = strpbrk (This, " "))) + { + TokenLength = Next - This; + Position += TokenLength; + + /* Split long lines */ + + if (Position > MaxPosition) + { + printf ("\n%*s", (int) Indent, " "); + Position = TokenLength; + } + + printf ("%.*s ", (int) TokenLength, This); + This = Next + 1; + } + + /* Handle last token on the input line */ + + TokenLength = Last - This; + if (TokenLength > 0) + { + Position += TokenLength; + if (Position > MaxPosition) + { + printf ("\n%*s", (int) Indent, " "); + } + printf ("%s", This); + } +} + + +/******************************************************************************* + * + * FUNCTION: AhDisplayDeviceIds + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all PNP* and ACPI* device IDs defined in the ACPI spec. + * + ******************************************************************************/ + +static const AH_DEVICE_ID AhDeviceIds[] = +{ + {"PNP0A05", "Generic Container Device"}, + {"PNP0A06", "Generic Container Device"}, + {"PNP0C08", "ACPI core hardware"}, + {"PNP0C09", "Embedded Controller Device"}, + {"PNP0C0A", "Control Method Battery"}, + {"PNP0C0B", "Fan"}, + {"PNP0C0C", "Power Button Device"}, + {"PNP0C0D", "Lid Device"}, + {"PNP0C0E", "Sleep Button Device"}, + {"PNP0C0F", "PCI Interrupt Link Device"}, + {"PNP0C80", "Memory Device"}, + + {"ACPI0001", "SMBus 1.0 Host Controller"}, + {"ACPI0002", "Smart Battery Subsystem"}, + {"ACPI0003", "Power Source Device"}, + {"ACPI0004", "Module Device"}, + {"ACPI0005", "SMBus 2.0 Host Controller"}, + {"ACPI0006", "GPE Block Device"}, + {"ACPI0007", "Processor Device"}, + {"ACPI0008", "Ambient Light Sensor Device"}, + {"ACPI0009", "I/O xAPIC Device"}, + {"ACPI000A", "I/O APIC Device"}, + {"ACPI000B", "I/O SAPIC Device"}, + {"ACPI000C", "Processor Aggregator Device"}, + {"ACPI000D", "Power Meter Device"}, + {"ACPI000E", "Time/Alarm Device"}, + {"ACPI000F", "User Presence Detection Device"}, + + {NULL, NULL} +}; + +void +AhDisplayDeviceIds ( + void) +{ + const AH_DEVICE_ID *DeviceId = AhDeviceIds; + + + printf ("ACPI and PNP Device IDs defined in the ACPI specification:\n\n"); + while (DeviceId->Name) + { + printf ("%8s %s\n", DeviceId->Name, DeviceId->Description); + DeviceId++; + } +} diff --git a/source/tools/acpihelp/ahmain.c b/source/tools/acpihelp/ahmain.c new file mode 100644 index 000000000000..e45a0b61a4e5 --- /dev/null +++ b/source/tools/acpihelp/ahmain.c @@ -0,0 +1,229 @@ +/****************************************************************************** + * + * Module Name: ahmain - Main module for the acpi help utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + + +/* Local prototypes */ + +static void +AhDisplayUsage ( + void); + + +/****************************************************************************** + * + * FUNCTION: AhDisplayUsage + * + * DESCRIPTION: Usage message + * + ******************************************************************************/ + +static void +AhDisplayUsage ( + void) +{ + + ACPI_USAGE_HEADER ("acpihelp [NamePrefix | HexValue]"); + ACPI_OPTION ("-h", "Display help"); + ACPI_OPTION ("-i", "Display known ACPI Device IDs (_HID)"); + ACPI_OPTION ("-k [NamePrefix]", "Find/Display ASL non-operator keyword(s)"); + ACPI_OPTION ("-m [NamePrefix]", "Find/Display AML opcode name(s)"); + ACPI_OPTION ("-o [HexValue]", "Decode hex AML opcode"); + ACPI_OPTION ("-p [NamePrefix]", "Find/Display ASL predefined method name(s)"); + ACPI_OPTION ("-s [NamePrefix]", "Find/Display ASL operator name(s)"); + printf ("\nNamePrefix/HexValue not specified means \"Display All\"\n"); + printf ("\nDefault search with NamePrefix and no options:\n"); + printf (" Find ASL operator names - if NamePrefix does not start with underscore\n"); + printf (" Find ASL predefined method names - if NamePrefix starts with underscore\n"); +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * DESCRIPTION: C main function for AcpiHelp utility. + * + ******************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char *argv[]) +{ + char *Name; + UINT32 DecodeType; + int j; + + + printf (ACPI_COMMON_SIGNON ("ACPI Help Utility")); + DecodeType = AH_DECODE_DEFAULT; + + if (argc < 2) + { + AhDisplayUsage (); + return (0); + } + + /* Command line options */ + + while ((j = AcpiGetopt (argc, argv, "hikmops")) != EOF) switch (j) + { + case 'i': + DecodeType = AH_DISPLAY_DEVICE_IDS; + break; + + case 'k': + DecodeType = AH_DECODE_ASL_KEYWORD; + break; + + case 'm': + DecodeType = AH_DECODE_AML; + break; + + case 'o': + DecodeType = AH_DECODE_AML_OPCODE; + break; + + case 'p': + DecodeType = AH_DECODE_PREDEFINED_NAME; + break; + + case 's': + DecodeType = AH_DECODE_ASL; + break; + + case 'h': + default: + AhDisplayUsage (); + return (-1); + } + + /* Missing (null) name means "display all" */ + + Name = argv[AcpiGbl_Optind]; + + switch (DecodeType) + { + case AH_DECODE_AML: + AhFindAmlOpcode (Name); + break; + + case AH_DECODE_AML_OPCODE: + AhDecodeAmlOpcode (Name); + break; + + case AH_DECODE_PREDEFINED_NAME: + AhFindPredefinedNames (Name); + break; + + case AH_DECODE_ASL: + AhFindAslOperators (Name); + break; + + case AH_DECODE_ASL_KEYWORD: + AhFindAslKeywords (Name); + break; + + case AH_DISPLAY_DEVICE_IDS: + AhDisplayDeviceIds (); + break; + + default: + if (!Name) + { + AhFindAslOperators (Name); + break; + } + + if (*Name == '_') + { + AhFindPredefinedNames (Name); + } + else + { + AhFindAslOperators (Name); + } + break; + } + + return (0); +} + + +/******************************************************************************* + * + * FUNCTION: AhStrupr (strupr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void +AhStrupr ( + char *SrcString) +{ + char *String; + + + if (!SrcString) + { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) toupper ((int) *String); + } + + return; +} diff --git a/source/tools/acpihelp/ahpredef.c b/source/tools/acpihelp/ahpredef.c new file mode 100644 index 000000000000..2baf711ab8f5 --- /dev/null +++ b/source/tools/acpihelp/ahpredef.c @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * Module Name: ahpredef - Table of all known ACPI predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpihelp.h" + +/* + * Predefined ACPI names, with short description and return value. + * This table was extracted directly from the ACPI specification. + */ +const AH_PREDEFINED_NAME AslPredefinedInfo[] = +{ + {"_ACx", "Active Cooling", "Returns the active cooling policy threshold values"}, + {"_ADR", "Address", "Returns the address of a device on its parent bus"}, + {"_AEI", "ACPI Event Interrupts", "Returns a list of GPIO events to be used as ACPI events"}, + {"_ALC", "Ambient Light Chromaticity", "Returns the ambient light color chromaticity"}, + {"_ALI", "Ambient Light Illuminance", "Returns the ambient light brightness"}, + {"_ALN", "Alignment", "Base alignment, Resource Descriptor field"}, + {"_ALP", "Ambient Light Polling", "Returns the ambient light sensor polling frequency"}, + {"_ALR", "Ambient Light Response", "Returns the ambient light brightness to display brightness mappings"}, + {"_ALT", "Ambient Light Temperature", "Returns the ambient light color temperature"}, + {"_ALx", "Active List", "Returns a list of active cooling device objects"}, + {"_ART", "Active cooling Relationship Table", "Returns thermal relationship information between platform devices and fan devices"}, + {"_ASI", "Address Space Id", "Resource Descriptor field"}, + {"_ASZ", "Access Size", "Resource Descriptor field"}, + {"_ATT", "Type-Specific Attribute", "Resource Descriptor field"}, + {"_BAS", "Base Address", "Range base address, Resource Descriptor field"}, + {"_BBN", "Bios Bus Number", "Returns the PCI bus number returned by the BIOS"}, + {"_BCL", "Brightness Control Levels", "Returns a list of supported brightness control levels"}, + {"_BCM", "Brightness Control Method", "Sets the brightness level of the display device"}, + {"_BCT", "Battery Charge Time", "Returns time remaining to complete charging battery"}, + {"_BDN", "Bios Dock Name", "Returns the Dock ID returned by the BIOS"}, + {"_BFS", "Back From Sleep", "Inform AML of a wake event"}, + {"_BIF", "Battery Information", "Returns a Control Method Battery information block"}, + {"_BIX", "Battery Information Extended", "Returns a Control Method Battery extended information block"}, + {"_BLT", "Battery Level Threshold", "Set battery level threshold preferences"}, + {"_BM_", "Bus Master", "Resource Descriptor field"}, + {"_BMA", "Battery Measurement Averaging Interval", "Sets battery measurement averaging interval"}, + {"_BMC", "Battery Maintenance Control", "Sets battery maintenance and control features"}, + {"_BMD", "Battery Maintenance Data", "Returns battery maintenance, control, and state data"}, + {"_BMS", "Battery Measurement Sampling Time", "Sets the battery measurement sampling time"}, + {"_BQC", "Brightness Query Current", "Returns the current display brightness level"}, + {"_BST", "Battery Status", "Returns a Control Method Battery status block"}, + {"_BTM", "Battery Time", "Returns the battery runtime"}, + {"_BTP", "Battery Trip Point", "Sets a Control Method Battery trip point"}, + {"_CBA", "Configuration Base Address", "Sets the CBA for a PCI Express host bridge"}, + {"_CDM", "Clock Domain", "Returns a logical processor's clock domain identifier"}, + {"_CID", "Compatible ID", "Returns a device's Plug and Play Compatible ID list"}, + {"_CLS", "Class Code", "Returns PCI class code and subclass"}, + {"_CPC", "Continuous Performance Control", "Returns a list of performance control interfaces"}, + {"_CRS", "Current Resource Settings", "Returns the current resource settings for a device"}, + {"_CRT", "Critical Temperature", "Returns the shutdown critical temperature"}, + {"_CSD", "C State Dependencies", "Returns a list of C-state dependencies"}, + {"_CST", "C States", "Returns a list of supported C-states"}, + {"_CWS", "Clear Wake Alarm Status", "Clear the status of wake alarms"}, + {"_DBT", "Debounce Timeout", "Timeout value, Resource Descriptor field"}, + {"_DCK", "Dock", "Sets docking isolation. Presence indicates device is a docking station"}, + {"_DCS", "Display Current Status", "Returns status of the display output device"}, + {"_DDC", "Display Data Current", "Returns the EDID for the display output device"}, + {"_DDN", "Dos Device Name", "Returns a device logical name"}, + {"_DEC", "Decode", "Device decoding type, Resource Descriptor field"}, + {"_DEP", "Dependencies", "Returns a list of operation region dependencies"}, + {"_DGS", "Display Graphics State", "Return the current state of the output device"}, + {"_DIS", "Disable", "Disables a device"}, + {"_DLM", "Device Lock Mutex", "Defines mutex for OS/AML sharing"}, + {"_DMA", "Direct Memory Access", "Returns a device's current resources for DMA transactions"}, + {"_DOD", "Display Output Devices", "Enumerate all devices attached to the display adapter"}, + {"_DOS", "Disable Output Switching", "Sets the display output switching mode"}, + {"_DPL", "Device Selection Polarity", "Polarity of Device Selection signal, Resource Descriptor field"}, + {"_DRS", "Drive Strength", "Drive Strength setting for GPIO connection, Resource Descriptor field"}, + {"_DSM", "Device Specific Method", "Executes device-specific functions"}, + {"_DSS", "Device Set State", "Sets the display device state"}, + {"_DSW", "Device Sleep Wake", "Sets the sleep and wake transition states for a device"}, + {"_DTI", "Device Temperature Indication", "Conveys native device temperature to the platform"}, + {"_Exx", "Edge GPE", "Method executed as a result of a general-purpose event"}, + {"_EC_", "Embedded Controller", "returns EC offset and query information"}, + {"_EDL", "Eject Device List", "Returns a list of devices that are dependent on a device (docking)"}, + {"_EJD", "Ejection Dependent Device", "Returns the name of dependent (parent) device (docking)"}, + {"_EJx", "Eject", "Begin or cancel a device ejection request (docking)"}, + {"_END", "Endian-ness", "Endian orientation, Resource Descriptor field"}, + {"_EVT", "Event", "Event method for GPIO events"}, + {"_FDE", "Floppy Disk Enumerate", "Returns floppy disk configuration information"}, + {"_FDI", "Floppy Drive Information", "Returns a floppy drive information block"}, + {"_FDM", "Floppy Drive Mode", "Sets a floppy drive speed"}, + {"_FIF", "Fan Information", "Returns fan device information"}, + {"_FIX", "Fixed Register Resource Provider", "Returns a list of devices that implement FADT register blocks"}, + {"_FLC", "Flow Control", "Flow control, Resource Descriptor field"}, + {"_FPS", "Fan Performance States", "Returns a list of supported fan performance states"}, + {"_FSL", "Fan Set Level", "Control method that sets the fan device's speed level (performance state)"}, + {"_FST", "Fan Status", "Returns current status information for a fan device"}, + {"_GAI", "Get Averaging Interval", "Returns the power meter averaging interval"}, + {"_GCP", "Get Capability", "Get device time capabilities"}, + {"_GHL", "Get Hardware Limit", "Returns the hardware limit enforced by the power meter"}, + {"_GL_", "Global Lock", "OS-defined Global Lock mutex object"}, + {"_GLK", "Global Lock", "Returns a device's Global Lock requirement for device access"}, + {"_GPD", "Get Post Data", "Returns the value of the VGA device that will be posted at boot"}, + {"_GPE", "General Purpose Events", "(1) predefined Scope (\\_GPE.)"}, + {"_GRA", "Granularity", "Address space granularity, Resource Descriptor field"}, + {"_GSB", "Global System Interrupt Base", "Returns the GSB for a I/O APIC device"}, + {"_GRT", "Get Real Time", "Returns current time-of-day"}, + {"_GTF", "Get Task File", "Returns a list of ATA commands to restore a drive to default state"}, + {"_GTM", "Get Timing Mode", "Returns a list of IDE controller timing information"}, + {"_GTS", "Going To Sleep", "Inform AML of pending sleep"}, + {"_GWS", "Get Wake Status", "Return status of wake alarms"}, + {"_HE_", "High-Edge", "Interrupt triggering, Resource Descriptor field"}, + {"_HID", "Hardware ID", "Returns a device's Plug and Play Hardware ID"}, + {"_HOT", "Hot Temperature", "Returns the critical temperature for sleep (entry to S4)"}, + {"_HPP", "Hot Plug Parameters", "Returns a list of hot-plug information for a PCI device"}, + {"_HPX", "Hot Plug Parameter Extensions", "Returns a list of hot-plug information for a PCI device. Supersedes _HPP"}, + {"_HRV", "Hardware Revision", "Returns a hardware revision value"}, + {"_IFT", "IPMI Interface Type", "See the Intelligent Platform Management Interface Specification"}, + {"_INI", "Initialize", "Performs device specific initialization"}, + {"_INT", "Interrupts", "Interrupt mask bits, Resource Descriptor field"}, + {"_IOR", "I/O Restriction", "Restriction type, Resource Descriptor field"}, + {"_IRC", "Inrush Current", "Presence indicates that a device has a significant inrush current draw"}, + {"_Lxx", "Level GPE", "Control method executed as a result of a general-purpose event"}, + {"_LCK", "Lock", "Locks or unlocks a device (docking)"}, + {"_LEN", "Length", "Range length, Resource Descriptor field"}, + {"_LID", "Lid", "Returns the open/closed status of the lid on a mobile system"}, + {"_LIN", "Lines In Use", "Handshake lines, Resource Descriptor field"}, + {"_LL_", "Low Level", "Interrupt polarity, Resource Descriptor field"}, + {"_MAF", "Maximum Address Fixed", "Resource Descriptor field"}, + {"_MAT", "Multiple Apic Table Entry", "Returns a list of MADT APIC structure entries"}, + {"_MAX", "Maximum Base Address", "Resource Descriptor field"}, + {"_MBM", "Memory Bandwidth Monitoring Data", "Returns bandwidth monitoring data for a memory device"}, + {"_MEM", "Memory Attributes", "Resource Descriptor field"}, + {"_MIF", "Minimum Address Fixed", "Resource Descriptor field"}, + {"_MIN", "Minimum Base Address", "Resource Descriptor field"}, + {"_MLS", "Multiple Language String", "Returns a device description in multiple languages"}, + {"_MOD", "Mode", "Interrupt mode, Resource Descriptor field"}, + {"_MSG", "Message", "Sets the system message waiting status indicator"}, + {"_MSM", "Memory Set Monitoring", "Sets bandwidth monitoring parameters for a memory device"}, + {"_MTP", "Memory Type", "Resource Descriptor field"}, + {"_NTT", "Notification Temperature Threshold", "Returns a threshold for device temperature change that requires platform notification"}, + {"_OFF", "Off", "Sets a power resource to the off state"}, + {"_ON_", "On", "Sets a power resource to the on state"}, + {"_OS_", "Operating System", "Returns a string that identifies the operating system"}, + {"_OSC", "Operating System Capabilities", "Inform AML of host features and capabilities"}, + {"_OSI", "Operating System Interfaces", "Returns supported interfaces, behaviors, and features"}, + {"_OST", "Ospm Status Indication", "Inform AML of event processing status"}, + {"_PAI", "Power Averaging Interval", "Sets the averaging interval for a power meter"}, + {"_PAR", "Parity", "Parity bits, Resource Descriptor field"}, + {"_PCL", "Power Consumer List", "Returns a list of devices powered by a power source"}, + {"_PCT", "Performance Control", "Returns processor performance control and status registers"}, + {"_PDC", "Processor Driver Capabilities", "Inform AML of processor driver capabilities"}, + {"_PDL", "P-state Depth Limit", "Returns the lowest available performance P-state"}, + {"_PHA", "Phase", "Clock phase, Resource Descriptor field"}, + {"_PIC", "PIC", "Inform AML of the interrupt model in use"}, + {"_PIF", "Power Source Information", "Returns a Power Source information block"}, + {"_PIN", "Pins", "Pin list, Resource Descriptor field"}, + {"_PLD", "Physical Device Location", "Returns a device's physical location information"}, + {"_PMC", "Power Meter Capabilities", "Returns a list of Power Meter capabilities info"}, + {"_PMD", "Power Metered Devices", "Returns a list of devices that are measured by the power meter device"}, + {"_PMM", "Power Meter Measurement", "Returns the current value of the Power Meter"}, + {"_POL", "Polarity", "Interrupt polarity, Resource Descriptor field"}, + {"_PPC", "Performance Present Capabilites", "Returns a list of the performance states currently supported by the platform"}, + {"_PPE", "Polling for Platform Error", "Returns the polling interval to retrieve Corrected Platform Error information"}, + {"_PPI", "Pin Configuration", "Resource Descriptor field"}, + {"_PR", "Processor", "Predefined scope for processor objects"}, + {"_PR0", "Power Resources for D0", "Returns a list of dependent power resources to enter state D0 (fully on)"}, + {"_PR1", "Power Resources for D1", "Returns a list of dependent power resources to enter state D1"}, + {"_PR2", "Power Resources for D2", "Returns a list of dependent power resources to enter state D2"}, + {"_PR3", "Power Resources for D3hot", "Returns a list of dependent power resources to enter state D3hot"}, + {"_PRE", "Power Resources for Enumeration", "Returns a list of dependent power resources to enumerate devices on a bus"}, + {"_PRL", "Power Source Redundancy List", "Returns a list of power source devices in the same redundancy grouping"}, + {"_PRS", "Possible Resource Settings", "Returns a list of a device's possible resource settings"}, + {"_PRT", "Pci Routing Table", "Returns a list of PCI interrupt mappings"}, + {"_PRW", "Power Resources for Wake", "Returns a list of dependent power resources for waking"}, + {"_PS0", "Power State 0", "Sets a device's power state to D0 (device fully on)"}, + {"_PS1", "Power State 1", "Sets a device's power state to D1"}, + {"_PS2", "Power State 2", "Sets a device's power state to D2"}, + {"_PS3", "Power State 3", "Sets a device's power state to D3 (device off)"}, + {"_PSC", "Power State Current", "Returns a device's current power state"}, + {"_PSD", "Processor State Dependencies", "Returns processor P-State dependencies"}, + {"_PSE", "Power State for Enumeration", "Put a bus into enumeration power mode"}, + {"_PSL", "Passive List", "Returns a list of passive cooling device objects"}, + {"_PSR", "Power Source", "Returns the power source device currently in use"}, + {"_PSS", "Performance Supported States", "Returns a list of supported processor performance states"}, + {"_PSV", "Passive", "Returns the passive trip point temperature"}, + {"_PSW", "Power State Wake", "Sets a device's wake function"}, + {"_PTC", "Processor Throttling Control", "Returns throttling control and status registers"}, + {"_PTP", "Power Trip Points", "Sets trip points for the Power Meter device"}, + {"_PTS", "Prepare To Sleep", "Inform the platform of an impending sleep transition"}, + {"_PUR", "Processor Utilization Request", "Returns the number of processors that the platform would like to idle"}, + {"_PXM", "Proximity", "Returns a device's proximity domain identifier"}, + {"_Qxx", "Query", "Embedded Controller query and SMBus Alarm control method"}, + {"_RBO", "Register Bit Offset", "Resource Descriptor field"}, + {"_RBW", "Register Bit Width", "Resource Descriptor field"}, + {"_REG", "Region", "Inform AML code of an operation region availability change"}, + {"_REV", "Revision", "Returns the revision of the ACPI specification that is implemented"}, + {"_RMV", "Remove", "Returns a device's removal ability status (docking)"}, + {"_RNG", "Range", "Memory range type, Resource Descriptor field"}, + {"_ROM", "Read-Only Memory", "Returns a copy of the ROM data for a display device"}, + {"_RT_", "Resource Type", "Resource Descriptor field"}, + {"_RTV", "Relative Temperature Values", "Returns temperature value information"}, + {"_RW_", "Read-Write Status", "Resource Descriptor field"}, + {"_RXL", "Receive Buffer Size", "Serial channel buffer, Resource Descriptor field"}, + {"_S0_", "S0 System State", "Returns values to enter the system into the S0 state"}, + {"_S1_", "S1 System State", "Returns values to enter the system into the S1 state"}, + {"_S2_", "S2 System State", "Returns values to enter the system into the S2 state"}, + {"_S3_", "S3 System State", "Returns values to enter the system into the S3 state"}, + {"_S4_", "S4 System State", "Returns values to enter the system into the S4 state"}, + {"_S5_", "S5 System State", "Returns values to enter the system into the S5 state"}, + {"_S1D", "S1 Device State", "Returns the highest D-state supported by a device when in the S1 state"}, + {"_S2D", "S2 Device State", "Returns the highest D-state supported by a device when in the S2 state"}, + {"_S3D", "S3 Device State", "Returns the highest D-state supported by a device when in the S3 state"}, + {"_S4D", "S4 Device State", "Returns the highest D-state supported by a device when in the S4 state"}, + {"_S0W", "S0 Device Wake State", "Returns the lowest D-state that the device can wake itself from S0"}, + {"_S1W", "S1 Device Wake State", "Returns the lowest D-state for this device that can wake the system from S1"}, + {"_S2W", "S2 Device Wake State", "Returns the lowest D-state for this device that can wake the system from S2"}, + {"_S3W", "S3 Device Wake State", "Returns the lowest D-state for this device that can wake the system from S3"}, + {"_S4W", "S4 Device Wake State", "Returns the lowest D-state for this device that can wake the system from S4"}, + {"_SB_", "System Bus", "Scope for device and bus objects"}, + {"_SBS", "Smart Battery Subsystem", "Returns the subsystem configuration"}, + {"_SCP", "Set Cooling Policy", "Sets the cooling policy (active or passive)"}, + {"_SDD", "Set Device Data", "Sets data for a SATA device"}, + {"_SEG", "Segment", "Returns a device's PCI Segment Group number"}, + {"_SHL", "Set Hardware Limit", "Sets the hardware limit enforced by the Power Meter"}, + {"_SHR", "Sharable", "Interrupt share status, Resource Descriptor field"}, + {"_SI_", "System Indicators", "Predefined scope"}, + {"_SIZ", "Size", "DMA transfer size, Resource Descriptor field"}, + {"_SLI", "System Locality Information", "Returns a list of NUMA system localities"}, + {"_SLV", "Slave Mode", "Mode setting, Resource Descriptor field"}, + {"_SPD", "Set Post Device", "Sets which video device will be posted at boot"}, + {"_SPE", "Speed", "Connection speed, Resource Descriptor field"}, + {"_SRS", "Set Resource Settings", "Sets a device's resource allocation"}, + {"_SRT", "Set Real Time", "Interrupt triggering, Resource Descriptor field"}, + {"_SRV", "IPMI Spec Revision", "See the Intelligent Platform Management Interface Specification"}, + {"_SST", "System Status", "Sets the system status indicator"}, + {"_STA", "Status", " (1) returns the current status of a device"}, + {"_STB", "Stop Bits", "Serial channel stop bits, Resource Descriptor field"}, + {"_STM", "Set Timing Mode", "Sets an IDE controller transfer timings"}, + {"_STP", "Set Expired Timer Wake Policy", "Sets expired timer policies of the wake alarm device"}, + {"_STR", "String", "Returns a device's description string"}, + {"_STV", "Set Timer Value", "Set timer values of the wake alarm device"}, + {"_SUB", "Subsystem ID", "Returns the subsystem ID for a device"}, + {"_SUN", "Slot User Number", "Returns the slot unique ID number"}, + {"_SWS", "System Wake Source", "Returns the source event that caused the system to wake"}, + {"_T_x", "Temporary", "Reserved for use by ASL compilers"}, + {"_TC1", "Thermal Constant 1", "Returns TC1 for the passive cooling formula"}, + {"_TC2", "Thermal Constant 2", "Returns TC2 for the passive cooling formula"}, + {"_TDL", "T-State Depth Limit", "Returns the _TSS entry number of the lowest power throttling state"}, + {"_TIP", "Expired Timer Wake Policy", "Returns timer policies of the wake alarm device"}, + {"_TIV", "Timer Values", "Returns remaining time of the wake alarm device"}, + {"_TMP", "Temperature", "Returns a thermal zone's current temperature"}, + {"_TPC", "Throttling Present Capabilities", "Returns the current number of supported throttling states"}, + {"_TPT", "Trip Point Temperature", "Inform AML that a device's embedded temperature sensor has crossed a temperature trip point"}, + {"_TRA", "Translation", "Address translation offset, Resource Descriptor field"}, + {"_TRS", "Translation Sparse", "Sparse/dense flag, Resource Descriptor field"}, + {"_TRT", "Thermal Relationship Table", "Returns thermal relationships between platform devices"}, + {"_TSD", "Throttling State Dependencies", "Returns a list of T-state dependencies"}, + {"_TSF", "Type-Specific Flags", "Resource Descriptor field"}, + {"_TSP", "Thermal Sampling Period", "Returns the thermal sampling period for passive cooling"}, + {"_TSS", "Throttling Supported States", "Returns supported throttling state information"}, + {"_TST", "Temperature Sensor Threshold", "Returns the minimum separation for a device's temperature trip points"}, + {"_TTP", "Translation Type", "Translation/static flag, Resource Descriptor field"}, + {"_TTS", "Transition To State", "Inform AML of an S-state transition"}, + {"_TXL", "Transmit Buffer Size", "Serial Channel buffer, Resource Descriptor field"}, + {"_TYP", "Type", "DMA channel type (speed), Resource Descriptor field"}, + {"_TZ_", "Thermal Zone", "Predefined scope: ACPI 1.0"}, + {"_TZD", "Thermal Zone Devices", "Returns a list of device names associated with a Thermal Zone"}, + {"_TZM", "Thermal Zone Member", "Returns a reference to the thermal zone of which a device is a member"}, + {"_TZP", "Thermal Zone Polling", "Returns a Thermal zone's polling frequency"}, + {"_UID", "Unique ID", "Return a device's unique persistent ID"}, + {"_UPC", "USB Port Capabilities", "Returns a list of USB port capabilities"}, + {"_UPD", "User Presence Detect", "Returns user detection information"}, + {"_UPP", "User Presence Polling", "Returns the recommended user presence polling interval"}, + {"_VEN", "Vendor Data", "Resource Descriptor field"}, + {"_VPO", "Video Post Options", "Returns the implemented video post options"}, + {"_WAK", "Wake", "Inform AML that the system has just awakened"}, + {"_Wxx", "Wake Event", "Method executed as a result of a wake event"}, + {NULL, NULL, NULL} +}; diff --git a/source/tools/acpinames/Makefile b/source/tools/acpinames/Makefile new file mode 100644 index 000000000000..bdd2d260c494 --- /dev/null +++ b/source/tools/acpinames/Makefile @@ -0,0 +1,189 @@ +# +# acpinames - Load ACPI table and dump namespace. This is a subset +# of the AcpiExec functionality, it is intended to demonstrate +# the configurability of ACPICA. +# +# NOTE: This makefile is intended to be used in the Linux environment, +# with the Linux directory structure. It will not work directly +# on the native ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpinames + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPINAMES = $(ACPICA_TOOLS)/acpinames +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ACPINAMES) \ + $(ACPICA_DEBUGGER) \ + $(ACPICA_DISPATCHER) \ + $(ACPICA_EXECUTER) \ + $(ACPICA_NAMESPACE) \ + $(ACPICA_PARSER) \ + $(ACPICA_TABLES) \ + $(ACPICA_UTILITIES) \ + $(ACPICA_COMMON) \ + $(ACPICA_OSL) + +HEADERS = \ + $(wildcard $(ACPINAMES)/*.h) + +OBJECTS = \ + anmain.o \ + anstubs.o \ + antables.o \ + dbfileio.o \ + dsfield.o \ + dsmthdat.o \ + dsobject.o \ + dsutils.o \ + dswload.o \ + dswload2.o \ + dswscope.o \ + dswstate.o \ + excreate.o \ + exnames.o \ + exresnte.o \ + exresolv.o \ + exutils.o \ + getopt.o \ + nsaccess.o \ + nsalloc.o \ + nsdump.o \ + nsinit.o \ + nsload.o \ + nsnames.o \ + nsobject.o \ + nsparse.o \ + nssearch.o \ + nsutils.o \ + nswalk.o \ + nsxfeval.o \ + nsxfname.o \ + nsxfobj.o \ + osunixxf.o \ + psargs.o \ + psloop.o \ + psopcode.o \ + psparse.o \ + psscope.o \ + pstree.o \ + psutils.o \ + pswalk.o \ + psxface.o \ + tbfadt.o \ + tbfind.o \ + tbinstal.o \ + tbutils.o \ + tbxface.o \ + tbxfroot.o \ + utaddress.o \ + utalloc.o \ + utcache.o \ + utdebug.o \ + utdecode.o \ + utdelete.o \ + utglobal.o \ + utlock.o \ + utmath.o \ + utmisc.o \ + utmutex.o \ + utobject.o \ + utstate.o \ + utosi.o \ + utxferror.o \ + utxface.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_NAMES_APP \ + -I$(ACPICA_INCLUDE) \ + -I$(ACPINAMES) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + $(COPYPROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpinames/acpinames.h b/source/tools/acpinames/acpinames.h new file mode 100644 index 000000000000..260124af8ee6 --- /dev/null +++ b/source/tools/acpinames/acpinames.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Module Name: acpinames.h - Common include for AcpiNames utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACPINAMES_H +#define _ACPINAMES_H + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" +#include "../acpiexec/aecommon.h" + +#include + +#define ACPI_MAX_INIT_TABLES (32) + +#endif + diff --git a/source/tools/acpinames/anmain.c b/source/tools/acpinames/anmain.c new file mode 100644 index 000000000000..682cc5f61570 --- /dev/null +++ b/source/tools/acpinames/anmain.c @@ -0,0 +1,275 @@ +/****************************************************************************** + * + * Module Name: anmain - Main routine for the AcpiNames utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpinames.h" + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("anmain") + + +extern ACPI_TABLE_DESC Tables[]; + +FILE *AcpiGbl_DebugFile; +static AE_TABLE_DESC *AeTableListHead = NULL; + + +#define AE_SUPPORTED_OPTIONS "?h" + + +/****************************************************************************** + * + * FUNCTION: usage + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print a usage message + * + *****************************************************************************/ + +static void +usage ( + void) +{ + + ACPI_USAGE_HEADER ("AcpiNames [options] AMLfile"); + ACPI_OPTION ("-?", "Display this message"); +} + + +/****************************************************************************** + * + * FUNCTION: NsDumpEntireNamespace + * + * PARAMETERS: AmlFilename - Filename for DSDT or SSDT AML table + * + * RETURN: Status (pass/fail) + * + * DESCRIPTION: Build an ACPI namespace for the input AML table, and dump the + * formatted namespace contents. + * + *****************************************************************************/ + +static int +NsDumpEntireNamespace ( + char *AmlFilename) +{ + ACPI_STATUS Status; + ACPI_TABLE_HEADER *Table = NULL; + UINT32 TableCount = 0; + AE_TABLE_DESC *TableDesc; + ACPI_HANDLE Handle; + + + /* Open the binary AML file and read the entire table */ + + Status = AcpiDbReadTableFromFile (AmlFilename, &Table); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not get input table %s, %s\n", AmlFilename, + AcpiFormatException (Status)); + return (-1); + } + + /* Table must be a DSDT. SSDTs are not currently supported */ + + if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT)) + { + printf ("**** Input table signature is [%4.4s], must be [DSDT]\n", + Table->Signature); + return (-1); + } + + /* + * Allocate and link a table descriptor (allows for future expansion to + * multiple input files) + */ + TableDesc = AcpiOsAllocate (sizeof (AE_TABLE_DESC)); + TableDesc->Table = Table; + TableDesc->Next = AeTableListHead; + AeTableListHead = TableDesc; + + TableCount++; + + /* + * Build a local XSDT with all tables. Normally, here is where the + * RSDP search is performed to find the ACPI tables + */ + Status = AeBuildLocalTables (TableCount, AeTableListHead); + if (ACPI_FAILURE (Status)) + { + return (-1); + } + + /* Initialize table manager, get XSDT */ + + Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not initialize ACPI table manager, %s\n", + AcpiFormatException (Status)); + return (-1); + } + + /* Reallocate root table to dynamic memory */ + + Status = AcpiReallocateRootTable (); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not reallocate root table, %s\n", + AcpiFormatException (Status)); + return (-1); + } + + /* Load the ACPI namespace */ + + Status = AcpiLoadTables (); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not load ACPI tables, %s\n", + AcpiFormatException (Status)); + return (-1); + } + + /* + * Enable ACPICA. These calls don't do much for this + * utility, since we only dump the namespace. There is no + * hardware or event manager code underneath. + */ + Status = AcpiEnableSubsystem ( + ACPI_NO_ACPI_ENABLE | + ACPI_NO_ADDRESS_SPACE_INIT | + ACPI_NO_EVENT_INIT | + ACPI_NO_HANDLER_INIT); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not EnableSubsystem, %s\n", + AcpiFormatException (Status)); + return (-1); + } + + Status = AcpiInitializeObjects ( + ACPI_NO_ADDRESS_SPACE_INIT | + ACPI_NO_DEVICE_INIT | + ACPI_NO_EVENT_INIT); + if (ACPI_FAILURE (Status)) + { + printf ("**** Could not InitializeObjects, %s\n", + AcpiFormatException (Status)); + return (-1); + } + + /* + * Perform a namespace walk to dump the contents + */ + AcpiOsPrintf ("\nACPI Namespace:\n"); + + AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, ACPI_UINT32_MAX, + ACPI_OWNER_ID_MAX, AcpiGbl_RootNode); + + + /* Example: get a handle to the _GPE scope */ + + Status = AcpiGetHandle (NULL, "\\_GPE", &Handle); + AE_CHECK_OK (AcpiGetHandle, Status); + + return (0); +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * PARAMETERS: argc, argv + * + * RETURN: Status (pass/fail) + * + * DESCRIPTION: Main routine for NsDump utility + * + *****************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char **argv) +{ + ACPI_STATUS Status; + int j; + + + printf (ACPI_COMMON_SIGNON ("ACPI Namespace Dump Utility")); + + if (argc < 2) + { + usage (); + return (0); + } + + /* Init globals and ACPICA */ + + AcpiDbgLevel = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; + AcpiDbgLayer = 0xFFFFFFFF; + + Status = AcpiInitializeSubsystem (); + AE_CHECK_OK (AcpiInitializeSubsystem, Status); + + /* Get the command line options */ + + while ((j = AcpiGetopt (argc, argv, AE_SUPPORTED_OPTIONS)) != EOF) switch(j) + { + case '?': + case 'h': + default: + usage(); + return (0); + } + + /* + * The next argument is the filename for the DSDT or SSDT. + * Open the file, build namespace and dump it. + */ + return (NsDumpEntireNamespace (argv[AcpiGbl_Optind])); +} + diff --git a/source/tools/acpinames/anstubs.c b/source/tools/acpinames/anstubs.c new file mode 100644 index 000000000000..a69c425e3776 --- /dev/null +++ b/source/tools/acpinames/anstubs.c @@ -0,0 +1,441 @@ +/****************************************************************************** + * + * Module Name: anstubs - Stub routines for the AcpiNames utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpinames.h" + +#include +#include +#include + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("anstubs") + + +/****************************************************************************** + * + * DESCRIPTION: Stubs used to facilitate linkage of the NsDump utility. + * + *****************************************************************************/ + + +/* Utilities */ + +void +AcpiUtSubsystemShutdown ( + void) +{ +} + +ACPI_STATUS +AcpiUtExecute_STA ( + ACPI_NAMESPACE_NODE *DeviceNode, + UINT32 *StatusFlags) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtExecute_HID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtExecute_CID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID_LIST **ReturnCidList) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtExecute_UID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtExecutePowerMethods ( + ACPI_NAMESPACE_NODE *DeviceNode, + const char **MethodNames, + UINT8 MethodCount, + UINT8 *OutValues) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtEvaluateNumericObject ( + char *ObjectName, + ACPI_NAMESPACE_NODE *DeviceNode, + UINT64 *Value) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtCopyIobjectToEobject ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_BUFFER *RetBuffer) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtCopyEobjectToIobject ( + ACPI_OBJECT *Obj, + ACPI_OPERAND_OBJECT **InternalObj) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiUtCopyIobjectToIobject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **DestDesc, + ACPI_WALK_STATE *WalkState) +{ + return (AE_NOT_IMPLEMENTED); +} + + +/* Hardware manager */ + +UINT32 +AcpiHwGetMode ( + void) +{ + return (0); +} + + +/* Event manager */ + +ACPI_STATUS +AcpiEvInstallXruptHandlers ( + void) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvInitializeEvents ( + void) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvInstallRegionHandlers ( + void) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvInitializeOpRegions ( + void) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEvInitializeRegion ( + ACPI_OPERAND_OBJECT *RegionObj, + BOOLEAN AcpiNsLocked) +{ + return (AE_OK); +} + +#if (!ACPI_REDUCED_HARDWARE) +ACPI_STATUS +AcpiEvDeleteGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiEnable ( + void) +{ + return (AE_OK); +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/* AML Interpreter */ + +void +AcpiExUnlinkMutex ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ +} + +void +AcpiExReleaseAllMutexes ( + ACPI_THREAD_STATE *Thread) +{ +} + +ACPI_STATUS +AcpiExReadDataFromField ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **RetBufferDesc) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiExWriteDataToField ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiExPrepFieldValue ( + ACPI_CREATE_FIELD_INFO *Info) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiExAcquireMutexObject ( + UINT16 Timeout, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_THREAD_ID ThreadId) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiExReleaseMutexObject ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiExStoreObjectToNode ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node, + ACPI_WALK_STATE *WalkState, + UINT8 ImplicitConversion) +{ + return (AE_NOT_IMPLEMENTED); +} + + +/* Namespace manager */ + +ACPI_STATUS +AcpiNsEvaluate ( + ACPI_EVALUATE_INFO *Info) +{ + return (AE_NOT_IMPLEMENTED); +} + +void +AcpiNsExecModuleCodeList ( + void) +{ +} + + +/* Dispatcher */ + +ACPI_STATUS +AcpiDsInitializeObjects ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsCallControlMethod ( + ACPI_THREAD_STATE *Thread, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsRestartControlMethod ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ReturnDesc) +{ + return (AE_NOT_IMPLEMENTED); +} + +void +AcpiDsTerminateControlMethod ( + ACPI_OPERAND_OBJECT *MethodDesc, + ACPI_WALK_STATE *WalkState) +{ +} + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsBeginMethodExecution ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsGetPredicateValue ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ResultObj) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsGetBufferFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsGetBankFieldArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsGetRegionArguments ( + ACPI_OPERAND_OBJECT *RgnDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsGetBufferArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsGetPackageArguments ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiDsExecBeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp) +{ + return (AE_NOT_IMPLEMENTED); +} + +ACPI_STATUS +AcpiDsExecEndOp ( + ACPI_WALK_STATE *State) +{ + return (AE_NOT_IMPLEMENTED); +} + + +/* AML Debugger */ + +void +AcpiDbDisplayArgumentObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ +} + +ACPI_STATUS +AcpiDbInitialize ( + void) +{ + return (AE_OK); +} + +void +AcpiDbTerminate ( + void) +{ +} + +/* OSL interfaces */ + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (0xFFFF); +} + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + return (AE_SUPPORT); +} diff --git a/source/tools/acpinames/antables.c b/source/tools/acpinames/antables.c new file mode 100644 index 000000000000..37fa24ae5f9f --- /dev/null +++ b/source/tools/acpinames/antables.c @@ -0,0 +1,304 @@ +/****************************************************************************** + * + * Module Name: antables - ACPI table setup/install for AcpiNames utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpinames.h" + +#define _COMPONENT ACPI_TOOLS + ACPI_MODULE_NAME ("antables") + +/* Local prototypes */ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void); + +/* Non-AML tables that are constructed locally and installed */ + +static ACPI_TABLE_RSDP LocalRSDP; +static ACPI_TABLE_FACS LocalFACS; + +/* + * We need a local FADT so that the hardware subcomponent will function, + * even though the underlying OSD HW access functions don't do anything. + */ +static ACPI_TABLE_FADT LocalFADT; + +/* + * Use XSDT so that both 32- and 64-bit versions of this utility will + * function automatically. + */ +static ACPI_TABLE_XSDT *LocalXSDT; + +#define BASE_XSDT_TABLES 1 +#define BASE_XSDT_SIZE (sizeof (ACPI_TABLE_XSDT) + \ + ((BASE_XSDT_TABLES -1) * sizeof (UINT64))) + +ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES]; + + +/****************************************************************************** + * + * FUNCTION: AeBuildLocalTables + * + * PARAMETERS: TableCount - Number of tables on the command line + * TableList - List of actual tables from files + * + * RETURN: Status + * + * DESCRIPTION: Build a complete ACPI table chain, with a local RSDP, XSDT, + * FADT, FACS, and the input DSDT/SSDT. + * + *****************************************************************************/ + +ACPI_STATUS +AeBuildLocalTables ( + UINT32 TableCount, + AE_TABLE_DESC *TableList) +{ + ACPI_PHYSICAL_ADDRESS DsdtAddress = 0; + UINT32 XsdtSize; + AE_TABLE_DESC *NextTable; + UINT32 NextIndex; + ACPI_TABLE_FADT *ExternalFadt = NULL; + + + /* + * Update the table count. For DSDT, it is not put into the XSDT. For + * FADT, this is already accounted for since we usually install a + * local FADT. + */ + NextTable = TableList; + while (NextTable) + { + if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) + { + TableCount--; + } + NextTable = NextTable->Next; + } + + XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64)); + + /* Build an XSDT */ + + LocalXSDT = AcpiOsAllocate (XsdtSize); + if (!LocalXSDT) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET (LocalXSDT, 0, XsdtSize); + ACPI_STRNCPY (LocalXSDT->Header.Signature, ACPI_SIG_XSDT, 4); + LocalXSDT->Header.Length = XsdtSize; + LocalXSDT->Header.Revision = 1; + + LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT); + + /* + * Install the user tables. The DSDT must be installed in the FADT. + * All other tables are installed directly into the XSDT. + */ + NextIndex = BASE_XSDT_TABLES; + NextTable = TableList; + while (NextTable) + { + /* + * Incoming DSDT or FADT are special cases. All other tables are + * just immediately installed into the XSDT. + */ + if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT)) + { + if (DsdtAddress) + { + printf ("Already found a DSDT, only one allowed\n"); + return (AE_ALREADY_EXISTS); + } + + /* The incoming user table is a DSDT */ + + DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table); + } + else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) + { + ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table); + LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); + } + else + { + /* Install the table in the XSDT */ + + LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); + NextIndex++; + } + + NextTable = NextTable->Next; + } + + /* Build an RSDP */ + + ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP)); + ACPI_MEMCPY (LocalRSDP.Signature, ACPI_SIG_RSDP, 8); + ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6); + LocalRSDP.Revision = 2; + LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT); + LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT); + + /* Set checksums for both XSDT and RSDP */ + + LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) LocalXSDT, LocalXSDT->Header.Length); + LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH); + + if (!DsdtAddress) + { + return (AE_SUPPORT); + } + + if (ExternalFadt) + { + /* + * Use the external FADT, but we must update the DSDT/FACS addresses + * as well as the checksum + */ + ExternalFadt->Dsdt = DsdtAddress; + ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + + if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt)) + { + ExternalFadt->XDsdt = DsdtAddress; + ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + } + /* Complete the FADT with the checksum */ + + ExternalFadt->Header.Checksum = 0; + ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) ExternalFadt, ExternalFadt->Header.Length); + } + else + { + /* + * Build a local FADT so we can test the hardware/event init + */ + ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT)); + ACPI_STRNCPY (LocalFADT.Header.Signature, ACPI_SIG_FADT, 4); + + /* Setup FADT header and DSDT/FACS addresses */ + + LocalFADT.Dsdt = 0; + LocalFADT.Facs = 0; + + LocalFADT.XDsdt = DsdtAddress; + LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); + + LocalFADT.Header.Revision = 3; + LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT); + + /* Miscellaneous FADT fields */ + + LocalFADT.Gpe0BlockLength = 16; + LocalFADT.Gpe0Block = 0x00001234; + + LocalFADT.Gpe1BlockLength = 6; + LocalFADT.Gpe1Block = 0x00005678; + LocalFADT.Gpe1Base = 96; + + LocalFADT.Pm1EventLength = 4; + LocalFADT.Pm1aEventBlock = 0x00001aaa; + LocalFADT.Pm1bEventBlock = 0x00001bbb; + + LocalFADT.Pm1ControlLength = 2; + LocalFADT.Pm1aControlBlock = 0xB0; + + LocalFADT.PmTimerLength = 4; + LocalFADT.PmTimerBlock = 0xA0; + + LocalFADT.Pm2ControlBlock = 0xC0; + LocalFADT.Pm2ControlLength = 1; + + /* Setup one example X-64 field */ + + LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO; + LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock; + LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength); + + /* Complete the FADT with the checksum */ + + LocalFADT.Header.Checksum = 0; + LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum ( + (void *) &LocalFADT, LocalFADT.Header.Length); + } + + /* Build a FACS */ + + ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS)); + ACPI_STRNCPY (LocalFACS.Signature, ACPI_SIG_FACS, 4); + + LocalFACS.Length = sizeof (ACPI_TABLE_FACS); + LocalFACS.GlobalLock = 0x11AA0011; + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AeLocalGetRootPointer + * + * PARAMETERS: None + * + * RETURN: Address of the RSDP + * + * DESCRIPTION: Return a local RSDP, used to dynamically load tables via the + * standard ACPI mechanism. + * + *****************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void) +{ + + return ((ACPI_PHYSICAL_ADDRESS) &LocalRSDP); +} diff --git a/source/tools/acpisrc/Makefile b/source/tools/acpisrc/Makefile new file mode 100644 index 000000000000..58a8654e350c --- /dev/null +++ b/source/tools/acpisrc/Makefile @@ -0,0 +1,124 @@ +# +# acpisrc - ACPICA source code conversion utility +# +# NOTE: This makefile is intended to be used in the Linux environment, +# with the Linux directory structure. It will not work directly +# on the native ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpisrc + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPISRC = $(ACPICA_TOOLS)/acpisrc +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search path for source files and individual source files +# +vpath %.c \ + $(ACPISRC) \ + $(ACPICA_COMMON) \ + $(ACPICA_OSL) + +HEADERS = \ + $(wildcard $(ACPISRC)/*.h) + +OBJECTS = \ + ascase.o \ + asconvrt.o \ + asfile.o \ + asmain.o \ + asremove.o \ + astable.o \ + asutils.o \ + osunixdir.o \ + getopt.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_SRC_APP \ + -I$(ACPISRC) \ + -I$(ACPICA_INCLUDE) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpisrc/acpisrc.h b/source/tools/acpisrc/acpisrc.h new file mode 100644 index 000000000000..3c0e5dc01d05 --- /dev/null +++ b/source/tools/acpisrc/acpisrc.h @@ -0,0 +1,405 @@ + +/****************************************************************************** + * + * Module Name: acpisrc.h - Include file for AcpiSrc utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define LINES_IN_LEGAL_HEADER 105 /* See above */ +#define LEGAL_HEADER_SIGNATURE " * 2.1. This is your license from Intel Corp. under its intellectual property" +#define LINES_IN_LINUX_HEADER 34 +#define LINUX_HEADER_SIGNATURE " * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS" +#define LINES_IN_ASL_HEADER 29 /* Header as output from disassembler */ + +#include "acpi.h" +#include "accommon.h" + +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#endif +#include + + +/* O_BINARY is not always defined */ +#ifndef O_BINARY +#define O_BINARY 0x0 +#endif + +/* Fixups for non-Win32 compilation */ +#ifndef WIN32 +#define mkdir(x) mkdir(x, 0770) +char * strlwr(char* str); +#endif + + +/* Constants */ + +#define ASRC_MAX_FILE_SIZE (1024 * 100) + +#define FILE_TYPE_SOURCE 1 +#define FILE_TYPE_HEADER 2 +#define FILE_TYPE_DIRECTORY 3 + +#define CVT_COUNT_TABS 0x00000001 +#define CVT_COUNT_NON_ANSI_COMMENTS 0x00000002 +#define CVT_TRIM_LINES 0x00000004 +#define CVT_CHECK_BRACES 0x00000008 +#define CVT_COUNT_LINES 0x00000010 +#define CVT_BRACES_ON_SAME_LINE 0x00000020 +#define CVT_MIXED_CASE_TO_UNDERSCORES 0x00000040 +#define CVT_LOWER_CASE_IDENTIFIERS 0x00000080 +#define CVT_REMOVE_DEBUG_MACROS 0x00000100 +#define CVT_TRIM_WHITESPACE 0x00000200 /* Should be after all line removal */ +#define CVT_REMOVE_EMPTY_BLOCKS 0x00000400 /* Should be after trimming lines */ +#define CVT_REDUCE_TYPEDEFS 0x00000800 +#define CVT_COUNT_SHORTMULTILINE_COMMENTS 0x00001000 +#define CVT_SPACES_TO_TABS4 0x40000000 /* Tab conversion should be last */ +#define CVT_SPACES_TO_TABS8 0x80000000 /* Tab conversion should be last */ + +#define FLG_DEFAULT_FLAGS 0x00000000 +#define FLG_NO_CARRIAGE_RETURNS 0x00000001 +#define FLG_NO_FILE_OUTPUT 0x00000002 +#define FLG_LOWERCASE_DIRNAMES 0x00000004 + +#define AS_START_IGNORE "/*!" +#define AS_STOP_IGNORE "!*/" + + +/* Globals */ + +extern UINT32 Gbl_Files; +extern UINT32 Gbl_MissingBraces; +extern UINT32 Gbl_Tabs; +extern UINT32 Gbl_NonAnsiComments; +extern UINT32 Gbl_SourceLines; +extern UINT32 Gbl_WhiteLines; +extern UINT32 Gbl_CommentLines; +extern UINT32 Gbl_LongLines; +extern UINT32 Gbl_TotalLines; +extern UINT32 Gbl_HeaderSize; +extern UINT32 Gbl_HeaderLines; +extern struct stat Gbl_StatBuf; +extern char *Gbl_FileBuffer; +extern UINT32 Gbl_TotalSize; +extern UINT32 Gbl_FileSize; +extern UINT32 Gbl_FileType; +extern BOOLEAN Gbl_VerboseMode; +extern BOOLEAN Gbl_QuietMode; +extern BOOLEAN Gbl_BatchMode; +extern BOOLEAN Gbl_MadeChanges; +extern BOOLEAN Gbl_Overwrite; +extern BOOLEAN Gbl_WidenDeclarations; +extern BOOLEAN Gbl_IgnoreLoneLineFeeds; +extern BOOLEAN Gbl_HasLoneLineFeeds; +extern void *Gbl_StructDefs; + +#define PARAM_LIST(pl) pl +#define TERSE_PRINT(a) if (!Gbl_VerboseMode) printf PARAM_LIST(a) +#define VERBOSE_PRINT(a) if (Gbl_VerboseMode) printf PARAM_LIST(a) + +#define REPLACE_WHOLE_WORD 0x00 +#define REPLACE_SUBSTRINGS 0x01 +#define REPLACE_MASK 0x01 + +#define EXTRA_INDENT_C 0x02 + + +/* Conversion table structs */ + +typedef struct acpi_string_table +{ + char *Target; + char *Replacement; + UINT8 Type; + +} ACPI_STRING_TABLE; + + +typedef struct acpi_typed_identifier_table +{ + char *Identifier; + UINT8 Type; + +} ACPI_TYPED_IDENTIFIER_TABLE; + +#define SRC_TYPE_SIMPLE 0 +#define SRC_TYPE_STRUCT 1 +#define SRC_TYPE_UNION 2 + + +typedef struct acpi_identifier_table +{ + char *Identifier; + +} ACPI_IDENTIFIER_TABLE; + +typedef struct acpi_conversion_table +{ + char *NewHeader; + UINT32 Flags; + + ACPI_TYPED_IDENTIFIER_TABLE *LowerCaseTable; + + ACPI_STRING_TABLE *SourceStringTable; + ACPI_IDENTIFIER_TABLE *SourceLineTable; + ACPI_IDENTIFIER_TABLE *SourceConditionalTable; + ACPI_IDENTIFIER_TABLE *SourceMacroTable; + ACPI_TYPED_IDENTIFIER_TABLE *SourceStructTable; + UINT32 SourceFunctions; + + ACPI_STRING_TABLE *HeaderStringTable; + ACPI_IDENTIFIER_TABLE *HeaderLineTable; + ACPI_IDENTIFIER_TABLE *HeaderConditionalTable; + ACPI_IDENTIFIER_TABLE *HeaderMacroTable; + ACPI_TYPED_IDENTIFIER_TABLE *HeaderStructTable; + UINT32 HeaderFunctions; + +} ACPI_CONVERSION_TABLE; + + +/* Conversion tables */ + +extern ACPI_CONVERSION_TABLE LinuxConversionTable; +extern ACPI_CONVERSION_TABLE CleanupConversionTable; +extern ACPI_CONVERSION_TABLE StatsConversionTable; +extern ACPI_CONVERSION_TABLE CustomConversionTable; +extern ACPI_CONVERSION_TABLE LicenseConversionTable; + + +/* Prototypes */ + +char * +AsSkipUntilChar ( + char *Buffer, + char Target); + +char * +AsSkipPastChar ( + char *Buffer, + char Target); + +char * +AsReplaceData ( + char *Buffer, + UINT32 LengthToRemove, + char *BufferToAdd, + UINT32 LengthToAdd); + +int +AsReplaceString ( + char *Target, + char *Replacement, + UINT8 Type, + char *Buffer); + +int +AsLowerCaseString ( + char *Target, + char *Buffer); + +void +AsRemoveLine ( + char *Buffer, + char *Keyword); + +void +AsRemoveMacro ( + char *Buffer, + char *Keyword); + +void +AsCheckForBraces ( + char *Buffer, + char *Filename); + +void +AsTrimLines ( + char *Buffer, + char *Filename); + +void +AsMixedCaseToUnderscores ( + char *Buffer); + +void +AsCountTabs ( + char *Buffer, + char *Filename); + +void +AsBracesOnSameLine ( + char *Buffer); + +void +AsLowerCaseIdentifiers ( + char *Buffer); + +void +AsReduceTypedefs ( + char *Buffer, + char *Keyword); + +void +AsRemoveDebugMacros ( + char *Buffer); + +void +AsRemoveEmptyBlocks ( + char *Buffer, + char *Filename); + +void +AsCountSourceLines ( + char *Buffer, + char *Filename); + +void +AsCountNonAnsiComments ( + char *Buffer, + char *Filename); + +void +AsTrimWhitespace ( + char *Buffer); + +void +AsTabify4 ( + char *Buffer); + +void +AsTabify8 ( + char *Buffer); + +void +AsRemoveConditionalCompile ( + char *Buffer, + char *Keyword); + +ACPI_NATIVE_INT +AsProcessTree ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath); + +int +AsGetFile ( + char *FileName, + char **FileBuffer, + UINT32 *FileSize); + +int +AsPutFile ( + char *Pathname, + char *FileBuffer, + UINT32 SystemFlags); + +void +AsReplaceHeader ( + char *Buffer, + char *NewHeader); + +void +AsConvertFile ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *FileBuffer, + char *Filename, + ACPI_NATIVE_INT FileType); + +ACPI_NATIVE_INT +AsProcessOneFile ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath, + int MaxPathLength, + char *Filename, + ACPI_NATIVE_INT FileType); + +ACPI_NATIVE_INT +AsCheckForDirectory ( + char *SourceDirPath, + char *TargetDirPath, + char *Filename, + char **SourcePath, + char **TargetPath); + +BOOLEAN +AsMatchExactWord ( + char *Word, + UINT32 WordLength); + +void +AsPrint ( + char *Message, + UINT32 Count, + char *Filename); + +void +AsInsertPrefix ( + char *Buffer, + char *Keyword, + UINT8 Type); + +char * +AsInsertData ( + char *Buffer, + char *BufferToAdd, + UINT32 LengthToAdd); + +char * +AsRemoveData ( + char *StartPointer, + char *EndPointer); + +void +AsInsertCarriageReturns ( + char *Buffer); + +void +AsConvertToLineFeeds ( + char *Buffer); + + diff --git a/source/tools/acpisrc/ascase.c b/source/tools/acpisrc/ascase.c new file mode 100644 index 000000000000..232ebe8b18fc --- /dev/null +++ b/source/tools/acpisrc/ascase.c @@ -0,0 +1,574 @@ + +/****************************************************************************** + * + * Module Name: ascase - Source conversion - lower/upper case utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpisrc.h" + +/* Local prototypes */ + +void +AsUppercaseTokens ( + char *Buffer, + char *PrefixString); + + +/****************************************************************************** + * + * FUNCTION: AsLowerCaseString + * + * DESCRIPTION: LowerCase all instances of a target string with a replacement + * string. Returns count of the strings replaced. + * + ******************************************************************************/ + +int +AsLowerCaseString ( + char *Target, + char *Buffer) +{ + char *SubString1; + char *SubString2; + char *SubBuffer; + int TargetLength; + int LowerCaseCount = 0; + int i; + + + TargetLength = strlen (Target); + + SubBuffer = Buffer; + SubString1 = Buffer; + + while (SubString1) + { + /* Find the target string */ + + SubString1 = strstr (SubBuffer, Target); + if (!SubString1) + { + return LowerCaseCount; + } + + /* + * Check for translation escape string -- means to ignore + * blocks of code while replacing + */ + SubString2 = strstr (SubBuffer, AS_START_IGNORE); + + if ((SubString2) && + (SubString2 < SubString1)) + { + /* Find end of the escape block starting at "Substring2" */ + + SubString2 = strstr (SubString2, AS_STOP_IGNORE); + if (!SubString2) + { + /* Didn't find terminator */ + + return LowerCaseCount; + } + + /* Move buffer to end of escape block and continue */ + + SubBuffer = SubString2; + } + + /* Do the actual replace if the target was found */ + + else + { + if (!AsMatchExactWord (SubString1, TargetLength)) + { + SubBuffer = SubString1 + 1; + continue; + } + + for (i = 0; i < TargetLength; i++) + { + SubString1[i] = (char) tolower ((int) SubString1[i]); + } + + SubBuffer = SubString1 + TargetLength; + + if ((Gbl_WidenDeclarations) && (!Gbl_StructDefs)) + { + if ((SubBuffer[0] == ' ') && (SubBuffer[1] == ' ')) + { + AsInsertData (SubBuffer, " ", 8); + } + } + + LowerCaseCount++; + } + } + + return LowerCaseCount; +} + + +/****************************************************************************** + * + * FUNCTION: AsMixedCaseToUnderscores + * + * DESCRIPTION: Converts mixed case identifiers to underscored identifiers. + * for example, + * + * ThisUsefullyNamedIdentifier becomes: + * + * this_usefully_named_identifier + * + ******************************************************************************/ + +void +AsMixedCaseToUnderscores ( + char *Buffer) +{ + UINT32 Length; + char *SubBuffer = Buffer; + char *TokenEnd; + char *TokenStart = NULL; + char *SubString; + BOOLEAN HasLowerCase = FALSE; + + + while (*SubBuffer) + { + /* Ignore whitespace */ + + if (*SubBuffer == ' ') + { + while (*SubBuffer == ' ') + { + SubBuffer++; + } + TokenStart = NULL; + HasLowerCase = FALSE; + continue; + } + + /* Ignore commas */ + + if ((*SubBuffer == ',') || + (*SubBuffer == '>') || + (*SubBuffer == ')')) + { + SubBuffer++; + TokenStart = NULL; + HasLowerCase = FALSE; + continue; + } + + /* Check for quoted string -- ignore */ + + if (*SubBuffer == '"') + { + SubBuffer++; + while (*SubBuffer != '"') + { + if (!*SubBuffer) + { + return; + } + + /* Handle embedded escape sequences */ + + if (*SubBuffer == '\\') + { + SubBuffer++; + } + SubBuffer++; + } + SubBuffer++; + continue; + } + + if (islower ((int) *SubBuffer)) + { + HasLowerCase = TRUE; + } + + /* + * Check for translation escape string -- means to ignore + * blocks of code while replacing + */ + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*') && + (SubBuffer[2] == '!')) + { + SubBuffer = strstr (SubBuffer, "!*/"); + if (!SubBuffer) + { + return; + } + continue; + } + + /* Ignore hex constants */ + + if (SubBuffer[0] == '0') + { + if ((SubBuffer[1] == 'x') || + (SubBuffer[1] == 'X')) + { + SubBuffer += 2; + while (isxdigit ((int) *SubBuffer)) + { + SubBuffer++; + } + continue; + } + } + +/* OBSOLETE CODE, all quoted strings now completely ignored. */ +#if 0 + /* Ignore format specification fields */ + + if (SubBuffer[0] == '%') + { + SubBuffer++; + + while ((isalnum (*SubBuffer)) || (*SubBuffer == '.')) + { + SubBuffer++; + } + + continue; + } +#endif + + /* Ignore standard escape sequences (\n, \r, etc.) Not Hex or Octal escapes */ + + if (SubBuffer[0] == '\\') + { + SubBuffer += 2; + continue; + } + + /* + * Ignore identifiers that already contain embedded underscores + * These are typically C macros or defines (all upper case) + * Note: there are some cases where identifiers have underscores + * AcpiGbl_* for example. HasLowerCase flag handles these. + */ + if ((*SubBuffer == '_') && (!HasLowerCase) && (TokenStart)) + { + /* Check the rest of the identifier for any lower case letters */ + + SubString = SubBuffer; + while ((isalnum ((int) *SubString)) || (*SubString == '_')) + { + if (islower ((int) *SubString)) + { + HasLowerCase = TRUE; + } + SubString++; + } + + /* If no lower case letters, we can safely ignore the entire token */ + + if (!HasLowerCase) + { + SubBuffer = SubString; + continue; + } + } + + /* A capital letter may indicate the start of a token; save it */ + + if (isupper ((int) SubBuffer[0])) + { + TokenStart = SubBuffer; + } + + /* + * Convert each pair of letters that matches the form: + * + * + * to + * + */ + else if ((islower ((int) SubBuffer[0]) || isdigit ((int) SubBuffer[0])) && + (isupper ((int) SubBuffer[1]))) + { + if (isdigit ((int) SubBuffer[0])) + { + /* Ignore */ + /* Ignore */ + + if (isupper ((int) *(SubBuffer-1)) || + *(SubBuffer-1) == '_') + { + SubBuffer++; + continue; + } + } + + /* + * Matched the pattern. + * Find the end of this identifier (token) + */ + TokenEnd = SubBuffer; + while ((isalnum ((int) *TokenEnd)) || (*TokenEnd == '_')) + { + TokenEnd++; + } + + /* Force the UpperCase letter (#2) to lower case */ + + Gbl_MadeChanges = TRUE; + SubBuffer[1] = (char) tolower ((int) SubBuffer[1]); + + SubString = TokenEnd; + Length = 0; + + while (*SubString != '\n') + { + /* + * If we have at least two trailing spaces, we can get rid of + * one to make up for the newly inserted underscore. This will + * help preserve the alignment of the text + */ + if ((SubString[0] == ' ') && + (SubString[1] == ' ')) + { + Length = SubString - SubBuffer - 2; + break; + } + + SubString++; + } + + if (!Length) + { + Length = strlen (&SubBuffer[1]); + } + + memmove (&SubBuffer[2], &SubBuffer[1], Length + 1); + SubBuffer[1] = '_'; + SubBuffer +=2; + + /* Lower case the leading character of the token */ + + if (TokenStart) + { + *TokenStart = (char) tolower ((int) *TokenStart); + TokenStart = NULL; + } + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsLowerCaseIdentifiers + * + * DESCRIPTION: Converts mixed case identifiers to lower case. Leaves comments, + * quoted strings, and all-upper-case macros alone. + * + ******************************************************************************/ + +void +AsLowerCaseIdentifiers ( + char *Buffer) +{ + char *SubBuffer = Buffer; + + + while (*SubBuffer) + { + /* + * Check for translation escape string -- means to ignore + * blocks of code while replacing + */ + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*') && + (SubBuffer[2] == '!')) + { + SubBuffer = strstr (SubBuffer, "!*/"); + if (!SubBuffer) + { + return; + } + } + + /* Ignore comments */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + SubBuffer = strstr (SubBuffer, "*/"); + if (!SubBuffer) + { + return; + } + + SubBuffer += 2; + } + + /* Ignore quoted strings */ + + if ((SubBuffer[0] == '\"') && (SubBuffer[1] != '\'')) + { + SubBuffer++; + + /* Find the closing quote */ + + while (SubBuffer[0]) + { + /* Ignore escaped quote characters */ + + if (SubBuffer[0] == '\\') + { + SubBuffer++; + } + else if (SubBuffer[0] == '\"') + { + SubBuffer++; + break; + } + SubBuffer++; + } + } + + if (!SubBuffer[0]) + { + return; + } + + /* + * Only lower case if we have an upper followed by a lower + * This leaves the all-uppercase things (macros, etc.) intact + */ + if ((isupper ((int) SubBuffer[0])) && + (islower ((int) SubBuffer[1]))) + { + Gbl_MadeChanges = TRUE; + *SubBuffer = (char) tolower ((int) *SubBuffer); + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsUppercaseTokens + * + * DESCRIPTION: Force to uppercase all tokens that begin with the prefix string. + * used to convert mixed-case macros and constants to uppercase. + * + ******************************************************************************/ + +void +AsUppercaseTokens ( + char *Buffer, + char *PrefixString) +{ + char *SubBuffer; + char *TokenEnd; + char *SubString; + int i; + UINT32 Length; + + + SubBuffer = Buffer; + + while (SubBuffer) + { + SubBuffer = strstr (SubBuffer, PrefixString); + if (SubBuffer) + { + TokenEnd = SubBuffer; + while ((isalnum ((int) *TokenEnd)) || (*TokenEnd == '_')) + { + TokenEnd++; + } + + for (i = 0; i < (TokenEnd - SubBuffer); i++) + { + if ((islower ((int) SubBuffer[i])) && + (isupper ((int) SubBuffer[i+1]))) + { + + SubString = TokenEnd; + Length = 0; + + while (*SubString != '\n') + { + if ((SubString[0] == ' ') && + (SubString[1] == ' ')) + { + Length = SubString - &SubBuffer[i] - 2; + break; + } + + SubString++; + } + + if (!Length) + { + Length = strlen (&SubBuffer[i+1]); + } + + memmove (&SubBuffer[i+2], &SubBuffer[i+1], (Length+1)); + SubBuffer[i+1] = '_'; + i +=2; + TokenEnd++; + } + } + + for (i = 0; i < (TokenEnd - SubBuffer); i++) + { + SubBuffer[i] = (char) toupper ((int) SubBuffer[i]); + } + + SubBuffer = TokenEnd; + } + } +} + + diff --git a/source/tools/acpisrc/asconvrt.c b/source/tools/acpisrc/asconvrt.c new file mode 100644 index 000000000000..1669f9d20e79 --- /dev/null +++ b/source/tools/acpisrc/asconvrt.c @@ -0,0 +1,1448 @@ + +/****************************************************************************** + * + * Module Name: asconvrt - Source conversion code + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpisrc.h" + +/* Local prototypes */ + +char * +AsCheckAndSkipLiterals ( + char *Buffer, + UINT32 *TotalLines); + +UINT32 +AsCountLines ( + char *Buffer, + char *Filename); + +/* Opening signature of the Intel legal header */ + +char *HeaderBegin = "/******************************************************************************\n *\n * 1. Copyright Notice"; + + +/****************************************************************************** + * + * FUNCTION: AsMatchExactWord + * + * DESCRIPTION: Check previous and next characters for whitespace + * + ******************************************************************************/ + +BOOLEAN +AsMatchExactWord ( + char *Word, + UINT32 WordLength) +{ + char NextChar; + char PrevChar; + + + NextChar = Word[WordLength]; + PrevChar = * (Word -1); + + if (isalnum ((int) NextChar) || + (NextChar == '_') || + isalnum ((int) PrevChar) || + (PrevChar == '_')) + { + return (FALSE); + } + + return (TRUE); +} + + +/****************************************************************************** + * + * FUNCTION: AsPrint + * + * DESCRIPTION: Common formatted print + * + ******************************************************************************/ + +void +AsPrint ( + char *Message, + UINT32 Count, + char *Filename) +{ + + if (Gbl_QuietMode) + { + return; + } + + printf ("-- %4u %28.28s : %s\n", Count, Message, Filename); +} + + +/****************************************************************************** + * + * FUNCTION: AsCheckAndSkipLiterals + * + * DESCRIPTION: Generic routine to skip comments and quoted string literals. + * Keeps a line count. + * + ******************************************************************************/ + +char * +AsCheckAndSkipLiterals ( + char *Buffer, + UINT32 *TotalLines) +{ + UINT32 NewLines = 0; + char *SubBuffer = Buffer; + char *LiteralEnd; + + + /* Ignore comments */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + LiteralEnd = strstr (SubBuffer, "*/"); + SubBuffer += 2; /* Get past comment opening */ + + if (!LiteralEnd) + { + return SubBuffer; + } + + while (SubBuffer < LiteralEnd) + { + if (*SubBuffer == '\n') + { + NewLines++; + } + + SubBuffer++; + } + + SubBuffer += 2; /* Get past comment close */ + } + + /* Ignore quoted strings */ + + else if (*SubBuffer == '\"') + { + SubBuffer++; + LiteralEnd = AsSkipPastChar (SubBuffer, '\"'); + if (!LiteralEnd) + { + return SubBuffer; + } + } + + if (TotalLines) + { + (*TotalLines) += NewLines; + } + return SubBuffer; +} + + +/****************************************************************************** + * + * FUNCTION: AsAsCheckForBraces + * + * DESCRIPTION: Check for an open brace after each if statement + * + ******************************************************************************/ + +void +AsCheckForBraces ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + char *NextBrace; + char *NextSemicolon; + char *NextIf; + UINT32 TotalLines = 1; + + + while (*SubBuffer) + { + + SubBuffer = AsCheckAndSkipLiterals (SubBuffer, &TotalLines); + + if (*SubBuffer == '\n') + { + TotalLines++; + } + else if (!(strncmp (" if", SubBuffer, 3))) + { + SubBuffer += 2; + NextBrace = strstr (SubBuffer, "{"); + NextSemicolon = strstr (SubBuffer, ";"); + NextIf = strstr (SubBuffer, " if"); + + if ((!NextBrace) || + (NextSemicolon && (NextBrace > NextSemicolon)) || + (NextIf && (NextBrace > NextIf))) + { + Gbl_MissingBraces++; + + if (!Gbl_QuietMode) + { + printf ("Missing braces for , line %u: %s\n", TotalLines, Filename); + } + } + } + else if (!(strncmp (" else if", SubBuffer, 8))) + { + SubBuffer += 7; + NextBrace = strstr (SubBuffer, "{"); + NextSemicolon = strstr (SubBuffer, ";"); + NextIf = strstr (SubBuffer, " if"); + + if ((!NextBrace) || + (NextSemicolon && (NextBrace > NextSemicolon)) || + (NextIf && (NextBrace > NextIf))) + { + Gbl_MissingBraces++; + + if (!Gbl_QuietMode) + { + printf ("Missing braces for , line %u: %s\n", TotalLines, Filename); + } + } + } + else if (!(strncmp (" else", SubBuffer, 5))) + { + SubBuffer += 4; + NextBrace = strstr (SubBuffer, "{"); + NextSemicolon = strstr (SubBuffer, ";"); + NextIf = strstr (SubBuffer, " if"); + + if ((!NextBrace) || + (NextSemicolon && (NextBrace > NextSemicolon)) || + (NextIf && (NextBrace > NextIf))) + { + Gbl_MissingBraces++; + + if (!Gbl_QuietMode) + { + printf ("Missing braces for , line %u: %s\n", TotalLines, Filename); + } + } + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsTrimLines + * + * DESCRIPTION: Remove extra blanks from the end of source lines. Does not + * check for tabs. + * + ******************************************************************************/ + +void +AsTrimLines ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + char *StartWhiteSpace = NULL; + UINT32 SpaceCount = 0; + + + while (*SubBuffer) + { + while (*SubBuffer != '\n') + { + if (!*SubBuffer) + { + goto Exit; + } + + if (*SubBuffer == ' ') + { + if (!StartWhiteSpace) + { + StartWhiteSpace = SubBuffer; + } + } + else + { + StartWhiteSpace = NULL; + } + + SubBuffer++; + } + + if (StartWhiteSpace) + { + SpaceCount += (SubBuffer - StartWhiteSpace); + + /* Remove the spaces */ + + SubBuffer = AsRemoveData (StartWhiteSpace, SubBuffer); + StartWhiteSpace = NULL; + } + + SubBuffer++; + } + + +Exit: + if (SpaceCount) + { + Gbl_MadeChanges = TRUE; + AsPrint ("Extraneous spaces removed", SpaceCount, Filename); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsTrimWhitespace + * + * DESCRIPTION: Remove "excess" blank lines - any more than 2 blank lines. + * this can happen during the translation when lines are removed. + * + ******************************************************************************/ + +void +AsTrimWhitespace ( + char *Buffer) +{ + int ReplaceCount = 1; + + + while (ReplaceCount) + { + ReplaceCount = AsReplaceString ("\n\n\n\n", "\n\n\n", REPLACE_SUBSTRINGS, Buffer); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsReplaceHeader + * + * DESCRIPTION: Replace the default Intel legal header with a new header + * + ******************************************************************************/ + +void +AsReplaceHeader ( + char *Buffer, + char *NewHeader) +{ + char *SubBuffer; + char *TokenEnd; + + + /* Find the original header */ + + SubBuffer = strstr (Buffer, HeaderBegin); + if (!SubBuffer) + { + return; + } + + /* Find the end of the original header */ + + TokenEnd = strstr (SubBuffer, "*/"); + TokenEnd = AsSkipPastChar (TokenEnd, '\n'); + + /* Delete old header, insert new one */ + + AsReplaceData (SubBuffer, TokenEnd - SubBuffer, NewHeader, strlen (NewHeader)); +} + + +/****************************************************************************** + * + * FUNCTION: AsReplaceString + * + * DESCRIPTION: Replace all instances of a target string with a replacement + * string. Returns count of the strings replaced. + * + ******************************************************************************/ + +int +AsReplaceString ( + char *Target, + char *Replacement, + UINT8 Type, + char *Buffer) +{ + char *SubString1; + char *SubString2; + char *SubBuffer; + int TargetLength; + int ReplacementLength; + int ReplaceCount = 0; + + + TargetLength = strlen (Target); + ReplacementLength = strlen (Replacement); + + SubBuffer = Buffer; + SubString1 = Buffer; + + while (SubString1) + { + /* Find the target string */ + + SubString1 = strstr (SubBuffer, Target); + if (!SubString1) + { + return ReplaceCount; + } + + /* + * Check for translation escape string -- means to ignore + * blocks of code while replacing + */ + SubString2 = strstr (SubBuffer, AS_START_IGNORE); + + if ((SubString2) && + (SubString2 < SubString1)) + { + /* Find end of the escape block starting at "Substring2" */ + + SubString2 = strstr (SubString2, AS_STOP_IGNORE); + if (!SubString2) + { + /* Didn't find terminator */ + + return ReplaceCount; + } + + /* Move buffer to end of escape block and continue */ + + SubBuffer = SubString2; + } + + /* Do the actual replace if the target was found */ + + else + { + if ((Type & REPLACE_MASK) == REPLACE_WHOLE_WORD) + { + if (!AsMatchExactWord (SubString1, TargetLength)) + { + SubBuffer = SubString1 + 1; + continue; + } + } + + SubBuffer = AsReplaceData (SubString1, TargetLength, Replacement, ReplacementLength); + + if ((Type & EXTRA_INDENT_C) && + (!Gbl_StructDefs)) + { + SubBuffer = AsInsertData (SubBuffer, " ", 8); + } + + ReplaceCount++; + } + } + + return ReplaceCount; +} + + +/****************************************************************************** + * + * FUNCTION: AsConvertToLineFeeds + * + * DESCRIPTION: + * + ******************************************************************************/ + +void +AsConvertToLineFeeds ( + char *Buffer) +{ + char *SubString; + char *SubBuffer; + + + SubBuffer = Buffer; + SubString = Buffer; + + while (SubString) + { + /* Find the target string */ + + SubString = strstr (SubBuffer, "\r\n"); + if (!SubString) + { + return; + } + + SubBuffer = AsReplaceData (SubString, 1, NULL, 0); + } + return; +} + + +/****************************************************************************** + * + * FUNCTION: AsInsertCarriageReturns + * + * DESCRIPTION: + * + ******************************************************************************/ + +void +AsInsertCarriageReturns ( + char *Buffer) +{ + char *SubString; + char *SubBuffer; + + + SubBuffer = Buffer; + SubString = Buffer; + + while (SubString) + { + /* Find the target string */ + + SubString = strstr (SubBuffer, "\n"); + if (!SubString) + { + return; + } + + SubBuffer = AsInsertData (SubString, "\r", 1); + SubBuffer += 1; + } + return; +} + + +/****************************************************************************** + * + * FUNCTION: AsBracesOnSameLine + * + * DESCRIPTION: Move opening braces up to the same line as an if, for, else, + * or while statement (leave function opening brace on separate + * line). + * + ******************************************************************************/ + +void +AsBracesOnSameLine ( + char *Buffer) +{ + char *SubBuffer = Buffer; + char *Beginning; + char *StartOfThisLine; + char *Next; + BOOLEAN BlockBegin = TRUE; + + + while (*SubBuffer) + { + /* Ignore comments */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + SubBuffer = strstr (SubBuffer, "*/"); + if (!SubBuffer) + { + return; + } + + SubBuffer += 2; + continue; + } + + /* Ignore quoted strings */ + + if (*SubBuffer == '\"') + { + SubBuffer++; + SubBuffer = AsSkipPastChar (SubBuffer, '\"'); + if (!SubBuffer) + { + return; + } + } + + if (!strncmp ("\n}", SubBuffer, 2)) + { + /* + * A newline followed by a closing brace closes a function + * or struct or initializer block + */ + BlockBegin = TRUE; + } + + /* + * Move every standalone brace up to the previous line + * Check for digit will ignore initializer lists surrounded by braces. + * This will work until we we need more complex detection. + */ + if ((*SubBuffer == '{') && !isdigit ((int) SubBuffer[1])) + { + if (BlockBegin) + { + BlockBegin = FALSE; + } + else + { + /* + * Backup to previous non-whitespace + */ + Beginning = SubBuffer - 1; + while ((*Beginning == ' ') || + (*Beginning == '\n')) + { + Beginning--; + } + + StartOfThisLine = Beginning; + while (*StartOfThisLine != '\n') + { + StartOfThisLine--; + } + + /* + * Move the brace up to the previous line, UNLESS: + * + * 1) There is a conditional compile on the line (starts with '#') + * 2) Previous line ends with an '=' (Start of initializer block) + * 3) Previous line ends with a comma (part of an init list) + * 4) Previous line ends with a backslash (part of a macro) + */ + if ((StartOfThisLine[1] != '#') && + (*Beginning != '\\') && + (*Beginning != '/') && + (*Beginning != '{') && + (*Beginning != '=') && + (*Beginning != ',')) + { + Beginning++; + SubBuffer++; + + Gbl_MadeChanges = TRUE; + +#ifdef ADD_EXTRA_WHITESPACE + AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3); +#else + /* Find non-whitespace start of next line */ + + Next = SubBuffer + 1; + while ((*Next == ' ') || + (*Next == '\t')) + { + Next++; + } + + /* Find non-whitespace start of this line */ + + StartOfThisLine++; + while ((*StartOfThisLine == ' ') || + (*StartOfThisLine == '\t')) + { + StartOfThisLine++; + } + + /* + * Must be a single-line comment to need more whitespace + * Even then, we don't need more if the previous statement + * is an "else". + */ + if ((Next[0] == '/') && + (Next[1] == '*') && + (Next[2] != '\n') && + + (!strncmp (StartOfThisLine, "else if", 7) || + !strncmp (StartOfThisLine, "else while", 10) || + strncmp (StartOfThisLine, "else", 4))) + { + AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3); + } + else + { + AsReplaceData (Beginning, SubBuffer - Beginning, " {", 2); + } +#endif + } + } + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsTabify4 + * + * DESCRIPTION: Convert the text to tabbed text. Alignment of text is + * preserved. + * + ******************************************************************************/ + +void +AsTabify4 ( + char *Buffer) +{ + char *SubBuffer = Buffer; + char *NewSubBuffer; + UINT32 SpaceCount = 0; + UINT32 Column = 0; + + + while (*SubBuffer) + { + if (*SubBuffer == '\n') + { + Column = 0; + } + else + { + Column++; + } + + /* Ignore comments */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + SubBuffer = strstr (SubBuffer, "*/"); + if (!SubBuffer) + { + return; + } + + SubBuffer += 2; + continue; + } + + /* Ignore quoted strings */ + + if (*SubBuffer == '\"') + { + SubBuffer++; + SubBuffer = AsSkipPastChar (SubBuffer, '\"'); + if (!SubBuffer) + { + return; + } + SpaceCount = 0; + } + + if (*SubBuffer == ' ') + { + SpaceCount++; + + if (SpaceCount >= 4) + { + SpaceCount = 0; + + NewSubBuffer = (SubBuffer + 1) - 4; + *NewSubBuffer = '\t'; + NewSubBuffer++; + + /* Remove the spaces */ + + SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer + 1); + } + + if ((Column % 4) == 0) + { + SpaceCount = 0; + } + } + else + { + SpaceCount = 0; + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsTabify8 + * + * DESCRIPTION: Convert the text to tabbed text. Alignment of text is + * preserved. + * + ******************************************************************************/ + +void +AsTabify8 ( + char *Buffer) +{ + char *SubBuffer = Buffer; + char *NewSubBuffer; + char *CommentEnd = NULL; + UINT32 SpaceCount = 0; + UINT32 Column = 0; + UINT32 TabCount = 0; + UINT32 LastLineTabCount = 0; + UINT32 LastLineColumnStart = 0; + UINT32 ThisColumnStart = 0; + UINT32 ThisTabCount = 0; + char *FirstNonBlank = NULL; + + + while (*SubBuffer) + { + if (*SubBuffer == '\n') + { + /* This is a standalone blank line */ + + FirstNonBlank = NULL; + Column = 0; + SpaceCount = 0; + TabCount = 0; + SubBuffer++; + continue; + } + + if (!FirstNonBlank) + { + /* Find the first non-blank character on this line */ + + FirstNonBlank = SubBuffer; + while (*FirstNonBlank == ' ') + { + FirstNonBlank++; + } + + /* + * This mechanism limits the difference in tab counts from + * line to line. It helps avoid the situation where a second + * continuation line (which was indented correctly for tabs=4) would + * get indented off the screen if we just blindly converted to tabs. + */ + ThisColumnStart = FirstNonBlank - SubBuffer; + + if (LastLineTabCount == 0) + { + ThisTabCount = 0; + } + else if (ThisColumnStart == LastLineColumnStart) + { + ThisTabCount = LastLineTabCount -1; + } + else + { + ThisTabCount = LastLineTabCount + 1; + } + } + + Column++; + + /* Check if we are in a comment */ + + if ((SubBuffer[0] == '*') && + (SubBuffer[1] == '/')) + { + SpaceCount = 0; + SubBuffer += 2; + + if (*SubBuffer == '\n') + { + if (TabCount > 0) + { + LastLineTabCount = TabCount; + TabCount = 0; + } + FirstNonBlank = NULL; + LastLineColumnStart = ThisColumnStart; + SubBuffer++; + } + + continue; + } + + /* Check for comment open */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + /* Find the end of the comment, it must exist */ + + CommentEnd = strstr (SubBuffer, "*/"); + if (!CommentEnd) + { + return; + } + + /* Toss the rest of this line or single-line comment */ + + while ((SubBuffer < CommentEnd) && + (*SubBuffer != '\n')) + { + SubBuffer++; + } + + if (*SubBuffer == '\n') + { + if (TabCount > 0) + { + LastLineTabCount = TabCount; + TabCount = 0; + } + FirstNonBlank = NULL; + LastLineColumnStart = ThisColumnStart; + } + + SpaceCount = 0; + continue; + } + + /* Ignore quoted strings */ + + if ((!CommentEnd) && (*SubBuffer == '\"')) + { + SubBuffer++; + SubBuffer = AsSkipPastChar (SubBuffer, '\"'); + if (!SubBuffer) + { + return; + } + SpaceCount = 0; + } + + if (*SubBuffer != ' ') + { + /* Not a space, skip to end of line */ + + SubBuffer = AsSkipUntilChar (SubBuffer, '\n'); + if (!SubBuffer) + { + return; + } + if (TabCount > 0) + { + LastLineTabCount = TabCount; + TabCount = 0; + } + + FirstNonBlank = NULL; + LastLineColumnStart = ThisColumnStart; + Column = 0; + SpaceCount = 0; + } + else + { + /* Another space */ + + SpaceCount++; + + if (SpaceCount >= 4) + { + /* Replace this group of spaces with a tab character */ + + SpaceCount = 0; + + NewSubBuffer = SubBuffer - 3; + + if (TabCount <= ThisTabCount ? (ThisTabCount +1) : 0) + { + *NewSubBuffer = '\t'; + NewSubBuffer++; + SubBuffer++; + TabCount++; + } + + /* Remove the spaces */ + + SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer); + continue; + } + } + + SubBuffer++; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsCountLines + * + * DESCRIPTION: Count the number of lines in the input buffer. Also count + * the number of long lines (lines longer than 80 chars). + * + ******************************************************************************/ + +UINT32 +AsCountLines ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + char *EndOfLine; + UINT32 LineCount = 0; + UINT32 LongLineCount = 0; + + + while (*SubBuffer) + { + EndOfLine = AsSkipUntilChar (SubBuffer, '\n'); + if (!EndOfLine) + { + Gbl_TotalLines += LineCount; + return LineCount; + } + + if ((EndOfLine - SubBuffer) > 80) + { + LongLineCount++; + VERBOSE_PRINT (("long: %.80s\n", SubBuffer)); + } + + LineCount++; + SubBuffer = EndOfLine + 1; + } + + if (LongLineCount) + { + VERBOSE_PRINT (("%u Lines longer than 80 found in %s\n", LongLineCount, Filename)); + Gbl_LongLines += LongLineCount; + } + + Gbl_TotalLines += LineCount; + return LineCount; +} + + +/****************************************************************************** + * + * FUNCTION: AsCountTabs + * + * DESCRIPTION: Simply count the number of tabs in the input file buffer + * + ******************************************************************************/ + +void +AsCountTabs ( + char *Buffer, + char *Filename) +{ + UINT32 i; + UINT32 TabCount = 0; + + + for (i = 0; Buffer[i]; i++) + { + if (Buffer[i] == '\t') + { + TabCount++; + } + } + + if (TabCount) + { + AsPrint ("Tabs found", TabCount, Filename); + Gbl_Tabs += TabCount; + } + + AsCountLines (Buffer, Filename); +} + + +/****************************************************************************** + * + * FUNCTION: AsCountNonAnsiComments + * + * DESCRIPTION: Count the number of "//" comments. This type of comment is + * non-ANSI C. + * + ******************************************************************************/ + +void +AsCountNonAnsiComments ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + UINT32 CommentCount = 0; + + + while (SubBuffer) + { + SubBuffer = strstr (SubBuffer, "//"); + if (SubBuffer) + { + CommentCount++; + SubBuffer += 2; + } + } + + if (CommentCount) + { + AsPrint ("Non-ANSI Comments found", CommentCount, Filename); + Gbl_NonAnsiComments += CommentCount; + } +} + + +/****************************************************************************** + * + * FUNCTION: AsCountSourceLines + * + * DESCRIPTION: Count the number of C source lines. Defined by 1) not a + * comment, and 2) not a blank line. + * + ******************************************************************************/ + +void +AsCountSourceLines ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + UINT32 LineCount = 0; + UINT32 WhiteCount = 0; + UINT32 CommentCount = 0; + + + while (*SubBuffer) + { + /* Detect comments (// comments are not used, non-ansii) */ + + if ((SubBuffer[0] == '/') && + (SubBuffer[1] == '*')) + { + SubBuffer += 2; + + /* First line of multi-line comment is often just whitespace */ + + if (SubBuffer[0] == '\n') + { + WhiteCount++; + SubBuffer++; + } + else + { + CommentCount++; + } + + /* Find end of comment */ + + while (SubBuffer[0] && SubBuffer[1] && + !(((SubBuffer[0] == '*') && + (SubBuffer[1] == '/')))) + { + if (SubBuffer[0] == '\n') + { + CommentCount++; + } + + SubBuffer++; + } + } + + /* A linefeed followed by a non-linefeed is a valid source line */ + + else if ((SubBuffer[0] == '\n') && + (SubBuffer[1] != '\n')) + { + LineCount++; + } + + /* Two back-to-back linefeeds indicate a whitespace line */ + + else if ((SubBuffer[0] == '\n') && + (SubBuffer[1] == '\n')) + { + WhiteCount++; + } + + SubBuffer++; + } + + /* Adjust comment count for legal header */ + + if (Gbl_HeaderSize < CommentCount) + { + CommentCount -= Gbl_HeaderSize; + Gbl_HeaderLines += Gbl_HeaderSize; + } + + Gbl_SourceLines += LineCount; + Gbl_WhiteLines += WhiteCount; + Gbl_CommentLines += CommentCount; + + VERBOSE_PRINT (("%u Comment %u White %u Code %u Lines in %s\n", + CommentCount, WhiteCount, LineCount, LineCount+WhiteCount+CommentCount, Filename)); +} + + +/****************************************************************************** + * + * FUNCTION: AsInsertPrefix + * + * DESCRIPTION: Insert struct or union prefixes + * + ******************************************************************************/ + +void +AsInsertPrefix ( + char *Buffer, + char *Keyword, + UINT8 Type) +{ + char *SubString; + char *SubBuffer; + char *EndKeyword; + int InsertLength; + char *InsertString; + int TrailingSpaces; + char LowerKeyword[128]; + int KeywordLength; + + + switch (Type) + { + case SRC_TYPE_STRUCT: + InsertString = "struct "; + break; + + case SRC_TYPE_UNION: + InsertString = "union "; + break; + + default: + return; + } + + strcpy (LowerKeyword, Keyword); + strlwr (LowerKeyword); + + SubBuffer = Buffer; + SubString = Buffer; + InsertLength = strlen (InsertString); + KeywordLength = strlen (Keyword); + + + while (SubString) + { + /* Find an instance of the keyword */ + + SubString = strstr (SubBuffer, LowerKeyword); + if (!SubString) + { + return; + } + + SubBuffer = SubString; + + /* Must be standalone word, not a substring */ + + if (AsMatchExactWord (SubString, KeywordLength)) + { + /* Make sure the keyword isn't already prefixed with the insert */ + + if (!strncmp (SubString - InsertLength, InsertString, InsertLength)) + { + /* Add spaces if not already at the end-of-line */ + + if (*(SubBuffer + KeywordLength) != '\n') + { + /* Already present, add spaces after to align structure members */ + +#if 0 +/* ONLY FOR C FILES */ + AsInsertData (SubBuffer + KeywordLength, " ", 8); +#endif + } + goto Next; + } + + /* Make sure the keyword isn't at the end of a struct/union */ + /* Note: This code depends on a single space after the brace */ + + if (*(SubString - 2) == '}') + { + goto Next; + } + + /* Prefix the keyword with the insert string */ + + Gbl_MadeChanges = TRUE; + + /* Is there room for insertion */ + + EndKeyword = SubString + strlen (LowerKeyword); + + TrailingSpaces = 0; + while (EndKeyword[TrailingSpaces] == ' ') + { + TrailingSpaces++; + } + + /* + * Use "if (TrailingSpaces > 1)" if we want to ignore casts + */ + SubBuffer = SubString + InsertLength; + + if (TrailingSpaces > InsertLength) + { + /* Insert the keyword */ + + memmove (SubBuffer, SubString, KeywordLength); + + /* Insert the keyword */ + + memmove (SubString, InsertString, InsertLength); + } + else + { + AsInsertData (SubString, InsertString, InsertLength); + } + } + +Next: + SubBuffer += KeywordLength; + } +} + +#ifdef ACPI_FUTURE_IMPLEMENTATION +/****************************************************************************** + * + * FUNCTION: AsTrimComments + * + * DESCRIPTION: Finds 3-line comments with only a single line of text + * + ******************************************************************************/ + +void +AsTrimComments ( + char *Buffer, + char *Filename) +{ + char *SubBuffer = Buffer; + char *Ptr1; + char *Ptr2; + UINT32 LineCount; + UINT32 ShortCommentCount = 0; + + + while (1) + { + /* Find comment open, within procedure level */ + + SubBuffer = strstr (SubBuffer, " /*"); + if (!SubBuffer) + { + goto Exit; + } + + /* Find comment terminator */ + + Ptr1 = strstr (SubBuffer, "*/"); + if (!Ptr1) + { + goto Exit; + } + + /* Find next EOL (from original buffer) */ + + Ptr2 = strstr (SubBuffer, "\n"); + if (!Ptr2) + { + goto Exit; + } + + /* Ignore one-line comments */ + + if (Ptr1 < Ptr2) + { + /* Normal comment, ignore and continue; */ + + SubBuffer = Ptr2; + continue; + } + + /* Examine multi-line comment */ + + LineCount = 1; + while (Ptr1 > Ptr2) + { + /* Find next EOL */ + + Ptr2++; + Ptr2 = strstr (Ptr2, "\n"); + if (!Ptr2) + { + goto Exit; + } + + LineCount++; + } + + SubBuffer = Ptr1; + + if (LineCount <= 3) + { + ShortCommentCount++; + } + } + + +Exit: + + if (ShortCommentCount) + { + AsPrint ("Short Comments found", ShortCommentCount, Filename); + } +} +#endif + + diff --git a/source/tools/acpisrc/asfile.c b/source/tools/acpisrc/asfile.c new file mode 100644 index 000000000000..ce26adc3d8e4 --- /dev/null +++ b/source/tools/acpisrc/asfile.c @@ -0,0 +1,815 @@ + +/****************************************************************************** + * + * Module Name: asfile - Main module for the acpi source processor utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpisrc.h" + +/* Local prototypes */ + +void +AsDoWildcard ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath, + int MaxPathLength, + int FileType, + char *WildcardSpec); + +BOOLEAN +AsDetectLoneLineFeeds ( + char *Filename, + char *Buffer); + +static ACPI_INLINE int +AsMaxInt (int a, int b) +{ + return (a > b ? a : b); +} + + +/****************************************************************************** + * + * FUNCTION: AsDoWildcard + * + * DESCRIPTION: Process files via wildcards + * + ******************************************************************************/ + +void +AsDoWildcard ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath, + int MaxPathLength, + int FileType, + char *WildcardSpec) +{ + void *DirInfo; + char *Filename; + char *SourceDirPath; + char *TargetDirPath; + char RequestedFileType; + + + if (FileType == FILE_TYPE_DIRECTORY) + { + RequestedFileType = REQUEST_DIR_ONLY; + } + else + { + RequestedFileType = REQUEST_FILE_ONLY; + } + + VERBOSE_PRINT (("Checking for %s source files in directory \"%s\"\n", + WildcardSpec, SourcePath)); + + /* Open the directory for wildcard search */ + + DirInfo = AcpiOsOpenDirectory (SourcePath, WildcardSpec, RequestedFileType); + if (DirInfo) + { + /* + * Get all of the files that match both the + * wildcard and the requested file type + */ + while ((Filename = AcpiOsGetNextFilename (DirInfo))) + { + /* Looking for directory files, must check file type */ + + switch (RequestedFileType) + { + case REQUEST_DIR_ONLY: + + /* If we actually have a dir, process the subtree */ + + if (!AsCheckForDirectory (SourcePath, TargetPath, Filename, + &SourceDirPath, &TargetDirPath)) + { + VERBOSE_PRINT (("Subdirectory: %s\n", Filename)); + + AsProcessTree (ConversionTable, SourceDirPath, TargetDirPath); + free (SourceDirPath); + free (TargetDirPath); + } + break; + + case REQUEST_FILE_ONLY: + + /* Otherwise, this is a file, not a directory */ + + VERBOSE_PRINT (("File: %s\n", Filename)); + + AsProcessOneFile (ConversionTable, SourcePath, TargetPath, + MaxPathLength, Filename, FileType); + break; + + default: + break; + } + } + + /* Cleanup */ + + AcpiOsCloseDirectory (DirInfo); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsProcessTree + * + * DESCRIPTION: Process the directory tree. Files with the extension ".C" and + * ".H" are processed as the tree is traversed. + * + ******************************************************************************/ + +ACPI_NATIVE_INT +AsProcessTree ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath) +{ + int MaxPathLength; + + + MaxPathLength = AsMaxInt (strlen (SourcePath), strlen (TargetPath)); + + if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT)) + { + if (ConversionTable->Flags & FLG_LOWERCASE_DIRNAMES) + { + strlwr (TargetPath); + } + + VERBOSE_PRINT (("Creating Directory \"%s\"\n", TargetPath)); + if (mkdir (TargetPath)) + { + if (errno != EEXIST) + { + printf ("Could not create target directory\n"); + return -1; + } + } + } + + /* Do the C source files */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_SOURCE, "*.c"); + + /* Do the C header files */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_HEADER, "*.h"); + + /* Do the Lex file(s) */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_SOURCE, "*.l"); + + /* Do the yacc file(s) */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_SOURCE, "*.y"); + + /* Do any ASL files */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_HEADER, "*.asl"); + + /* Do any subdirectories */ + + AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength, + FILE_TYPE_DIRECTORY, "*"); + + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AsDetectLoneLineFeeds + * + * DESCRIPTION: Find LF without CR. + * + ******************************************************************************/ + +BOOLEAN +AsDetectLoneLineFeeds ( + char *Filename, + char *Buffer) +{ + UINT32 i = 1; + UINT32 LfCount = 0; + UINT32 LineCount = 0; + + + if (!Buffer[0]) + { + return FALSE; + } + + while (Buffer[i]) + { + if (Buffer[i] == 0x0A) + { + if (Buffer[i-1] != 0x0D) + { + LfCount++; + } + LineCount++; + } + i++; + } + + if (LfCount) + { + if (LineCount == LfCount) + { + if (!Gbl_IgnoreLoneLineFeeds) + { + printf ("%s: ****File has UNIX format**** (LF only, not CR/LF) %u lines\n", + Filename, LfCount); + } + } + else + { + printf ("%s: %u lone linefeeds in file\n", Filename, LfCount); + } + return TRUE; + } + + return (FALSE); +} + + +/****************************************************************************** + * + * FUNCTION: AsConvertFile + * + * DESCRIPTION: Perform the requested transforms on the file buffer (as + * determined by the ConversionTable and the FileType). + * + ******************************************************************************/ + +void +AsConvertFile ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *FileBuffer, + char *Filename, + ACPI_NATIVE_INT FileType) +{ + UINT32 i; + UINT32 Functions; + ACPI_STRING_TABLE *StringTable; + ACPI_IDENTIFIER_TABLE *ConditionalTable; + ACPI_IDENTIFIER_TABLE *LineTable; + ACPI_IDENTIFIER_TABLE *MacroTable; + ACPI_TYPED_IDENTIFIER_TABLE *StructTable; + + + switch (FileType) + { + case FILE_TYPE_SOURCE: + Functions = ConversionTable->SourceFunctions; + StringTable = ConversionTable->SourceStringTable; + LineTable = ConversionTable->SourceLineTable; + ConditionalTable = ConversionTable->SourceConditionalTable; + MacroTable = ConversionTable->SourceMacroTable; + StructTable = ConversionTable->SourceStructTable; + break; + + case FILE_TYPE_HEADER: + Functions = ConversionTable->HeaderFunctions; + StringTable = ConversionTable->HeaderStringTable; + LineTable = ConversionTable->HeaderLineTable; + ConditionalTable = ConversionTable->HeaderConditionalTable; + MacroTable = ConversionTable->HeaderMacroTable; + StructTable = ConversionTable->HeaderStructTable; + break; + + default: + printf ("Unknown file type, cannot process\n"); + return; + } + + + Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs"); + Gbl_Files++; + VERBOSE_PRINT (("Processing %u bytes\n", + (unsigned int) strlen (FileBuffer))); + + if (ConversionTable->LowerCaseTable) + { + for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++) + { + AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier, + FileBuffer); + } + } + + /* Process all the string replacements */ + + if (StringTable) + { + for (i = 0; StringTable[i].Target; i++) + { + AsReplaceString (StringTable[i].Target, StringTable[i].Replacement, + StringTable[i].Type, FileBuffer); + } + } + + if (LineTable) + { + for (i = 0; LineTable[i].Identifier; i++) + { + AsRemoveLine (FileBuffer, LineTable[i].Identifier); + } + } + + if (ConditionalTable) + { + for (i = 0; ConditionalTable[i].Identifier; i++) + { + AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier); + } + } + + if (MacroTable) + { + for (i = 0; MacroTable[i].Identifier; i++) + { + AsRemoveMacro (FileBuffer, MacroTable[i].Identifier); + } + } + + if (StructTable) + { + for (i = 0; StructTable[i].Identifier; i++) + { + AsInsertPrefix (FileBuffer, StructTable[i].Identifier, StructTable[i].Type); + } + } + + /* Process the function table */ + + for (i = 0; i < 32; i++) + { + /* Decode the function bitmap */ + + switch ((1 << i) & Functions) + { + case 0: + /* This function not configured */ + break; + + + case CVT_COUNT_TABS: + + AsCountTabs (FileBuffer, Filename); + break; + + + case CVT_COUNT_NON_ANSI_COMMENTS: + + AsCountNonAnsiComments (FileBuffer, Filename); + break; + + + case CVT_CHECK_BRACES: + + AsCheckForBraces (FileBuffer, Filename); + break; + + + case CVT_TRIM_LINES: + + AsTrimLines (FileBuffer, Filename); + break; + + + case CVT_COUNT_LINES: + + AsCountSourceLines (FileBuffer, Filename); + break; + + + case CVT_BRACES_ON_SAME_LINE: + + AsBracesOnSameLine (FileBuffer); + break; + + + case CVT_MIXED_CASE_TO_UNDERSCORES: + + AsMixedCaseToUnderscores (FileBuffer); + break; + + + case CVT_LOWER_CASE_IDENTIFIERS: + + AsLowerCaseIdentifiers (FileBuffer); + break; + + + case CVT_REMOVE_DEBUG_MACROS: + + AsRemoveDebugMacros (FileBuffer); + break; + + + case CVT_TRIM_WHITESPACE: + + AsTrimWhitespace (FileBuffer); + break; + + + case CVT_REMOVE_EMPTY_BLOCKS: + + AsRemoveEmptyBlocks (FileBuffer, Filename); + break; + + + case CVT_REDUCE_TYPEDEFS: + + AsReduceTypedefs (FileBuffer, "typedef union"); + AsReduceTypedefs (FileBuffer, "typedef struct"); + break; + + + case CVT_SPACES_TO_TABS4: + + AsTabify4 (FileBuffer); + break; + + + case CVT_SPACES_TO_TABS8: + + AsTabify8 (FileBuffer); + break; + + case CVT_COUNT_SHORTMULTILINE_COMMENTS: + +#ifdef ACPI_FUTURE_IMPLEMENTATION + AsTrimComments (FileBuffer, Filename); +#endif + break; + + default: + + printf ("Unknown conversion subfunction opcode\n"); + break; + } + } + + if (ConversionTable->NewHeader) + { + AsReplaceHeader (FileBuffer, ConversionTable->NewHeader); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsProcessOneFile + * + * DESCRIPTION: Process one source file. The file is opened, read entirely + * into a buffer, converted, then written to a new file. + * + ******************************************************************************/ + +ACPI_NATIVE_INT +AsProcessOneFile ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *SourcePath, + char *TargetPath, + int MaxPathLength, + char *Filename, + ACPI_NATIVE_INT FileType) +{ + char *Pathname; + char *OutPathname = NULL; + + + /* Allocate a file pathname buffer for both source and target */ + + Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1); + if (!Pathname) + { + printf ("Could not allocate buffer for file pathnames\n"); + return -1; + } + + Gbl_FileType = FileType; + + /* Generate the source pathname and read the file */ + + if (SourcePath) + { + strcpy (Pathname, SourcePath); + strcat (Pathname, "/"); + } + + strcat (Pathname, Filename); + + if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize)) + { + return -1; + } + + Gbl_HeaderSize = 0; + if (strstr (Filename, ".asl")) + { + Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */ + } + else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE)) + { + Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */ + } + else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE)) + { + Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */ + } + + /* Process the file in the buffer */ + + Gbl_MadeChanges = FALSE; + if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds) + { + /* + * All lone LFs will be converted to CR/LF + * (when file is written, Windows version only) + */ + printf ("Converting lone linefeeds\n"); + Gbl_MadeChanges = TRUE; + } + + AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType); + + if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT)) + { + if (!(Gbl_Overwrite && !Gbl_MadeChanges)) + { + /* Generate the target pathname and write the file */ + + OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1); + if (!OutPathname) + { + printf ("Could not allocate buffer for file pathnames\n"); + return -1; + } + + strcpy (OutPathname, TargetPath); + if (SourcePath) + { + strcat (OutPathname, "/"); + strcat (OutPathname, Filename); + } + + AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags); + } + } + + free (Gbl_FileBuffer); + free (Pathname); + if (OutPathname) + { + free (OutPathname); + } + + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AsCheckForDirectory + * + * DESCRIPTION: Check if the current file is a valid directory. If not, + * construct the full pathname for the source and target paths. + * Checks for the dot and dot-dot files (they are ignored) + * + ******************************************************************************/ + +ACPI_NATIVE_INT +AsCheckForDirectory ( + char *SourceDirPath, + char *TargetDirPath, + char *Filename, + char **SourcePath, + char **TargetPath) +{ + char *SrcPath; + char *TgtPath; + + + if (!(strcmp (Filename, ".")) || + !(strcmp (Filename, ".."))) + { + return -1; + } + + SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1); + if (!SrcPath) + { + printf ("Could not allocate buffer for directory source pathname\n"); + return -1; + } + + TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1); + if (!TgtPath) + { + printf ("Could not allocate buffer for directory target pathname\n"); + free (SrcPath); + return -1; + } + + strcpy (SrcPath, SourceDirPath); + strcat (SrcPath, "/"); + strcat (SrcPath, Filename); + + strcpy (TgtPath, TargetDirPath); + strcat (TgtPath, "/"); + strcat (TgtPath, Filename); + + *SourcePath = SrcPath; + *TargetPath = TgtPath; + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AsGetFile + * + * DESCRIPTION: Open a file and read it entirely into a an allocated buffer + * + ******************************************************************************/ + +int +AsGetFile ( + char *Filename, + char **FileBuffer, + UINT32 *FileSize) +{ + + int FileHandle; + UINT32 Size; + char *Buffer; + + + /* Binary mode leaves CR/LF pairs */ + + FileHandle = open (Filename, O_BINARY | O_RDONLY); + if (!FileHandle) + { + printf ("Could not open %s\n", Filename); + return -1; + } + + if (fstat (FileHandle, &Gbl_StatBuf)) + { + printf ("Could not get file status for %s\n", Filename); + goto ErrorExit; + } + + /* + * Create a buffer for the entire file + * Add plenty extra buffer to accomodate string replacements + */ + Size = Gbl_StatBuf.st_size; + Gbl_TotalSize += Size; + + Buffer = calloc (Size * 2, 1); + if (!Buffer) + { + printf ("Could not allocate buffer of size %u\n", Size * 2); + goto ErrorExit; + } + + /* Read the entire file */ + + Size = read (FileHandle, Buffer, Size); + if (Size == -1) + { + printf ("Could not read the input file %s\n", Filename); + goto ErrorExit; + } + + Buffer [Size] = 0; /* Null terminate the buffer */ + close (FileHandle); + + /* Check for unix contamination */ + + Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer); + + /* + * Convert all CR/LF pairs to LF only. We do this locally so that + * this code is portable across operating systems. + */ + AsConvertToLineFeeds (Buffer); + + *FileBuffer = Buffer; + *FileSize = Size; + + return 0; + + +ErrorExit: + + close (FileHandle); + return -1; +} + + +/****************************************************************************** + * + * FUNCTION: AsPutFile + * + * DESCRIPTION: Create a new output file and write the entire contents of the + * buffer to the new file. Buffer must be a zero terminated string + * + ******************************************************************************/ + +int +AsPutFile ( + char *Pathname, + char *FileBuffer, + UINT32 SystemFlags) +{ + UINT32 FileSize; + int DestHandle; + int OpenFlags; + + + /* Create the target file */ + + OpenFlags = O_TRUNC | O_CREAT | O_WRONLY | O_BINARY; + + if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS)) + { + /* Put back the CR before each LF */ + + AsInsertCarriageReturns (FileBuffer); + } + + DestHandle = open (Pathname, OpenFlags, S_IREAD | S_IWRITE); + if (DestHandle == -1) + { + perror ("Could not create destination file"); + printf ("Could not create destination file \"%s\"\n", Pathname); + return -1; + } + + /* Write the buffer to the file */ + + FileSize = strlen (FileBuffer); + write (DestHandle, FileBuffer, FileSize); + + close (DestHandle); + + return 0; +} + + diff --git a/source/tools/acpisrc/asmain.c b/source/tools/acpisrc/asmain.c new file mode 100644 index 000000000000..baf4e2fc34c7 --- /dev/null +++ b/source/tools/acpisrc/asmain.c @@ -0,0 +1,457 @@ + +/****************************************************************************** + * + * Module Name: asmain - Main module for the acpi source processor utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpisrc.h" +#include "acapps.h" + +/* Local prototypes */ + +int +AsStricmp ( + char *String1, + char *String2); + +int +AsExaminePaths ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *Source, + char *Target, + UINT32 *SourceFileType); + +void +AsDisplayStats ( + void); + +void +AsDisplayUsage ( + void); + +/* Globals */ + +UINT32 Gbl_Tabs = 0; +UINT32 Gbl_MissingBraces = 0; +UINT32 Gbl_NonAnsiComments = 0; +UINT32 Gbl_Files = 0; +UINT32 Gbl_WhiteLines = 0; +UINT32 Gbl_CommentLines = 0; +UINT32 Gbl_SourceLines = 0; +UINT32 Gbl_LongLines = 0; +UINT32 Gbl_TotalLines = 0; +UINT32 Gbl_TotalSize = 0; +UINT32 Gbl_HeaderLines = 0; +UINT32 Gbl_HeaderSize = 0; +void *Gbl_StructDefs = NULL; + +struct stat Gbl_StatBuf; +char *Gbl_FileBuffer; +UINT32 Gbl_FileSize; +UINT32 Gbl_FileType; +BOOLEAN Gbl_VerboseMode = FALSE; +BOOLEAN Gbl_QuietMode = FALSE; +BOOLEAN Gbl_BatchMode = FALSE; +BOOLEAN Gbl_DebugStatementsMode = FALSE; +BOOLEAN Gbl_MadeChanges = FALSE; +BOOLEAN Gbl_Overwrite = FALSE; +BOOLEAN Gbl_WidenDeclarations = FALSE; +BOOLEAN Gbl_IgnoreLoneLineFeeds = FALSE; +BOOLEAN Gbl_HasLoneLineFeeds = FALSE; + + +/****************************************************************************** + * + * FUNCTION: AsStricmp + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int +AsStricmp ( + char *String1, + char *String2) +{ + int c1; + int c2; + + + do + { + c1 = tolower ((int) *String1); + c2 = tolower ((int) *String2); + + String1++; + String2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} + + +/****************************************************************************** + * + * FUNCTION: AsExaminePaths + * + * DESCRIPTION: Source and Target pathname verification and handling + * + ******************************************************************************/ + +int +AsExaminePaths ( + ACPI_CONVERSION_TABLE *ConversionTable, + char *Source, + char *Target, + UINT32 *SourceFileType) +{ + int Status; + char Response; + + + Status = stat (Source, &Gbl_StatBuf); + if (Status) + { + printf ("Source path \"%s\" does not exist\n", Source); + return -1; + } + + /* Return the filetype -- file or a directory */ + + *SourceFileType = 0; + if (Gbl_StatBuf.st_mode & S_IFDIR) + { + *SourceFileType = S_IFDIR; + } + + /* + * If we are in no-output mode or in batch mode, we are done + */ + if ((ConversionTable->Flags & FLG_NO_FILE_OUTPUT) || + (Gbl_BatchMode)) + { + return 0; + } + + if (!AsStricmp (Source, Target)) + { + printf ("Target path is the same as the source path, overwrite?\n"); + scanf ("%c", &Response); + + /* Check response */ + + if ((char) Response != 'y') + { + return -1; + } + + Gbl_Overwrite = TRUE; + } + else + { + Status = stat (Target, &Gbl_StatBuf); + if (!Status) + { + printf ("Target path already exists, overwrite?\n"); + scanf ("%c", &Response); + + /* Check response */ + + if ((char) Response != 'y') + { + return -1; + } + } + } + + return 0; +} + + +/****************************************************************************** + * + * FUNCTION: AsDisplayStats + * + * DESCRIPTION: Display global statistics gathered during translation + * + ******************************************************************************/ + +void +AsDisplayStats ( + void) +{ + + if (Gbl_QuietMode) + { + return; + } + + printf ("\nAcpiSrc statistics:\n\n"); + printf ("%8u Files processed\n", Gbl_Files); + + if (!Gbl_Files) + { + return; + } + + printf ("%8u Total bytes (%.1fK/file)\n", + Gbl_TotalSize, ((double) Gbl_TotalSize/Gbl_Files)/1024); + printf ("%8u Tabs found\n", Gbl_Tabs); + printf ("%8u Missing if/else braces\n", Gbl_MissingBraces); + printf ("%8u Non-ANSI comments found\n", Gbl_NonAnsiComments); + printf ("%8u Total Lines\n", Gbl_TotalLines); + printf ("%8u Lines of code\n", Gbl_SourceLines); + printf ("%8u Lines of non-comment whitespace\n", Gbl_WhiteLines); + printf ("%8u Lines of comments\n", Gbl_CommentLines); + printf ("%8u Long lines found\n", Gbl_LongLines); + printf ("%8.1f Ratio of code to whitespace\n", + ((float) Gbl_SourceLines / (float) Gbl_WhiteLines)); + printf ("%8.1f Ratio of code to comments\n", + ((float) Gbl_SourceLines / (float) (Gbl_CommentLines + Gbl_NonAnsiComments))); + + if (!Gbl_TotalLines) + { + return; + } + + printf (" %u%% code, %u%% comments, %u%% whitespace, %u%% headers\n", + (Gbl_SourceLines * 100) / Gbl_TotalLines, + (Gbl_CommentLines * 100) / Gbl_TotalLines, + (Gbl_WhiteLines * 100) / Gbl_TotalLines, + (Gbl_HeaderLines * 100) / Gbl_TotalLines); + return; +} + + +/****************************************************************************** + * + * FUNCTION: AsDisplayUsage + * + * DESCRIPTION: Usage message + * + ******************************************************************************/ + +void +AsDisplayUsage ( + void) +{ + + ACPI_USAGE_HEADER ("acpisrc [-c|l|u] [-dsvy] "); + + ACPI_OPTION ("-c", "Generate cleaned version of the source"); + ACPI_OPTION ("-h", "Insert dual-license header into all modules"); + ACPI_OPTION ("-l", "Generate Linux version of the source"); + ACPI_OPTION ("-u", "Generate Custom source translation"); + + printf ("\n"); + ACPI_OPTION ("-d", "Leave debug statements in code"); + ACPI_OPTION ("-s", "Generate source statistics only"); + ACPI_OPTION ("-v", "Verbose mode"); + ACPI_OPTION ("-y", "Suppress file overwrite prompts"); +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * DESCRIPTION: C main function + * + ******************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char *argv[]) +{ + int j; + ACPI_CONVERSION_TABLE *ConversionTable = NULL; + char *SourcePath; + char *TargetPath; + UINT32 FileType; + + + printf (ACPI_COMMON_SIGNON ("ACPI Source Code Conversion Utility")); + + if (argc < 2) + { + AsDisplayUsage (); + return 0; + } + + /* Command line options */ + + while ((j = AcpiGetopt (argc, argv, "cdhlqsuvy")) != EOF) switch(j) + { + case 'l': + /* Linux code generation */ + + printf ("Creating Linux source code\n"); + ConversionTable = &LinuxConversionTable; + Gbl_WidenDeclarations = TRUE; + Gbl_IgnoreLoneLineFeeds = TRUE; + break; + + case 'c': + /* Cleanup code */ + + printf ("Code cleanup\n"); + ConversionTable = &CleanupConversionTable; + break; + + case 'h': + /* Inject Dual-license header */ + + printf ("Inserting Dual-license header to all modules\n"); + ConversionTable = &LicenseConversionTable; + break; + + case 's': + /* Statistics only */ + + break; + + case 'u': + /* custom conversion */ + + printf ("Custom source translation\n"); + ConversionTable = &CustomConversionTable; + break; + + case 'v': + /* Verbose mode */ + + Gbl_VerboseMode = TRUE; + break; + + case 'y': + /* Batch mode */ + + Gbl_BatchMode = TRUE; + break; + + case 'd': + /* Leave debug statements in */ + + Gbl_DebugStatementsMode = TRUE; + break; + + case 'q': + /* Quiet mode */ + + Gbl_QuietMode = TRUE; + break; + + default: + AsDisplayUsage (); + return -1; + } + + + SourcePath = argv[AcpiGbl_Optind]; + if (!SourcePath) + { + printf ("Missing source path\n"); + AsDisplayUsage (); + return -1; + } + + TargetPath = argv[AcpiGbl_Optind+1]; + + if (!ConversionTable) + { + /* Just generate statistics. Ignore target path */ + + TargetPath = SourcePath; + + printf ("Source code statistics only\n"); + ConversionTable = &StatsConversionTable; + } + else if (!TargetPath) + { + TargetPath = SourcePath; + } + + if (Gbl_DebugStatementsMode) + { + ConversionTable->SourceFunctions &= ~CVT_REMOVE_DEBUG_MACROS; + } + + /* Check source and target paths and files */ + + if (AsExaminePaths (ConversionTable, SourcePath, TargetPath, &FileType)) + { + return -1; + } + + /* Source/target can be either directories or a files */ + + if (FileType == S_IFDIR) + { + /* Process the directory tree */ + + AsProcessTree (ConversionTable, SourcePath, TargetPath); + } + else + { + /* Process a single file */ + + /* Differentiate between source and header files */ + + if (strstr (SourcePath, ".h")) + { + AsProcessOneFile (ConversionTable, NULL, TargetPath, 0, SourcePath, FILE_TYPE_HEADER); + } + else + { + AsProcessOneFile (ConversionTable, NULL, TargetPath, 0, SourcePath, FILE_TYPE_SOURCE); + } + } + + /* Always display final summary and stats */ + + AsDisplayStats (); + + return 0; +} diff --git a/source/tools/acpisrc/asremove.c b/source/tools/acpisrc/asremove.c new file mode 100644 index 000000000000..8fe29e158a2a --- /dev/null +++ b/source/tools/acpisrc/asremove.c @@ -0,0 +1,616 @@ + +/****************************************************************************** + * + * Module Name: asremove - Source conversion - removal functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpisrc.h" + +/* Local prototypes */ + +void +AsRemoveStatement ( + char *Buffer, + char *Keyword, + UINT32 Type); + + +/****************************************************************************** + * + * FUNCTION: AsRemoveStatement + * + * DESCRIPTION: Remove all statements that contain the given keyword. + * Limitations: Removes text from the start of the line that + * contains the keyword to the next semicolon. Currently + * doesn't ignore comments. + * + ******************************************************************************/ + +void +AsRemoveStatement ( + char *Buffer, + char *Keyword, + UINT32 Type) +{ + char *SubString; + char *SubBuffer; + int KeywordLength; + + + KeywordLength = strlen (Keyword); + SubBuffer = Buffer; + SubString = Buffer; + + + while (SubString) + { + SubString = strstr (SubBuffer, Keyword); + + if (SubString) + { + SubBuffer = SubString; + + if ((Type == REPLACE_WHOLE_WORD) && + (!AsMatchExactWord (SubString, KeywordLength))) + { + SubBuffer++; + continue; + } + + /* Find start of this line */ + + while (*SubString != '\n') + { + SubString--; + } + SubString++; + + /* Find end of this statement */ + + SubBuffer = AsSkipPastChar (SubBuffer, ';'); + if (!SubBuffer) + { + return; + } + + /* Find end of this line */ + + SubBuffer = AsSkipPastChar (SubBuffer, '\n'); + if (!SubBuffer) + { + return; + } + + /* If next line is blank, remove it too */ + + if (*SubBuffer == '\n') + { + SubBuffer++; + } + + /* Remove the lines */ + + SubBuffer = AsRemoveData (SubString, SubBuffer); + } + } +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveConditionalCompile + * + * DESCRIPTION: Remove a "#ifdef" statement, and all text that it encompasses. + * Limitations: cannot handle nested ifdefs. + * + ******************************************************************************/ + +void +AsRemoveConditionalCompile ( + char *Buffer, + char *Keyword) +{ + char *SubString; + char *SubBuffer; + char *IfPtr; + char *EndifPtr; + char *ElsePtr; + char *Comment; + int KeywordLength; + + + KeywordLength = strlen (Keyword); + SubBuffer = Buffer; + SubString = Buffer; + + + while (SubString) + { + SubBuffer = strstr (SubString, Keyword); + if (!SubBuffer) + { + return; + } + + /* + * Check for translation escape string -- means to ignore + * blocks of code while replacing + */ + Comment = strstr (SubString, AS_START_IGNORE); + + if ((Comment) && + (Comment < SubBuffer)) + { + SubString = strstr (Comment, AS_STOP_IGNORE); + if (!SubString) + { + return; + } + + SubString += 3; + continue; + } + + /* Check for ordinary comment */ + + Comment = strstr (SubString, "/*"); + + if ((Comment) && + (Comment < SubBuffer)) + { + SubString = strstr (Comment, "*/"); + if (!SubString) + { + return; + } + + SubString += 2; + continue; + } + + SubString = SubBuffer; + if (!AsMatchExactWord (SubString, KeywordLength)) + { + SubString++; + continue; + } + + /* Find start of this line */ + + while (*SubString != '\n' && (SubString > Buffer)) + { + SubString--; + } + SubString++; + + /* Find the "#ifxxxx" */ + + IfPtr = strstr (SubString, "#if"); + if (!IfPtr) + { + return; + } + + if (IfPtr > SubBuffer) + { + /* Not the right #if */ + + SubString = SubBuffer + strlen (Keyword); + continue; + } + + /* Find closing #endif or #else */ + + EndifPtr = strstr (SubBuffer, "#endif"); + if (!EndifPtr) + { + /* There has to be an #endif */ + + return; + } + + ElsePtr = strstr (SubBuffer, "#else"); + if ((ElsePtr) && + (EndifPtr > ElsePtr)) + { + /* This #ifdef contains an #else clause */ + /* Find end of this line */ + + SubBuffer = AsSkipPastChar (ElsePtr, '\n'); + if (!SubBuffer) + { + return; + } + + /* Remove the #ifdef .... #else code */ + + AsRemoveData (SubString, SubBuffer); + + /* Next, we will remove the #endif statement */ + + EndifPtr = strstr (SubString, "#endif"); + if (!EndifPtr) + { + /* There has to be an #endif */ + + return; + } + + SubString = EndifPtr; + } + + /* Remove the ... #endif part */ + /* Find end of this line */ + + SubBuffer = AsSkipPastChar (EndifPtr, '\n'); + if (!SubBuffer) + { + return; + } + + /* Remove the lines */ + + SubBuffer = AsRemoveData (SubString, SubBuffer); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveMacro + * + * DESCRIPTION: Remove every line that contains the keyword. Does not + * skip comments. + * + ******************************************************************************/ + +void +AsRemoveMacro ( + char *Buffer, + char *Keyword) +{ + char *SubString; + char *SubBuffer; + int NestLevel; + + + SubBuffer = Buffer; + SubString = Buffer; + + + while (SubString) + { + SubString = strstr (SubBuffer, Keyword); + + if (SubString) + { + SubBuffer = SubString; + + /* Find start of the macro parameters */ + + while (*SubString != '(') + { + SubString++; + } + SubString++; + + /* Remove the macro name and opening paren */ + + SubString = AsRemoveData (SubBuffer, SubString); + + NestLevel = 1; + while (*SubString) + { + if (*SubString == '(') + { + NestLevel++; + } + else if (*SubString == ')') + { + NestLevel--; + } + + SubString++; + + if (NestLevel == 0) + { + break; + } + } + + /* Remove the closing paren */ + + SubBuffer = AsRemoveData (SubString-1, SubString); + } + } +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveLine + * + * DESCRIPTION: Remove every line that contains the keyword. Does not + * skip comments. + * + ******************************************************************************/ + +void +AsRemoveLine ( + char *Buffer, + char *Keyword) +{ + char *SubString; + char *SubBuffer; + + + SubBuffer = Buffer; + SubString = Buffer; + + + while (SubString) + { + SubString = strstr (SubBuffer, Keyword); + + if (SubString) + { + SubBuffer = SubString; + + /* Find start of this line */ + + while (*SubString != '\n') + { + SubString--; + } + SubString++; + + /* Find end of this line */ + + SubBuffer = AsSkipPastChar (SubBuffer, '\n'); + if (!SubBuffer) + { + return; + } + + /* Remove the line */ + + SubBuffer = AsRemoveData (SubString, SubBuffer); + } + } +} + + +/****************************************************************************** + * + * FUNCTION: AsReduceTypedefs + * + * DESCRIPTION: Eliminate certain typedefs + * + ******************************************************************************/ + +void +AsReduceTypedefs ( + char *Buffer, + char *Keyword) +{ + char *SubString; + char *SubBuffer; + int NestLevel; + + + SubBuffer = Buffer; + SubString = Buffer; + + + while (SubString) + { + SubString = strstr (SubBuffer, Keyword); + + if (SubString) + { + /* Remove the typedef itself */ + + SubBuffer = SubString + strlen ("typedef") + 1; + SubBuffer = AsRemoveData (SubString, SubBuffer); + + /* Find the opening brace of the struct or union */ + + while (*SubString != '{') + { + SubString++; + } + SubString++; + + /* Find the closing brace. Handles nested braces */ + + NestLevel = 1; + while (*SubString) + { + if (*SubString == '{') + { + NestLevel++; + } + else if (*SubString == '}') + { + NestLevel--; + } + + SubString++; + + if (NestLevel == 0) + { + break; + } + } + + /* Remove an extra line feed if present */ + + if (!strncmp (SubString - 3, "\n\n", 2)) + { + *(SubString -2) = '}'; + SubString--; + } + + /* Find the end of the typedef name */ + + SubBuffer = AsSkipUntilChar (SubString, ';'); + + /* And remove the typedef name */ + + SubBuffer = AsRemoveData (SubString, SubBuffer); + } + } +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveEmptyBlocks + * + * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This + * can happen as a result of removing lines such as DEBUG_PRINT. + * + ******************************************************************************/ + +void +AsRemoveEmptyBlocks ( + char *Buffer, + char *Filename) +{ + char *SubBuffer; + char *BlockStart; + BOOLEAN EmptyBlock = TRUE; + BOOLEAN AnotherPassRequired = TRUE; + UINT32 BlockCount = 0; + + + while (AnotherPassRequired) + { + SubBuffer = Buffer; + AnotherPassRequired = FALSE; + + while (*SubBuffer) + { + if (*SubBuffer == '{') + { + BlockStart = SubBuffer; + EmptyBlock = TRUE; + + SubBuffer++; + while (*SubBuffer != '}') + { + if ((*SubBuffer != ' ') && + (*SubBuffer != '\n')) + { + EmptyBlock = FALSE; + break; + } + SubBuffer++; + } + + if (EmptyBlock) + { + /* Find start of the first line of the block */ + + while (*BlockStart != '\n') + { + BlockStart--; + } + + /* Find end of the last line of the block */ + + SubBuffer = AsSkipUntilChar (SubBuffer, '\n'); + if (!SubBuffer) + { + break; + } + + /* Remove the block */ + + SubBuffer = AsRemoveData (BlockStart, SubBuffer); + BlockCount++; + AnotherPassRequired = TRUE; + continue; + } + } + + SubBuffer++; + } + } + + if (BlockCount) + { + Gbl_MadeChanges = TRUE; + AsPrint ("Code blocks deleted", BlockCount, Filename); + } +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveDebugMacros + * + * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output. + * + ******************************************************************************/ + +void +AsRemoveDebugMacros ( + char *Buffer) +{ + AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT"); + + AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT", REPLACE_WHOLE_WORD); + AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW", REPLACE_WHOLE_WORD); + AsRemoveStatement (Buffer, "DEBUG_EXEC", REPLACE_WHOLE_WORD); + AsRemoveStatement (Buffer, "FUNCTION_ENTRY", REPLACE_WHOLE_WORD); + AsRemoveStatement (Buffer, "PROC_NAME", REPLACE_WHOLE_WORD); + AsRemoveStatement (Buffer, "FUNCTION_TRACE", REPLACE_SUBSTRINGS); + AsRemoveStatement (Buffer, "DUMP_", REPLACE_SUBSTRINGS); + + AsReplaceString ("return_VOID", "return", REPLACE_WHOLE_WORD, Buffer); + AsReplaceString ("return_PTR", "return", REPLACE_WHOLE_WORD, Buffer); + AsReplaceString ("return_ACPI_STATUS", "return", REPLACE_WHOLE_WORD, Buffer); + AsReplaceString ("return_acpi_status", "return", REPLACE_WHOLE_WORD, Buffer); + AsReplaceString ("return_VALUE", "return", REPLACE_WHOLE_WORD, Buffer); +} + + diff --git a/source/tools/acpisrc/astable.c b/source/tools/acpisrc/astable.c new file mode 100644 index 000000000000..a1d96d32a83a --- /dev/null +++ b/source/tools/acpisrc/astable.c @@ -0,0 +1,870 @@ + +/****************************************************************************** + * + * Module Name: astable - Tables used for source conversion + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#include "acpisrc.h" +#include "acapps.h" + + +/****************************************************************************** + * + * Standard/Common translation tables + * + ******************************************************************************/ + + +ACPI_STRING_TABLE StandardDataTypes[] = { + + /* Declarations first */ + + {"UINT32 ", "unsigned int", REPLACE_SUBSTRINGS}, + {"UINT16 ", "unsigned short", REPLACE_SUBSTRINGS}, + {"UINT8 ", "unsigned char", REPLACE_SUBSTRINGS}, + {"BOOLEAN ", "unsigned char", REPLACE_SUBSTRINGS}, + + /* Now do embedded typecasts */ + + {"UINT32", "unsigned int", REPLACE_SUBSTRINGS}, + {"UINT16", "unsigned short", REPLACE_SUBSTRINGS}, + {"UINT8", "unsigned char", REPLACE_SUBSTRINGS}, + {"BOOLEAN", "unsigned char", REPLACE_SUBSTRINGS}, + + {"INT32 ", "int ", REPLACE_SUBSTRINGS}, + {"INT32", "int", REPLACE_SUBSTRINGS}, + {"INT16", "short", REPLACE_SUBSTRINGS}, + {"INT8", "char", REPLACE_SUBSTRINGS}, + + /* Put back anything we broke (such as anything with _INT32_ in it) */ + + {"_int_", "_INT32_", REPLACE_SUBSTRINGS}, + {"_unsigned int_", "_UINT32_", REPLACE_SUBSTRINGS}, + {NULL, NULL, 0} +}; + + +/****************************************************************************** + * + * Linux-specific translation tables + * + ******************************************************************************/ + +char DualLicenseHeader[] = +"/*\n" +" * Copyright (C) 2000 - 2012, Intel Corp.\n" +" * All rights reserved.\n" +" *\n" +" * Redistribution and use in source and binary forms, with or without\n" +" * modification, are permitted provided that the following conditions\n" +" * are met:\n" +" * 1. Redistributions of source code must retain the above copyright\n" +" * notice, this list of conditions, and the following disclaimer,\n" +" * without modification.\n" +" * 2. Redistributions in binary form must reproduce at minimum a disclaimer\n" +" * substantially similar to the \"NO WARRANTY\" disclaimer below\n" +" * (\"Disclaimer\") and any redistribution must be conditioned upon\n" +" * including a substantially similar Disclaimer requirement for further\n" +" * binary redistribution.\n" +" * 3. Neither the names of the above-listed copyright holders nor the names\n" +" * of any contributors may be used to endorse or promote products derived\n" +" * from this software without specific prior written permission.\n" +" *\n" +" * Alternatively, this software may be distributed under the terms of the\n" +" * GNU General Public License (\"GPL\") version 2 as published by the Free\n" +" * Software Foundation.\n" +" *\n" +" * NO WARRANTY\n" +" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" +" * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" +" * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR\n" +" * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" +" * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n" +" * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" +" * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n" +" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n" +" * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n" +" * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" +" * POSSIBILITY OF SUCH DAMAGES.\n" +" */\n"; + +ACPI_STRING_TABLE LinuxDataTypes[] = { + +/* + * Extra space is added after the type so there is room to add "struct", "union", + * etc. when the existing struct typedefs are eliminated. + */ + + /* Declarations first - ACPI types and standard C types */ + + {"INT64 ", "s64 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"UINT64 ", "u64 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"UINT32 ", "u32 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"INT32 ", "s32 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"UINT16 ", "u16 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"INT16 ", "s16 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"UINT8 ", "u8 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"BOOLEAN ", "u8 ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"char ", "char ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"void ", "void ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"char * ", "char * ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"void * ", "void * ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"int ", "int ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"FILE ", "FILE ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + {"size_t ", "size_t ", REPLACE_WHOLE_WORD | EXTRA_INDENT_C}, + + /* Now do embedded typecasts */ + + {"UINT64", "u64", REPLACE_WHOLE_WORD}, + {"UINT32", "u32", REPLACE_WHOLE_WORD}, + {"UINT16", "u16", REPLACE_WHOLE_WORD}, + {"UINT8", "u8", REPLACE_WHOLE_WORD}, + {"BOOLEAN", "u8", REPLACE_WHOLE_WORD}, + + {"INT64 ", "s64 ", REPLACE_WHOLE_WORD}, + {"INT64", "s64", REPLACE_WHOLE_WORD}, + {"INT32 ", "s32 ", REPLACE_WHOLE_WORD}, + {"INT32", "s32", REPLACE_WHOLE_WORD}, + {"INT16 ", "s16 ", REPLACE_WHOLE_WORD}, + {"INT8 ", "s8 ", REPLACE_WHOLE_WORD}, + {"INT16", "s16", REPLACE_WHOLE_WORD}, + {"INT8", "s8", REPLACE_WHOLE_WORD}, + + /* Include file paths */ + + {"\"acpi.h\"", "", REPLACE_WHOLE_WORD}, + + {NULL, NULL, 0} +}; + +ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { + + {"ACPI_ADR_SPACE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_ADR_SPACE_SETUP", SRC_TYPE_SIMPLE}, + {"ACPI_ADR_SPACE_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_AML_OPERANDS", SRC_TYPE_UNION}, + {"ACPI_BIT_REGISTER_INFO", SRC_TYPE_STRUCT}, + {"ACPI_BUFFER", SRC_TYPE_STRUCT}, + {"ACPI_BUS_ATTRIBUTE", SRC_TYPE_STRUCT}, + {"ACPI_CACHE_T", SRC_TYPE_SIMPLE}, + {"ACPI_CMTABLE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_COMMON_FACS", SRC_TYPE_STRUCT}, + {"ACPI_COMMON_STATE", SRC_TYPE_STRUCT}, + {"ACPI_COMMON_DESCRIPTOR", SRC_TYPE_STRUCT}, + {"ACPI_COMPATIBLE_ID", SRC_TYPE_STRUCT}, + {"ACPI_CONNECTION_INFO", SRC_TYPE_STRUCT}, + {"ACPI_CONTROL_STATE", SRC_TYPE_STRUCT}, + {"ACPI_CONVERSION_TABLE", SRC_TYPE_STRUCT}, + {"ACPI_CPU_FLAGS", SRC_TYPE_SIMPLE}, + {"ACPI_CREATE_FIELD_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DB_METHOD_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DEBUG_MEM_BLOCK", SRC_TYPE_STRUCT}, + {"ACPI_DEBUG_MEM_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_DEBUG_PRINT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DESCRIPTOR", SRC_TYPE_UNION}, + {"ACPI_DEVICE_ID", SRC_TYPE_STRUCT}, + {"ACPI_DEVICE_ID_LIST", SRC_TYPE_STRUCT}, + {"ACPI_DEVICE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DEVICE_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DMTABLE_DATA", SRC_TYPE_STRUCT}, + {"ACPI_DMTABLE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_DMTABLE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_EVALUATE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_EVENT_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_EVENT_STATUS", SRC_TYPE_SIMPLE}, + {"ACPI_EVENT_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_EXCEPTION_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_EXDUMP_INFO", SRC_TYPE_STRUCT}, + {"ACPI_EXECUTE_OP", SRC_TYPE_SIMPLE}, + {"ACPI_EXECUTE_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_EXECUTE_WALK", SRC_TYPE_STRUCT}, + {"ACPI_EXTERNAL_LIST", SRC_TYPE_STRUCT}, + {"ACPI_EXTERNAL_FILE", SRC_TYPE_STRUCT}, + {"ACPI_FADT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_FADT_PM_INFO", SRC_TYPE_STRUCT}, + {"ACPI_FIELD_INFO", SRC_TYPE_STRUCT}, + {"ACPI_FIND_CONTEXT", SRC_TYPE_STRUCT}, + {"ACPI_FIXED_EVENT_HANDLER", SRC_TYPE_STRUCT}, + {"ACPI_FIXED_EVENT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GBL_EVENT_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_GENERIC_ADDRESS", SRC_TYPE_STRUCT}, + {"ACPI_GENERIC_STATE", SRC_TYPE_UNION}, + {"ACPI_GET_DEVICES_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_BLOCK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_GPE_DEVICE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_EVENT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_GPE_HANDLER_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_INDEX_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_REGISTER_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_GPE_XRUPT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_HANDLE", SRC_TYPE_SIMPLE}, + {"ACPI_HANDLER_INFO", SRC_TYPE_STRUCT}, + {"ACPI_INIT_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_INTERFACE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_IDENTIFIER_TABLE", SRC_TYPE_STRUCT}, + {"ACPI_INIT_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_INTEGER", SRC_TYPE_SIMPLE}, + {"ACPI_INTEGER_OVERLAY", SRC_TYPE_STRUCT}, + {"ACPI_INTEGRITY_INFO", SRC_TYPE_STRUCT}, + {"ACPI_INTERFACE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_INTERNAL_METHOD", SRC_TYPE_SIMPLE}, + {"ACPI_INTERPRETER_MODE", SRC_TYPE_SIMPLE}, + {"ACPI_IO_ADDRESS", SRC_TYPE_SIMPLE}, + {"ACPI_IO_ATTRIBUTE", SRC_TYPE_STRUCT}, + {"ACPI_MEM_SPACE_CONTEXT", SRC_TYPE_STRUCT}, + {"ACPI_MEMORY_ATTRIBUTE", SRC_TYPE_STRUCT}, + {"ACPI_MEMORY_LIST", SRC_TYPE_STRUCT}, + {"ACPI_MUTEX", SRC_TYPE_SIMPLE}, + {"ACPI_MUTEX_HANDLE", SRC_TYPE_SIMPLE}, + {"ACPI_MUTEX_INFO", SRC_TYPE_STRUCT}, + {"ACPI_NAME", SRC_TYPE_SIMPLE}, + {"ACPI_NAME_INFO", SRC_TYPE_STRUCT}, + {"ACPI_NAME_UNION", SRC_TYPE_UNION}, + {"ACPI_NAMESPACE_NODE", SRC_TYPE_STRUCT}, + {"ACPI_NAMESTRING_INFO", SRC_TYPE_STRUCT}, + {"ACPI_NATIVE_INT", SRC_TYPE_SIMPLE}, + {"ACPI_NATIVE_UINT", SRC_TYPE_SIMPLE}, + {"ACPI_NOTIFY_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_NOTIFY_INFO", SRC_TYPE_STRUCT}, + {"ACPI_NS_SEARCH_DATA", SRC_TYPE_STRUCT}, + {"ACPI_OBJ_INFO_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT", SRC_TYPE_UNION}, + {"ACPI_OBJECT_ADDR_HANDLER", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_BANK_FIELD", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_BUFFER", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_BUFFER_FIELD", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_CACHE_LIST", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_DATA", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_DEVICE", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_EVENT", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_EXTRA", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_FIELD_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_OBJECT_INDEX_FIELD", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_INTEGER", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_LIST", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_METHOD", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_MUTEX", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_NOTIFY_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_NOTIFY_HANDLER", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_PACKAGE", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_POWER_RESOURCE", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_PROCESSOR", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_REFERENCE", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_REGION", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_REGION_FIELD", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_STRING", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_THERMAL_ZONE", SRC_TYPE_STRUCT}, + {"ACPI_OBJECT_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_OBJECT_TYPE8", SRC_TYPE_SIMPLE}, + {"ACPI_OP_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_OPCODE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_OPERAND_OBJECT", SRC_TYPE_UNION}, + {"ACPI_OSD_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_OSD_EXEC_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_OWNER_ID", SRC_TYPE_SIMPLE}, + {"ACPI_PACKAGE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_PACKAGE_INFO2", SRC_TYPE_STRUCT}, + {"ACPI_PACKAGE_INFO3", SRC_TYPE_STRUCT}, + {"ACPI_PARSE_DOWNWARDS", SRC_TYPE_SIMPLE}, + {"ACPI_PARSE_OBJ_ASL", SRC_TYPE_STRUCT}, + {"ACPI_PARSE_OBJ_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_PARSE_OBJ_NAMED", SRC_TYPE_STRUCT}, + {"ACPI_PARSE_OBJECT", SRC_TYPE_UNION}, + {"ACPI_PARSE_STATE", SRC_TYPE_STRUCT}, + {"ACPI_PARSE_UPWARDS", SRC_TYPE_SIMPLE}, + {"ACPI_PARSE_VALUE", SRC_TYPE_UNION}, + {"ACPI_PCI_DEVICE", SRC_TYPE_STRUCT}, + {"ACPI_PCI_ID", SRC_TYPE_STRUCT}, + {"ACPI_PCI_ROUTING_TABLE", SRC_TYPE_STRUCT}, + {"ACPI_PHYSICAL_ADDRESS", SRC_TYPE_SIMPLE}, + {"ACPI_PKG_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_PKG_INFO", SRC_TYPE_STRUCT}, + {"ACPI_PKG_STATE", SRC_TYPE_STRUCT}, + {"ACPI_PMTT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_POINTER", SRC_TYPE_STRUCT}, + {"ACPI_POINTERS", SRC_TYPE_UNION}, + {"ACPI_PORT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_PREDEFINED_DATA", SRC_TYPE_STRUCT}, + {"ACPI_PREDEFINED_INFO", SRC_TYPE_UNION}, + {"ACPI_PREDEFINED_NAMES", SRC_TYPE_STRUCT}, + {"ACPI_PSCOPE_STATE", SRC_TYPE_STRUCT}, + {"ACPI_REPAIR_FUNCTION", SRC_TYPE_SIMPLE}, + {"ACPI_REPAIR_INFO", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_RESOURCE_ADDRESS", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_ADDRESS16", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_ADDRESS32", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_ADDRESS64", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_COMMON_SERIALBUS", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_EXTENDED_ADDRESS64", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_ATTRIBUTE", SRC_TYPE_UNION}, + {"ACPI_RESOURCE_DATA", SRC_TYPE_UNION}, + {"ACPI_RESOURCE_DMA", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_END_TAG", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_EXTENDED_IRQ", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_FIXED_DMA", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_FIXED_IO", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_FIXED_MEMORY32", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_GENERIC_REGISTER", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_GPIO", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_I2C_SERIALBUS", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_IO", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_IRQ", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_MEMORY24", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_MEMORY32", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_SOURCE", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_SPI_SERIALBUS", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_START_DEPENDENT", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_TAG", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_RESOURCE_UART_SERIALBUS", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_VENDOR", SRC_TYPE_STRUCT}, + {"ACPI_RESOURCE_VENDOR_TYPED", SRC_TYPE_STRUCT}, + {"ACPI_RESULT_VALUES", SRC_TYPE_STRUCT}, + {"ACPI_ROUND_UP_TO_32_BIT", SRC_TYPE_SIMPLE}, + {"ACPI_RSCONVERT_INFO", SRC_TYPE_STRUCT}, + {"ACPI_RSDUMP_INFO", SRC_TYPE_STRUCT}, + {"ACPI_RW_LOCK", SRC_TYPE_STRUCT}, + {"ACPI_S3PT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_SCOPE_STATE", SRC_TYPE_STRUCT}, + {"ACPI_SEMAPHORE", SRC_TYPE_SIMPLE}, + {"ACPI_SIGNAL_FATAL_INFO", SRC_TYPE_STRUCT}, + {"ACPI_SIZE", SRC_TYPE_SIMPLE}, + {"ACPI_SLEEP_FUNCTION", SRC_TYPE_SIMPLE}, + {"ACPI_SLEEP_FUNCTIONS", SRC_TYPE_STRUCT}, + {"ACPI_SPINLOCK", SRC_TYPE_SIMPLE}, + {"ACPI_STATISTICS", SRC_TYPE_STRUCT}, + {"ACPI_STATUS", SRC_TYPE_SIMPLE}, + {"ACPI_STRING", SRC_TYPE_SIMPLE}, + {"ACPI_STRING_TABLE", SRC_TYPE_STRUCT}, + {"ACPI_SUBTABLE_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_SYSTEM_INFO", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_DESC", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_TABLE_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_INFO", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_LIST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SUPPORT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_TAG_INFO", SRC_TYPE_STRUCT}, + {"ACPI_THREAD_ID", SRC_TYPE_SIMPLE}, + {"ACPI_THREAD_STATE", SRC_TYPE_STRUCT}, + {"ACPI_TYPED_IDENTIFIER_TABLE", SRC_TYPE_STRUCT}, + {"ACPI_UINTPTR_T", SRC_TYPE_SIMPLE}, + {"ACPI_UPDATE_STATE", SRC_TYPE_STRUCT}, + {"ACPI_UUID", SRC_TYPE_STRUCT}, + {"ACPI_VENDOR_UUID", SRC_TYPE_STRUCT}, + {"ACPI_VENDOR_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_WALK_AML_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_WALK_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_WALK_RESOURCE_CALLBACK", SRC_TYPE_SIMPLE}, + {"ACPI_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_WALK_STATE", SRC_TYPE_STRUCT}, + {"ACPI_WHEA_HEADER", SRC_TYPE_STRUCT}, + + {"ACPI_RS_LENGTH", SRC_TYPE_SIMPLE}, + {"ACPI_RSDESC_SIZE", SRC_TYPE_SIMPLE}, + + {"AML_RESOURCE", SRC_TYPE_UNION}, + {"AML_RESOURCE_ADDRESS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_ADDRESS16", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_ADDRESS32", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_ADDRESS64", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_COMMON_SERIALBUS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_DMA", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_END_DEPENDENT", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_END_TAG", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_EXTENDED_ADDRESS64", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_EXTENDED_IRQ", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_FIXED_DMA", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_FIXED_IO", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_FIXED_MEMORY32", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_GENERIC_REGISTER", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_GPIO", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_IO", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_I2C_SERIALBUS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_IRQ", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_IRQ_NOFLAGS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_LARGE_HEADER", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_MEMORY24", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_MEMORY32", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_SMALL_HEADER", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_SPI_SERIALBUS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_START_DEPENDENT", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_START_DEPENDENT_NOPRIO", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_UART_SERIALBUS", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_VENDOR_LARGE", SRC_TYPE_STRUCT}, + {"AML_RESOURCE_VENDOR_SMALL", SRC_TYPE_STRUCT}, + + {"APIC_HEADER", SRC_TYPE_STRUCT}, + {"ARGUMENT_INFO", SRC_TYPE_STRUCT}, + {"AE_DEBUG_REGIONS", SRC_TYPE_STRUCT}, + {"AE_REGION", SRC_TYPE_STRUCT}, + {"AE_TABLE_DESC", SRC_TYPE_STRUCT}, + {"ASL_ANALYSIS_WALK_INFO", SRC_TYPE_STRUCT}, + {"ASL_ERROR_MSG", SRC_TYPE_STRUCT}, + {"ASL_EVENT_INFO", SRC_TYPE_STRUCT}, + {"ASL_FILE_INFO", SRC_TYPE_STRUCT}, + {"ASL_FILE_STATUS", SRC_TYPE_STRUCT}, + {"ASL_INCLUDE_DIR", SRC_TYPE_STRUCT}, + {"ASL_LISTING_NODE", SRC_TYPE_STRUCT}, + {"ASL_MAPPING_ENTRY", SRC_TYPE_STRUCT}, + {"ASL_METHOD_INFO", SRC_TYPE_STRUCT}, + {"ASL_RESERVED_INFO", SRC_TYPE_STRUCT}, + {"ASL_RESOURCE_NODE", SRC_TYPE_STRUCT}, + {"ASL_WALK_CALLBACK", SRC_TYPE_SIMPLE}, + {"COMMAND_INFO", SRC_TYPE_STRUCT}, + {"UINT64_OVERLAY", SRC_TYPE_UNION}, + {"UINT64_STRUCT", SRC_TYPE_STRUCT}, + + /* + * Acpi table definition names. + */ + {"ACPI_TABLE_ASF", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_BERT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_BGRT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_BOOT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_CPEP", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_DBGP", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_DMAR", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_DRTM", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_ECDT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_EINJ", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_ERST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_FACS", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_FADT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_FPDT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_HEST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_HPET", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_IBFT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_IVRS", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MADT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MCFG", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MCHI", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MPST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MSCT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_PCCT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_RSDP", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_RSDT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MCHI", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_S3PT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SBST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SLIC", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SLIT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SPCR", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SPMI", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_SRAT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_TCPA", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_UEFI", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_WAET", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_WDAT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_WDDT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_WDRT", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_XSDT", SRC_TYPE_STRUCT}, + + {"ACPI_ASF_ADDRESS", SRC_TYPE_STRUCT}, + {"ACPI_ASF_ALERT", SRC_TYPE_STRUCT}, + {"ACPI_ASF_ALERT_DATA", SRC_TYPE_STRUCT}, + {"ACPI_ASF_CONTROL_DATA", SRC_TYPE_STRUCT}, + {"ACPI_ASF_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_ASF_INFO", SRC_TYPE_STRUCT}, + {"ACPI_ASF_REMOTE", SRC_TYPE_STRUCT}, + {"ACPI_ASF_RMCP", SRC_TYPE_STRUCT}, + {"ACPI_BERT_REGION", SRC_TYPE_STRUCT}, + {"ACPI_CPEP_POLLING", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_DEVICE_SCOPE", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_ATSR", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_RHSA", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_HARDWARE_UNIT", SRC_TYPE_STRUCT}, + {"ACPI_DMAR_RESERVED_MEMORY", SRC_TYPE_STRUCT}, + {"ACPI_EINJ_ENTRY", SRC_TYPE_STRUCT}, + {"ACPI_EINJ_TRIGGER", SRC_TYPE_STRUCT}, + {"ACPI_FPDT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_FPDT_BOOT", SRC_TYPE_STRUCT}, + {"ACPI_FPDT_S3PT_PTR", SRC_TYPE_STRUCT}, + {"ACPI_ERST_ENTRY", SRC_TYPE_STRUCT}, + {"ACPI_ERST_INFO", SRC_TYPE_STRUCT}, + {"ACPI_HEST_AER_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_HEST_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_HEST_NOTIFY", SRC_TYPE_STRUCT}, + {"ACPI_HEST_IA_ERROR_BANK", SRC_TYPE_STRUCT}, + {"ACPI_HEST_IA_MACHINE_CHECK", SRC_TYPE_STRUCT}, + {"ACPI_HEST_IA_CORRECTED", SRC_TYPE_STRUCT}, + {"ACPI_HEST_IA_NMI", SRC_TYPE_STRUCT}, + {"ACPI_HEST_AER_ROOT", SRC_TYPE_STRUCT}, + {"ACPI_HEST_AER", SRC_TYPE_STRUCT}, + {"ACPI_HEST_AER_BRIDGE", SRC_TYPE_STRUCT}, + {"ACPI_HEST_GENERIC", SRC_TYPE_STRUCT}, + {"ACPI_HEST_GENERIC_STATUS", SRC_TYPE_STRUCT}, + {"ACPI_HEST_GENERIC_DATA", SRC_TYPE_STRUCT}, + {"ACPI_IBFT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_IBFT_CONTROL", SRC_TYPE_STRUCT}, + {"ACPI_IBFT_INITIATOR", SRC_TYPE_STRUCT}, + {"ACPI_IBFT_NIC", SRC_TYPE_STRUCT}, + {"ACPI_IBFT_TARGET", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_HARDWARE", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_DE_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_DEVICE4", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_DEVICE8A", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_DEVICE8B", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_DEVICE8C", SRC_TYPE_STRUCT}, + {"ACPI_IVRS_MEMORY", SRC_TYPE_STRUCT}, + {"ACPI_MADT_ADDRESS_OVERRIDE", SRC_TYPE_STRUCT}, + {"ACPI_MADT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_MADT_IO_APIC", SRC_TYPE_STRUCT}, + {"ACPI_MADT_IO_SAPIC", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_APIC", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_APIC_NMI", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_APIC_OVERRIDE", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_SAPIC", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_X2APIC", SRC_TYPE_STRUCT}, + {"ACPI_MADT_LOCAL_X2APIC_NMI", SRC_TYPE_STRUCT}, + {"ACPI_MADT_GENERIC_DISTRIBUTOR", SRC_TYPE_STRUCT}, + {"ACPI_MADT_GENERIC_INTERRUPT", SRC_TYPE_STRUCT}, + {"ACPI_MADT_INTERRUPT_OVERRIDE", SRC_TYPE_STRUCT}, + {"ACPI_MADT_INTERRUPT_SOURCE", SRC_TYPE_STRUCT}, + {"ACPI_MADT_NMI_SOURCE", SRC_TYPE_STRUCT}, + {"ACPI_MADT_PROCESSOR_APIC", SRC_TYPE_STRUCT}, + {"ACPI_MPST_COMPONENT", SRC_TYPE_STRUCT}, + {"ACPI_MPST_DATA_HDR", SRC_TYPE_STRUCT}, + {"ACPI_MPST_POWER_DATA", SRC_TYPE_STRUCT}, + {"ACPI_MPST_POWER_NODE", SRC_TYPE_STRUCT}, + {"ACPI_MPST_POWER_STATE", SRC_TYPE_STRUCT}, + {"ACPI_MCFG_ALLOCATION", SRC_TYPE_STRUCT}, + {"ACPI_MSCT_PROXIMITY", SRC_TYPE_STRUCT}, + {"ACPI_PCCT_SUBSPACE", SRC_TYPE_STRUCT}, + {"ACPI_RSDP_COMMON", SRC_TYPE_STRUCT}, + {"ACPI_RSDP_EXTENSION", SRC_TYPE_STRUCT}, + {"ACPI_S3PT_RESUME", SRC_TYPE_STRUCT}, + {"ACPI_S3PT_SUSPEND", SRC_TYPE_STRUCT}, + {"ACPI_SLIC_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_SLIC_KEY", SRC_TYPE_STRUCT}, + {"ACPI_SLIC_MARKER", SRC_TYPE_STRUCT}, + {"ACPI_SRAT_CPU_AFFINITY", SRC_TYPE_STRUCT}, + {"ACPI_SRAT_HEADER", SRC_TYPE_STRUCT}, + {"ACPI_SRAT_MEM_AFFINITY", SRC_TYPE_STRUCT}, + {"ACPI_SRAT_X2APIC_CPU_AFFINITY", SRC_TYPE_STRUCT}, + {"ACPI_WDAT_ENTRY", SRC_TYPE_STRUCT}, + + /* Data Table compiler */ + + {"DT_FIELD", SRC_TYPE_STRUCT}, + {"DT_SUBTABLE", SRC_TYPE_STRUCT}, + {"DT_WALK_CALLBACK", SRC_TYPE_SIMPLE}, + + /* AcpiHelp utility */ + + {"AH_AML_OPCODE", SRC_TYPE_STRUCT}, + {"AH_ASL_OPERATOR", SRC_TYPE_STRUCT}, + {"AH_ASL_KEYWORD", SRC_TYPE_STRUCT}, + {"AH_PREDEFINED_NAME", SRC_TYPE_STRUCT}, + + /* AcpiXtract utility */ + + {"AX_TABLE_INFO", SRC_TYPE_STRUCT}, + + {NULL, 0} +}; + + +ACPI_IDENTIFIER_TABLE LinuxAddStruct[] = { + {"acpi_namespace_node"}, + {"acpi_parse_object"}, + {"acpi_table_desc"}, + {"acpi_walk_state"}, + {NULL} +}; + + +ACPI_IDENTIFIER_TABLE LinuxEliminateMacros[] = { + + {"ACPI_GET_ADDRESS"}, + {"ACPI_VALID_ADDRESS"}, + {NULL} +}; + + +ACPI_IDENTIFIER_TABLE LinuxEliminateLines_C[] = { + + {"#define __"}, + {NULL} +}; + + +ACPI_IDENTIFIER_TABLE LinuxEliminateLines_H[] = { + + {NULL} +}; + + +ACPI_IDENTIFIER_TABLE LinuxConditionalIdentifiers[] = { + +/* {"ACPI_USE_STANDARD_HEADERS"}, */ + {"WIN32"}, + {"_MSC_VER"}, + {NULL} +}; + +ACPI_CONVERSION_TABLE LinuxConversionTable = { + + DualLicenseHeader, + FLG_NO_CARRIAGE_RETURNS | FLG_LOWERCASE_DIRNAMES, + + AcpiIdentifiers, + + /* C source files */ + + LinuxDataTypes, + LinuxEliminateLines_C, + NULL, + LinuxEliminateMacros, + AcpiIdentifiers, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_CHECK_BRACES | CVT_TRIM_LINES | CVT_BRACES_ON_SAME_LINE | + CVT_MIXED_CASE_TO_UNDERSCORES | CVT_LOWER_CASE_IDENTIFIERS | + CVT_REMOVE_DEBUG_MACROS | CVT_TRIM_WHITESPACE | + CVT_REMOVE_EMPTY_BLOCKS | CVT_SPACES_TO_TABS8), + + /* C header files */ + + LinuxDataTypes, + LinuxEliminateLines_H, + LinuxConditionalIdentifiers, + NULL, + AcpiIdentifiers, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_TRIM_LINES | CVT_MIXED_CASE_TO_UNDERSCORES | + CVT_LOWER_CASE_IDENTIFIERS | CVT_TRIM_WHITESPACE | + CVT_REMOVE_EMPTY_BLOCKS| CVT_REDUCE_TYPEDEFS | CVT_SPACES_TO_TABS8), +}; + + +/****************************************************************************** + * + * Code cleanup translation tables + * + ******************************************************************************/ + +ACPI_CONVERSION_TABLE CleanupConversionTable = { + + NULL, + FLG_DEFAULT_FLAGS, + NULL, + /* C source files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_CHECK_BRACES | CVT_TRIM_LINES | CVT_TRIM_WHITESPACE), + + /* C header files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_TRIM_LINES | CVT_TRIM_WHITESPACE), +}; + + +ACPI_CONVERSION_TABLE StatsConversionTable = { + + NULL, + FLG_NO_FILE_OUTPUT, + NULL, + + /* C source files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_COUNT_SHORTMULTILINE_COMMENTS), + + /* C header files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_COUNT_SHORTMULTILINE_COMMENTS), +}; + + +/****************************************************************************** + * + * Dual License injection translation table + * + ******************************************************************************/ + +ACPI_CONVERSION_TABLE LicenseConversionTable = { + + DualLicenseHeader, + FLG_DEFAULT_FLAGS, + NULL, + + /* C source files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_COUNT_SHORTMULTILINE_COMMENTS), + + /* C header files */ + + NULL, + NULL, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_COUNT_SHORTMULTILINE_COMMENTS), +}; + + +/****************************************************************************** + * + * Customizable translation tables + * + ******************************************************************************/ + +ACPI_STRING_TABLE CustomReplacements[] = { + + + {"(c) 1999 - 2012", "(c) 1999 - 2012", REPLACE_WHOLE_WORD}, /* Main ACPICA source */ + {"(c) 2006 - 2012", "(c) 2006 - 2012", REPLACE_WHOLE_WORD}, /* Test suites */ + +#if 0 + {"(ACPI_INTEGER)", "(UINT64)", REPLACE_WHOLE_WORD}, + {"ACPI_INTEGER ", "UINT64 ", REPLACE_WHOLE_WORD}, + {"ACPI_INTEGER", "UINT64", REPLACE_WHOLE_WORD}, + {"ACPI_INTEGER_MAX", "ACPI_UINT64_MAX", REPLACE_WHOLE_WORD}, + {"#include \"acpi.h\"", "#include \"acpi.h\"\n#include \"accommon.h\"", REPLACE_SUBSTRINGS}, + {"AcpiTbSumTable", "AcpiTbSumTable", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_BOOT", "ACPI_SIG_BOOT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_DBGP", "ACPI_SIG_DBGP", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_DSDT", "ACPI_SIG_DSDT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_ECDT", "ACPI_SIG_ECDT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_FACS", "ACPI_SIG_FACS", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_FADT", "ACPI_SIG_FADT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_HPET", "ACPI_SIG_HPET", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_MADT", "ACPI_SIG_MADT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_MCFG", "ACPI_SIG_MCFG", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_PSDT", "ACPI_SIG_PSDT", REPLACE_WHOLE_WORD}, + {"ACPI_NAME_RSDP", "ACPI_NAME_RSDP", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_RSDP", "ACPI_SIG_RSDP", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_RSDT", "ACPI_SIG_RSDT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SBST", "ACPI_SIG_SBST", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SLIT", "ACPI_SIG_SLIT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SPCR", "ACPI_SIG_SPCR", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SPIC", "ACPI_SIG_SPIC", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SPMI", "ACPI_SIG_SPMI", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SRAT", "ACPI_SIG_SRAT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_SSDT", "ACPI_SIG_SSDT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_TCPA", "ACPI_SIG_TCPA", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_WDRT", "ACPI_SIG_WDRT", REPLACE_WHOLE_WORD}, + {"ACPI_SIG_XSDT", "ACPI_SIG_XSDT", REPLACE_WHOLE_WORD}, + + {"ACPI_ALLOCATE_ZEROED", "ACPI_ALLOCATE_ZEROED", REPLACE_WHOLE_WORD}, + {"ACPI_ALLOCATE", "ACPI_ALLOCATE", REPLACE_WHOLE_WORD}, + {"ACPI_FREE", "ACPI_FREE", REPLACE_WHOLE_WORD}, + + "ACPI_NATIVE_UINT", "ACPI_NATIVE_UINT", REPLACE_WHOLE_WORD, + "ACPI_NATIVE_UINT *", "ACPI_NATIVE_UINT *", REPLACE_WHOLE_WORD, + "ACPI_NATIVE_UINT", "ACPI_NATIVE_UINT", REPLACE_WHOLE_WORD, + "ACPI_NATIVE_INT", "ACPI_NATIVE_INT", REPLACE_WHOLE_WORD, + "ACPI_NATIVE_INT *", "ACPI_NATIVE_INT *", REPLACE_WHOLE_WORD, + "ACPI_NATIVE_INT", "ACPI_NATIVE_INT", REPLACE_WHOLE_WORD, +#endif + + {NULL, NULL, 0} +}; + + +ACPI_CONVERSION_TABLE CustomConversionTable = { + + NULL, + FLG_DEFAULT_FLAGS, + NULL, + + /* C source files */ + + CustomReplacements, + LinuxEliminateLines_H, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_TRIM_LINES | CVT_TRIM_WHITESPACE), + + /* C header files */ + + CustomReplacements, + LinuxEliminateLines_H, + NULL, + NULL, + NULL, + (CVT_COUNT_TABS | CVT_COUNT_NON_ANSI_COMMENTS | CVT_COUNT_LINES | + CVT_TRIM_LINES | CVT_TRIM_WHITESPACE), +}; + diff --git a/source/tools/acpisrc/asutils.c b/source/tools/acpisrc/asutils.c new file mode 100644 index 000000000000..a596ea8cee06 --- /dev/null +++ b/source/tools/acpisrc/asutils.c @@ -0,0 +1,234 @@ + +/****************************************************************************** + * + * Module Name: asutils - common utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpisrc.h" + + +/****************************************************************************** + * + * FUNCTION: AsSkipUntilChar + * + * DESCRIPTION: Find the next instance of the input character + * + ******************************************************************************/ + +char * +AsSkipUntilChar ( + char *Buffer, + char Target) +{ + + while (*Buffer != Target) + { + if (!*Buffer) + { + return NULL; + } + + Buffer++; + } + + return (Buffer); +} + + +/****************************************************************************** + * + * FUNCTION: AsSkipPastChar + * + * DESCRIPTION: Find the next instance of the input character, return a buffer + * pointer to this character+1. + * + ******************************************************************************/ + +char * +AsSkipPastChar ( + char *Buffer, + char Target) +{ + + while (*Buffer != Target) + { + if (!*Buffer) + { + return NULL; + } + + Buffer++; + } + + Buffer++; + + return (Buffer); +} + + +/****************************************************************************** + * + * FUNCTION: AsReplaceData + * + * DESCRIPTION: This function inserts and removes data from the file buffer. + * if more data is inserted than is removed, the data in the buffer + * is moved to make room. If less data is inserted than is removed, + * the remaining data is moved to close the hole. + * + ******************************************************************************/ + +char * +AsReplaceData ( + char *Buffer, + UINT32 LengthToRemove, + char *BufferToAdd, + UINT32 LengthToAdd) +{ + UINT32 BufferLength; + + + /* + * Buffer is a string, so the length must include the terminating zero + */ + BufferLength = strlen (Buffer) + 1; + + if (LengthToRemove != LengthToAdd) + { + /* + * Move some of the existing data + * 1) If adding more bytes than removing, make room for the new data + * 2) if removing more bytes than adding, delete the extra space + */ + if (LengthToRemove > 0) + { + Gbl_MadeChanges = TRUE; + memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove), (BufferLength - LengthToRemove)); + } + } + + /* + * Now we can move in the new data + */ + if (LengthToAdd > 0) + { + Gbl_MadeChanges = TRUE; + memmove (Buffer, BufferToAdd, LengthToAdd); + } + + return (Buffer + LengthToAdd); +} + + +/****************************************************************************** + * + * FUNCTION: AsInsertData + * + * DESCRIPTION: This function inserts and removes data from the file buffer. + * if more data is inserted than is removed, the data in the buffer + * is moved to make room. If less data is inserted than is removed, + * the remaining data is moved to close the hole. + * + ******************************************************************************/ + +char * +AsInsertData ( + char *Buffer, + char *BufferToAdd, + UINT32 LengthToAdd) +{ + UINT32 BufferLength; + + + if (LengthToAdd > 0) + { + /* + * Buffer is a string, so the length must include the terminating zero + */ + BufferLength = strlen (Buffer) + 1; + + /* + * Move some of the existing data + * 1) If adding more bytes than removing, make room for the new data + * 2) if removing more bytes than adding, delete the extra space + */ + Gbl_MadeChanges = TRUE; + memmove ((Buffer + LengthToAdd), Buffer, BufferLength); + + /* + * Now we can move in the new data + */ + memmove (Buffer, BufferToAdd, LengthToAdd); + } + + return (Buffer + LengthToAdd); +} + + +/****************************************************************************** + * + * FUNCTION: AsRemoveData + * + * DESCRIPTION: This function inserts and removes data from the file buffer. + * if more data is inserted than is removed, the data in the buffer + * is moved to make room. If less data is inserted than is removed, + * the remaining data is moved to close the hole. + * + ******************************************************************************/ + +char * +AsRemoveData ( + char *StartPointer, + char *EndPointer) +{ + UINT32 BufferLength; + + + /* + * Buffer is a string, so the length must include the terminating zero + */ + BufferLength = strlen (EndPointer) + 1; + + Gbl_MadeChanges = TRUE; + memmove (StartPointer, EndPointer, BufferLength); + + return (StartPointer); +} + diff --git a/source/tools/acpixtract/Makefile b/source/tools/acpixtract/Makefile new file mode 100644 index 000000000000..d5db832a7394 --- /dev/null +++ b/source/tools/acpixtract/Makefile @@ -0,0 +1,116 @@ +# +# acpixtract - extract binary ACPI tables from acpidump text output +# +# NOTE: This makefile is intended to be used within the native +# ACPICA source tree. +# + +# +# Configuration +# Notes: +# gcc should be version 4 or greater, otherwise some of the options +# used will not be recognized. +# Global optimization flags (such as -O2, -Os) are not used, since +# they cause issues on some compilers. +# The _GNU_SOURCE symbol is required for many hosts. +# +PROG = acpixtract + +HOST = _LINUX +NOMAN = YES +COMPILE = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< + +ACPICA_SRC = ../../../source +ACPICA_COMMON = $(ACPICA_SRC)/common +ACPICA_TOOLS = $(ACPICA_SRC)/tools +ACPICA_OSL = $(ACPICA_SRC)/os_specific/service_layers +ACPICA_CORE = $(ACPICA_SRC)/components +ACPICA_INCLUDE = $(ACPICA_SRC)/include +ACPICA_DEBUGGER = $(ACPICA_CORE)/debugger +ACPICA_DISASSEMBLER = $(ACPICA_CORE)/disassembler +ACPICA_DISPATCHER = $(ACPICA_CORE)/dispatcher +ACPICA_EVENTS = $(ACPICA_CORE)/events +ACPICA_EXECUTER = $(ACPICA_CORE)/executer +ACPICA_HARDWARE = $(ACPICA_CORE)/hardware +ACPICA_NAMESPACE = $(ACPICA_CORE)/namespace +ACPICA_PARSER = $(ACPICA_CORE)/parser +ACPICA_RESOURCES = $(ACPICA_CORE)/resources +ACPICA_TABLES = $(ACPICA_CORE)/tables +ACPICA_UTILITIES = $(ACPICA_CORE)/utilities +ACPIXTRACT = $(ACPICA_TOOLS)/acpixtract +INSTALLDIR = /usr/bin +INSTALLPROG = cp --remove-destination $(PROG) $(INSTALLDIR) + +ACPICA_HEADERS = \ + $(wildcard $(ACPICA_INCLUDE)/*.h) \ + $(wildcard $(ACPICA_INCLUDE)/platform/*.h) + +# +# Search paths for source files +# +vpath %.c \ + $(ACPIXTRACT) \ + $(ACPICA_COMMON) + +HEADERS = \ + $(wildcard $(ACPIXTRACT)/*.h) + +OBJECTS = \ + acpixtract.o \ + axmain.o \ + getopt.o + +CFLAGS+= \ + -D$(HOST) \ + -D_GNU_SOURCE \ + -DACPI_XTRACT_APP \ + -I$(ACPICA_INCLUDE) + +CWARNINGFLAGS = \ + -ansi \ + -Wall \ + -Wbad-function-cast \ + -Wdeclaration-after-statement \ + -Werror \ + -Wformat=2 \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wstrict-aliasing=0 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wpointer-arith \ + -Wundef + +# +# gcc 4+ flags +# +CWARNINGFLAGS += \ + -Waddress \ + -Waggregate-return \ + -Wchar-subscripts \ + -Wempty-body \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-parameter-type \ + -Wnested-externs \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wredundant-decls \ + -Wtype-limits + +# +# Rules +# +$(PROG) : $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $(PROG) + $(COPYPROG) + +%.o : %.c $(HEADERS) $(ACPICA_HEADERS) + $(COMPILE) + +clean : + rm -f $(PROG) $(PROG).exe $(OBJECTS) + +install : + $(INSTALLPROG) diff --git a/source/tools/acpixtract/acpixtract.c b/source/tools/acpixtract/acpixtract.c new file mode 100644 index 000000000000..85ce346af152 --- /dev/null +++ b/source/tools/acpixtract/acpixtract.c @@ -0,0 +1,740 @@ +/****************************************************************************** + * + * Module Name: acpixtract - convert ascii ACPI tables to binary + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" + +#include +#include +#include +#include + +/* Local prototypes */ + +static void +AxStrlwr ( + char *String); + +static void +AxCheckAscii ( + char *Name, + int Count); + +static void +AxNormalizeSignature ( + char *Signature); + +static unsigned int +AxGetNextInstance ( + char *InputPathname, + char *Signature); + +static size_t +AxGetTableHeader ( + FILE *InputFile, + unsigned char *OutputData); + +static unsigned int +AxCountTableInstances ( + char *InputPathname, + char *Signature); + +int +AxExtractTables ( + char *InputPathname, + char *Signature, + unsigned int MinimumInstances); + +int +AxListTables ( + char *InputPathname); + +static size_t +AxConvertLine ( + char *InputLine, + unsigned char *OutputData); + + +typedef struct AxTableInfo +{ + UINT32 Signature; + unsigned int Instances; + unsigned int NextInstance; + struct AxTableInfo *Next; + +} AX_TABLE_INFO; + +/* Extraction states */ + +#define AX_STATE_FIND_HEADER 0 +#define AX_STATE_EXTRACT_DATA 1 + +/* Miscellaneous constants */ + +#define AX_LINE_BUFFER_SIZE 256 +#define AX_MIN_TABLE_NAME_LENGTH 6 /* strlen ("DSDT @") */ + + +static AX_TABLE_INFO *AxTableListHead = NULL; +static char Filename[16]; +static unsigned char Data[16]; +static char LineBuffer[AX_LINE_BUFFER_SIZE]; +static char HeaderBuffer[AX_LINE_BUFFER_SIZE]; +static char InstanceBuffer[AX_LINE_BUFFER_SIZE]; + + +/******************************************************************************* + * + * FUNCTION: AxStrlwr + * + * PARAMETERS: String - Ascii string + * + * RETURN: None + * + * DESCRIPTION: String lowercase function. + * + ******************************************************************************/ + +static void +AxStrlwr ( + char *String) +{ + + while (*String) + { + *String = (char) tolower ((int) *String); + String++; + } +} + + +/******************************************************************************* + * + * FUNCTION: AxCheckAscii + * + * PARAMETERS: Name - Ascii string, at least as long as Count + * Count - Number of characters to check + * + * RETURN: None + * + * DESCRIPTION: Ensure that the requested number of characters are printable + * Ascii characters. Sets non-printable and null chars to . + * + ******************************************************************************/ + +static void +AxCheckAscii ( + char *Name, + int Count) +{ + int i; + + + for (i = 0; i < Count; i++) + { + if (!Name[i] || !isprint ((int) Name[i])) + { + Name[i] = ' '; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AxNormalizeSignature + * + * PARAMETERS: Name - Ascii string containing an ACPI signature + * + * RETURN: None + * + * DESCRIPTION: Change "RSD PTR" to "RSDP" + * + ******************************************************************************/ + +static void +AxNormalizeSignature ( + char *Signature) +{ + + if (!strncmp (Signature, "RSD ", 4)) + { + Signature[3] = 'P'; + } +} + + +/****************************************************************************** + * + * FUNCTION: AxConvertLine + * + * PARAMETERS: InputLine - One line from the input acpidump file + * OutputData - Where the converted data is returned + * + * RETURN: The number of bytes actually converted + * + * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes) + * + ******************************************************************************/ + +static size_t +AxConvertLine ( + char *InputLine, + unsigned char *OutputData) +{ + char *End; + int BytesConverted; + int Converted[16]; + int i; + + + /* Terminate the input line at the end of the actual data (for sscanf) */ + + End = strstr (InputLine + 2, " "); + if (!End) + { + return (0); /* Don't understand the format */ + } + *End = 0; + + /* + * Convert one line of table data, of the form: + * : + * + * Example: + * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........ + */ + BytesConverted = sscanf (InputLine, + "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", + &Converted[0], &Converted[1], &Converted[2], &Converted[3], + &Converted[4], &Converted[5], &Converted[6], &Converted[7], + &Converted[8], &Converted[9], &Converted[10], &Converted[11], + &Converted[12], &Converted[13], &Converted[14], &Converted[15]); + + /* Pack converted data into a byte array */ + + for (i = 0; i < BytesConverted; i++) + { + OutputData[i] = (unsigned char) Converted[i]; + } + + return ((size_t) BytesConverted); +} + + +/****************************************************************************** + * + * FUNCTION: AxGetTableHeader + * + * PARAMETERS: InputFile - Handle for the input acpidump file + * OutputData - Where the table header is returned + * + * RETURN: The actual number of bytes converted + * + * DESCRIPTION: Extract and convert an ACPI table header + * + ******************************************************************************/ + +static size_t +AxGetTableHeader ( + FILE *InputFile, + unsigned char *OutputData) +{ + size_t BytesConverted; + size_t TotalConverted = 0; + int i; + + + /* Get the full 36 byte ACPI table header, requires 3 input text lines */ + + for (i = 0; i < 3; i++) + { + if (!fgets (HeaderBuffer, AX_LINE_BUFFER_SIZE, InputFile)) + { + return (TotalConverted); + } + + BytesConverted = AxConvertLine (HeaderBuffer, OutputData); + TotalConverted += BytesConverted; + OutputData += 16; + + if (BytesConverted != 16) + { + return (TotalConverted); + } + } + + return (TotalConverted); +} + + +/****************************************************************************** + * + * FUNCTION: AxCountTableInstances + * + * PARAMETERS: InputPathname - Filename for acpidump file + * Signature - Requested signature to count + * + * RETURN: The number of instances of the signature + * + * DESCRIPTION: Count the instances of tables with the given signature within + * the input acpidump file. + * + ******************************************************************************/ + +static unsigned int +AxCountTableInstances ( + char *InputPathname, + char *Signature) +{ + FILE *InputFile; + unsigned int Instances = 0; + + + InputFile = fopen (InputPathname, "rt"); + if (!InputFile) + { + printf ("Could not open %s\n", InputPathname); + return (0); + } + + /* Count the number of instances of this signature */ + + while (fgets (InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile)) + { + /* Ignore empty lines and lines that start with a space */ + + if ((InstanceBuffer[0] == ' ') || + (InstanceBuffer[0] == '\n')) + { + continue; + } + + AxNormalizeSignature (InstanceBuffer); + if (!strncmp (InstanceBuffer, Signature, 4)) + { + Instances++; + } + } + + fclose (InputFile); + return (Instances); +} + + +/****************************************************************************** + * + * FUNCTION: AxGetNextInstance + * + * PARAMETERS: InputPathname - Filename for acpidump file + * Signature - Requested ACPI signature + * + * RETURN: The next instance number for this signature. Zero if this + * is the first instance of this signature. + * + * DESCRIPTION: Get the next instance number of the specified table. If this + * is the first instance of the table, create a new instance + * block. Note: only SSDT and PSDT tables can have multiple + * instances. + * + ******************************************************************************/ + +static unsigned int +AxGetNextInstance ( + char *InputPathname, + char *Signature) +{ + AX_TABLE_INFO *Info; + + + Info = AxTableListHead; + while (Info) + { + if (*(UINT32 *) Signature == Info->Signature) + { + break; + } + + Info = Info->Next; + } + + if (!Info) + { + /* Signature not found, create new table info block */ + + Info = malloc (sizeof (AX_TABLE_INFO)); + if (!Info) + { + printf ("Could not allocate memory\n"); + exit (0); + } + + Info->Signature = *(UINT32 *) Signature; + Info->Instances = AxCountTableInstances (InputPathname, Signature); + Info->NextInstance = 1; + Info->Next = AxTableListHead; + AxTableListHead = Info; + } + + if (Info->Instances > 1) + { + return (Info->NextInstance++); + } + + return (0); +} + + +/****************************************************************************** + * + * FUNCTION: AxExtractTables + * + * PARAMETERS: InputPathname - Filename for acpidump file + * Signature - Requested ACPI signature to extract. + * NULL means extract ALL tables. + * MinimumInstances - Min instances that are acceptable + * + * RETURN: Status + * + * DESCRIPTION: Convert text ACPI tables to binary + * + ******************************************************************************/ + +int +AxExtractTables ( + char *InputPathname, + char *Signature, + unsigned int MinimumInstances) +{ + FILE *InputFile; + FILE *OutputFile = NULL; + size_t BytesWritten; + size_t TotalBytesWritten = 0; + size_t BytesConverted; + unsigned int State = AX_STATE_FIND_HEADER; + unsigned int FoundTable = 0; + unsigned int Instances = 0; + unsigned int ThisInstance; + char ThisSignature[4]; + int Status = 0; + + + /* Open input in text mode, output is in binary mode */ + + InputFile = fopen (InputPathname, "rt"); + if (!InputFile) + { + printf ("Could not open %s\n", InputPathname); + return (-1); + } + + if (Signature) + { + /* Are there enough instances of the table to continue? */ + + AxNormalizeSignature (Signature); + + Instances = AxCountTableInstances (InputPathname, Signature); + if (Instances < MinimumInstances) + { + printf ("Table %s was not found in %s\n", Signature, InputPathname); + Status = -1; + goto CleanupAndExit; + } + + if (Instances == 0) + { + goto CleanupAndExit; + } + } + + /* Convert all instances of the table to binary */ + + while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) + { + switch (State) + { + case AX_STATE_FIND_HEADER: + + /* Ignore lines that are too short to be header lines */ + + if (strlen (LineBuffer) < AX_MIN_TABLE_NAME_LENGTH) + { + continue; + } + + /* Ignore empty lines and lines that start with a space */ + + if ((LineBuffer[0] == ' ') || + (LineBuffer[0] == '\n')) + { + continue; + } + + /* + * Ignore lines that are not of the form @ . + * Examples of lines that must be supported: + * + * DSDT @ 0x737e4000 + * XSDT @ 0x737f2fff + * RSD PTR @ 0xf6cd0 + * SSDT @ (nil) + */ + if (!strstr (LineBuffer, " @ ")) + { + continue; + } + + AxNormalizeSignature (LineBuffer); + strncpy (ThisSignature, LineBuffer, 4); + + if (Signature) + { + /* Ignore signatures that don't match */ + + if (strncmp (ThisSignature, Signature, 4)) + { + continue; + } + } + + /* + * Get the instance number for this signature. Only the + * SSDT and PSDT tables can have multiple instances. + */ + ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); + + /* Build an output filename and create/open the output file */ + + if (ThisInstance > 0) + { + sprintf (Filename, "%4.4s%u.dat", ThisSignature, ThisInstance); + } + else + { + sprintf (Filename, "%4.4s.dat", ThisSignature); + } + + AxStrlwr (Filename); + OutputFile = fopen (Filename, "w+b"); + if (!OutputFile) + { + printf ("Could not open %s\n", Filename); + Status = -1; + goto CleanupAndExit; + } + + State = AX_STATE_EXTRACT_DATA; + TotalBytesWritten = 0; + FoundTable = 1; + continue; + + case AX_STATE_EXTRACT_DATA: + + /* Empty line or non-data line terminates the data */ + + if ((LineBuffer[0] == '\n') || + (LineBuffer[0] != ' ')) + { + fclose (OutputFile); + OutputFile = NULL; + State = AX_STATE_FIND_HEADER; + + printf ("Acpi table [%4.4s] - %u bytes written to %s\n", + ThisSignature, (unsigned int) TotalBytesWritten, Filename); + continue; + } + + /* Convert the ascii data (one line of text) to binary */ + + BytesConverted = AxConvertLine (LineBuffer, Data); + + /* Write the binary data */ + + BytesWritten = fwrite (Data, 1, BytesConverted, OutputFile); + if (BytesWritten != BytesConverted) + { + printf ("Write error on %s\n", Filename); + fclose (OutputFile); + OutputFile = NULL; + Status = -1; + goto CleanupAndExit; + } + + TotalBytesWritten += BytesConverted; + continue; + + default: + Status = -1; + goto CleanupAndExit; + } + } + + if (!FoundTable) + { + printf ("Table %s was not found in %s\n", Signature, InputPathname); + } + + +CleanupAndExit: + + if (OutputFile) + { + fclose (OutputFile); + if (State == AX_STATE_EXTRACT_DATA) + { + /* Received an EOF while extracting data */ + + printf ("Acpi table [%4.4s] - %u bytes written to %s\n", + ThisSignature, (unsigned int) TotalBytesWritten, Filename); + } + } + + fclose (InputFile); + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AxListTables + * + * PARAMETERS: InputPathname - Filename for acpidump file + * + * RETURN: Status + * + * DESCRIPTION: Display info for all ACPI tables found in input. Does not + * perform an actual extraction of the tables. + * + ******************************************************************************/ + +int +AxListTables ( + char *InputPathname) +{ + FILE *InputFile; + size_t HeaderSize; + unsigned char Header[48]; + int TableCount = 0; + ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header; + + + /* Open input in text mode, output is in binary mode */ + + InputFile = fopen (InputPathname, "rt"); + if (!InputFile) + { + printf ("Could not open %s\n", InputPathname); + return (-1); + } + + /* Dump the headers for all tables found in the input file */ + + printf ("\nSignature Length Revision OemId OemTableId" + " OemRevision CompilerId CompilerRevision\n\n"); + + while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) + { + /* Ignore empty lines and lines that start with a space */ + + if ((LineBuffer[0] == ' ') || + (LineBuffer[0] == '\n')) + { + continue; + } + + /* Get the 36 byte header and display the fields */ + + HeaderSize = AxGetTableHeader (InputFile, Header); + if (HeaderSize < 16) + { + continue; + } + + /* RSDP has an oddball signature and header */ + + if (!strncmp (TableHeader->Signature, "RSD PTR ", 8)) + { + AxCheckAscii ((char *) &Header[9], 6); + printf ("%8.4s \"%6.6s\"\n", "RSDP", &Header[9]); + TableCount++; + continue; + } + + /* Minimum size for table with standard header */ + + if (HeaderSize < sizeof (ACPI_TABLE_HEADER)) + { + continue; + } + + /* Signature and Table length */ + + TableCount++; + printf ("%8.4s % 7d", TableHeader->Signature, TableHeader->Length); + + /* FACS has only signature and length */ + + if (!strncmp (TableHeader->Signature, "FACS", 4)) + { + printf ("\n"); + continue; + } + + /* OEM IDs and Compiler IDs */ + + AxCheckAscii (TableHeader->OemId, 6); + AxCheckAscii (TableHeader->OemTableId, 8); + AxCheckAscii (TableHeader->AslCompilerId, 4); + + printf (" %2.2X \"%6.6s\" \"%8.8s\" %8.8X \"%4.4s\" %8.8X\n", + TableHeader->Revision, TableHeader->OemId, + TableHeader->OemTableId, TableHeader->OemRevision, + TableHeader->AslCompilerId, TableHeader->AslCompilerRevision); + } + + printf ("\nFound %u ACPI tables\n", TableCount); + fclose (InputFile); + return (0); +} diff --git a/source/tools/acpixtract/axmain.c b/source/tools/acpixtract/axmain.c new file mode 100644 index 000000000000..5d275802916e --- /dev/null +++ b/source/tools/acpixtract/axmain.c @@ -0,0 +1,191 @@ +/****************************************************************************** + * + * Module Name: axmain - main module for acpixtract utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" +#include + + +static void +DisplayUsage ( + void); + +int +AxExtractTables ( + char *InputPathname, + char *Signature, + unsigned int MinimumInstances); + +int +AxListTables ( + char *InputPathname); + + +/* Options */ + +#define AX_EXTRACT_ALL 0 +#define AX_LIST_ALL 1 +#define AX_EXTRACT_SIGNATURE 2 +#define AX_EXTRACT_AML_TABLES 3 + +static int AxAction = AX_EXTRACT_AML_TABLES; /* DSDT & SSDTs */ + +#define AX_OPTIONAL_TABLES 0 +#define AX_REQUIRED_TABLE 1 + + +/****************************************************************************** + * + * FUNCTION: DisplayUsage + * + * DESCRIPTION: Usage message + * + ******************************************************************************/ + +static void +DisplayUsage ( + void) +{ + + ACPI_USAGE_HEADER ("acpixtract [option] "); + + ACPI_OPTION ("-a", "Extract all tables, not just DSDT/SSDT"); + ACPI_OPTION ("-l", "List table summaries, do not extract"); + ACPI_OPTION ("-s ", "Extract all tables with "); + + printf ("\nExtract binary ACPI tables from text acpidump output\n"); + printf ("Default invocation extracts the DSDT and all SSDTs\n"); +} + + +/****************************************************************************** + * + * FUNCTION: main + * + * DESCRIPTION: C main function + * + ******************************************************************************/ + +int +main ( + int argc, + char *argv[]) +{ + char *Filename; + int Status; + int j; + + + printf (ACPI_COMMON_SIGNON ("ACPI Binary Table Extraction Utility")); + + if (argc < 2) + { + DisplayUsage (); + return (0); + } + + /* Command line options */ + + while ((j = AcpiGetopt (argc, argv, "ahls:")) != EOF) switch (j) + { + case 'a': + AxAction = AX_EXTRACT_ALL; /* Extract all tables found */ + break; + + case 'l': + AxAction = AX_LIST_ALL; /* List tables only, do not extract */ + break; + + case 's': + AxAction = AX_EXTRACT_SIGNATURE; /* Extract only tables with this sig */ + break; + + case 'h': + default: + DisplayUsage (); + return (0); + } + + /* Input filename is always required */ + + Filename = argv[AcpiGbl_Optind]; + if (!Filename) + { + printf ("Missing required input filename\n"); + return (-1); + } + + /* Perform requested action */ + + switch (AxAction) + { + case AX_EXTRACT_ALL: + Status = AxExtractTables (Filename, NULL, AX_OPTIONAL_TABLES); + break; + + case AX_LIST_ALL: + Status = AxListTables (Filename); + break; + + case AX_EXTRACT_SIGNATURE: + Status = AxExtractTables (Filename, AcpiGbl_Optarg, AX_REQUIRED_TABLE); + break; + + default: + /* + * Default output is the DSDT and all SSDTs. One DSDT is required, + * any SSDTs are optional. + */ + Status = AxExtractTables (Filename, "DSDT", AX_REQUIRED_TABLE); + if (Status) + { + return (Status); + } + + Status = AxExtractTables (Filename, "SSDT", AX_OPTIONAL_TABLES); + break; + } + + return (Status); +} diff --git a/source/tools/examples/examples.c b/source/tools/examples/examples.c new file mode 100644 index 000000000000..570683e29311 --- /dev/null +++ b/source/tools/examples/examples.c @@ -0,0 +1,449 @@ +/****************************************************************************** + * + * Module Name: examples - Example ACPICA code + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* Set the ACPICA application type for use in include/platform/acenv.h */ + +#ifndef WIN32 +#define WIN32 +#endif + +#define ACPI_DEBUG_OUTPUT + +/* ACPICA public headers */ + +#include "acpi.h" + +#define _COMPONENT ACPI_EXAMPLE + ACPI_MODULE_NAME ("examples") + + +/****************************************************************************** + * + * ACPICA Example Code + * + * This module contains examples of how the host OS should interface to the + * ACPICA subsystem. + * + * 1) How to use the platform/acenv.h file and how to set configuration + * options. + * + * 2) main - using the debug output mechanism and the error/warning output + * macros. + * + * 3) Two examples of the ACPICA initialization sequence. The first is a + * initialization with no "early" ACPI table access. The second shows + * how to use ACPICA to obtain the tables very early during kernel + * initialization, even before dynamic memory is available. + * + * 4) How to invoke a control method, including argument setup and how to + * access the return value. + * + *****************************************************************************/ + +/* Standard Clib headers */ + +#include +#include + +/* Local Prototypes */ + +ACPI_STATUS +InitializeFullAcpi (void); + +ACPI_STATUS +InstallHandlers (void); + +void +ExecuteOSI (void); + + +/****************************************************************************** + * + * FUNCTION: main + * + * PARAMETERS: argc, argv + * + * RETURN: Status + * + * DESCRIPTION: Main routine. Shows the use of the various output macros, as + * well as the use of the debug layer/level globals. + * + *****************************************************************************/ + +int ACPI_SYSTEM_XFACE +main ( + int argc, + char **argv) +{ + ACPI_FUNCTION_NAME (Examples-main); + + + InitializeFullAcpi (); + + /* Enable debug output, example debug print */ + + AcpiDbgLayer = ACPI_EXAMPLE; + AcpiDbgLevel = ACPI_LV_INIT; + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Example Debug output\n")); + + /* Example warning and error output */ + + ACPI_INFO ((AE_INFO, "ACPICA example info message")); + ACPI_WARNING ((AE_INFO, "ACPICA example warning message")); + ACPI_ERROR ((AE_INFO, "ACPICA example error message")); + ACPI_EXCEPTION ((AE_INFO, AE_AML_OPERAND_TYPE, "Example exception message")); + + ExecuteOSI (); + return (0); +} + + +/****************************************************************************** + * + * Example ACPICA initialization code. This shows a full initialization with + * no early ACPI table access. + * + *****************************************************************************/ + +ACPI_STATUS +InitializeFullAcpi (void) +{ + ACPI_STATUS Status; + + + /* Initialize the ACPICA subsystem */ + + Status = AcpiInitializeSubsystem (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA")); + return (Status); + } + + /* Initialize the ACPICA Table Manager and get all ACPI tables */ + + Status = AcpiInitializeTables (NULL, 16, FALSE); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager")); + return (Status); + } + + /* Create the ACPI namespace from ACPI tables */ + + Status = AcpiLoadTables (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables")); + return (Status); + } + + /* Install local handlers */ + + Status = InstallHandlers (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); + return (Status); + } + + /* Initialize the ACPI hardware */ + + Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA")); + return (Status); + } + + /* Complete the ACPI namespace object initialization */ + + Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects")); + return (Status); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * Example ACPICA initialization code with early ACPI table access. This shows + * an initialization that requires early access to ACPI tables (before + * kernel dynamic memory is available) + * + *****************************************************************************/ + +/* + * The purpose of this static table array is to avoid the use of kernel + * dynamic memory which may not be available during early ACPI table + * access. + */ +#define ACPI_MAX_INIT_TABLES 16 +static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES]; + + +/* + * This function would be called early in kernel initialization. After this + * is called, all ACPI tables are available to the host. + */ +ACPI_STATUS +InitializeAcpiTables (void) +{ + ACPI_STATUS Status; + + + /* Initialize the ACPICA Table Manager and get all ACPI tables */ + + Status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, TRUE); + return (Status); +} + + +/* + * This function would be called after the kernel is initialized and + * dynamic/virtual memory is available. It completes the initialization of + * the ACPICA subsystem. + */ +ACPI_STATUS +InitializeAcpi (void) +{ + ACPI_STATUS Status; + + + /* Initialize the ACPICA subsystem */ + + Status = AcpiInitializeSubsystem (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Copy the root table list to dynamic memory */ + + Status = AcpiReallocateRootTable (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Create the ACPI namespace from ACPI tables */ + + Status = AcpiLoadTables (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Install local handlers */ + + Status = InstallHandlers (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); + return (Status); + } + + /* Initialize the ACPI hardware */ + + Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Complete the ACPI namespace object initialization */ + + Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * Example ACPICA handler and handler installation + * + *****************************************************************************/ + +void +NotifyHandler ( + ACPI_HANDLE Device, + UINT32 Value, + void *Context) +{ + + ACPI_INFO ((AE_INFO, "Received a notify 0x%X", Value)); +} + + +ACPI_STATUS +InstallHandlers (void) +{ + ACPI_STATUS Status; + + + /* Install global notify handler */ + + Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, + NotifyHandler, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler")); + return (Status); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * Example control method execution. + * + * _OSI is a predefined method that is implemented internally within ACPICA. + * + * Shows the following elements: + * + * 1) How to setup a control method argument and argument list + * 2) How to setup the return value object + * 3) How to invoke AcpiEvaluateObject + * 4) How to check the returned ACPI_STATUS + * 5) How to analyze the return value + * + *****************************************************************************/ + +void +ExecuteOSI (void) +{ + ACPI_STATUS Status; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg[1]; + ACPI_BUFFER ReturnValue; + ACPI_OBJECT *Object; + + + ACPI_INFO ((AE_INFO, "Executing OSI method")); + + /* Setup input argument */ + + ArgList.Count = 1; + ArgList.Pointer = Arg; + + Arg[0].Type = ACPI_TYPE_STRING; + Arg[0].String.Pointer = "Windows 2001"; + Arg[0].String.Length = strlen (Arg[0].String.Pointer); + + /* Ask ACPICA to allocate space for the return object */ + + ReturnValue.Length = ACPI_ALLOCATE_BUFFER; + + Status = AcpiEvaluateObject (NULL, "\\_OSI", &ArgList, &ReturnValue); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While executing _OSI")); + return; + } + + /* Ensure that the return object is large enough */ + + if (ReturnValue.Length < sizeof (ACPI_OBJECT)) + { + AcpiOsPrintf ("Return value from _OSI method too small, %.8X\n", + ReturnValue.Length); + return; + } + + /* Expect an integer return value from execution of _OSI */ + + Object = ReturnValue.Pointer; + if (Object->Type != ACPI_TYPE_INTEGER) + { + AcpiOsPrintf ("Invalid return type from _OSI, %.2X\n", Object->Type); + } + + ACPI_INFO ((AE_INFO, "_OSI returned 0x%8.8X", (UINT32) Object->Integer.Value)); + AcpiOsFree (Object); + return; +} + + +/****************************************************************************** + * + * OSL support (only needed to link to the windows OSL) + * + *****************************************************************************/ + +FILE *AcpiGbl_DebugFile; + +ACPI_PHYSICAL_ADDRESS +AeLocalGetRootPointer ( + void) +{ + + return (0); +} + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (0xFFFF); +} + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + return (AE_SUPPORT); +} -- cgit v1.2.3